Containable ビヘイビアをもっと理解したいと思いましたの。
なんとなくわかるのですけれども、実際に体験したいと思いましたので、自分人のためのチュートリアルを本投稿で実施したいと存じます♪
Containable ビヘイビアでできることまとめ
- 深い階層のデータを取得できるのではなく、取得したいモデル、モデルのカラムのデータを指定することができる。
- 逆に、モデルを記述しないことで取得したくないデータを除いて取得することができる。
- 単一のモデルに設定したアソシエーションのデータだけではなく、アソシエーションをたどってつながりのあるモデルのデータを取得することができる。
試した環境
以下の環境で、予め CakePHP をインストールしておきました。
- CakePHP 2.5.4
- PHP 5.4.32
- Apache/2.2.15
- MySQL 5.5.39
- CentOS 6
- VirtualBox 4.3.16。仮想マシンの IP アドレスは 192.168.56.112
- CakePHP は /var/www/html/cake2/ に Composer でインストール。データベースへも接続済み。
- CakePHP へは http://192.168.56.112/cake2/ でウェブブラウザからアクセス
データベース関連図
準備1.で説明しておりますが、SQL は本投稿の最後に掲載しております。
ER 図は次のようになりました。カラムは Containable ビヘイビアページから読み取れるもの以外は適当に設定しております。
users テーブルを起点として、最大4テーブルのリレーションがございます。こんなにも深いリレーションのデータを SQL を直に書かずに本当に取得できるのか?気になりますわね。
準備1.MySQL にテーブルとレコードをインポート
本投稿末尾の「テーブルとデータの SQL」をデータベースへインポートします。Containable ビヘイビアページの Containing deeper associations の章の後半部分に出てくる9つのモデルに対応するテーブル、users、profiles、accounts、account_summaries、posts、post_attachments、post_attachment_histories、history_notes、tags が生成され、それぞれのテーブルにレコードが挿入されます。
準備2.bake でプログラムソースを自動生成
CakePHP をインストールした場所へ移動します。
cd /var/www/html/cake2/
移動したら、bake コマンドで ソースを自動生成します。オプションに all をつけて、MVC すべて作成します。
Console/cake bake all
データベースの9つのテーブルすべて bake します。9回コマンドを繰り返さなくてはならないので、少し面倒ですが、頑張りましょう。
生成された Model/User.php などを見ますと、当初の予定では User hasOne Profile などとなっていることを期待しておりました。
しかし、bake は hasOne と hasMany は自動で判定しないようです。User hasMany Profile となっていました。Containable ビヘイビアの動きを確認するにはどちらでも問題ありませんでしたので、本当は直したほうがよいでしょうけれども(開発を進めるのであれば絶対に!)、このままとしました。
結局今回の Containable ビヘイビアの確認で、各モデルに設定されたリレーションは次のようになりました。
- User
- hasMany Account, Post, Profile
- Profile
- belongsTo User
- Account
- belongsTo User
- AccountSummary
- belongsTo Account
- Post
- belongsTo User
- hasMany PostAttachment, Tag
- PostAttachment
- belongsTo Post
- hasMany PostAttachmentHistory
- PostAttachmentHistory
- belongsTo PostAttachment
- hasMany HistoryNote
- HistoryNote
- belongsTo PostAttachmentHistory
- Tag
- belongsTo Post
ちなみに、事前に同名のファイルがある場合、bake で生成されたソースが上書きしてしまいますので要注意ですし、逆にテーブルの内容を変更した場合に bake でその内容を反映することもできます。
ただ、bake の上書きで VIEW がなぜか反映されないことがあったため、一旦該当ファイルを削除してから bake し直すことで対処しました。臨機応変さも必要ですね。
すべてのテーブルに対して bake all が完了したら、「http://192.168.56.112/cake2/users/」などテーブルに対応した URL にアクセスしてみて、bake が予定通り行われてインポートしたレコードも表示されるか確認しましょう。
準備3.Containable ビヘイビア確認用のコントロール、ビューを作成
bake したソースには手を加えずに、新しくソースを作成してそこで Containable ビヘイビアの動きを確認していきます。
まずはコントローラーです。
vim Controller/ContainersController.php
Containable ビヘイビアを使用せず、まずは単純に find でデータが取得できるのかを確認するソースになっています。
また、このコントローラーから使用するモデルとして User を指定します。
<?php App::uses('AppController', 'Controller'); /** * Containers Controller * * @property Container $Container * @property PaginatorComponent $Paginator */ class ContainersController extends AppController { public $uses = array('User'); /** * index method * * @return void */ public function index() { $data = $this->User->find('all'); debug($data); } }
つづいて、ビューを作成します。これは空のファイルで問題ありません。コントローラーで debug 関数でウェブブラウザに表示させているためです。ただ、ビューがない場合だとエラーが表示されますのでそれでもなんの問題もありませんが気持ち悪いのです。エラーを消すためだけに、空のビューファイルを作成しています。
View/Containers/index.ctp
これで準備が整いました。それでは Containable ビヘイビアの動きを確認していきましょう♪
確認1.Containable ビヘイビアを使わない場合の動き
http://192.168.56.112/cake2/containers/ にアクセスします。
Contaiable ビヘイビアを使用しない場合、User が取得できるのはもちろんとして配列の同じ次元の位置で Account、Post、Profile が取得されました。
つまり、User モデルに記述したアソシエーションのモデルを自動的に取ってきてくれます。
確認2.Containable ビヘイビアをオンにしただけだと。。。
Contaiable ビヘイビアをオンにするには2通りの方法があります。どちらかを一方、書けばよいです。
1つが、Users モデルで読み込む方法。
public $actsAs = array('Containable');
もう一つが、コントローラーでモデルを指定してオンにする方法ですの。
$this->User->Behaviors->load('Containable');
本投稿では、コントローラーのソースだけを修正すれば済む、後者の方法を取り扱います。
vim Controller/ContainersController.php
index アクションを編集いたしました。
public function index() { // モデルでなくとも、コントローラーでもビヘイビアを有効にできる $this->User->Behaviors->load('Containable'); $data = $this->User->find('all'); debug($data); }
Contaiable ビヘイビアをオンにすると、取得できるデータはどのように変わるかしら?
答えは、オンにしただけでは取得データに変わりがありません。User と、リレーションのある Account、Post、Profile が取得されました。
確認3.Containable ビヘイビアを false にすると
Contaiable ビヘイビアは false を設定できます。確認1.確認2.と同じデータがとれるのかしら?と思ったのですけれども全然違いましたの。
public function index() { $this->User->Behaviors->load('Containable'); $params = array('contain' => false); $data = $this->User->find('all', $params); debug($data); }
なんと User モデルのデータのみを取得するようになりました。
より深い階層のデータを取るときに使うものだと思っていましたけれども、逆に Containable ビヘイビアを使うことによってアソシエーションを断ち切って単独のデータを取得するためにも使える、ということですの!
便利ですわね♪
同じことは次の指定でも可能です。こちらは recursive の設定ですので Containable ビヘイビアとはちょっと違いますけれどもね。
public function index() { $this->User->recursive = -1; $data = $this->User->find('all'); debug($data); }
確認4.Containable ビヘイビアでモデルを指定すると。。。
Contaiable ビヘイビアを使わない、またはオンにしただけですと User と、リレーションのある Account、Post、Profile が取得されました。
では、Contaiable ビヘイビアとして Account を指定するとどうなるでしょうか?
public function index() { $this->User->Behaviors->load('Containable'); $params = array('contain' => 'Account'); $data = $this->User->find('all', $params); debug($data); }
そう、User と Account のデータが取得できます。User にアソシエーションのあった残りの Post、Profile のデータは除外されています。
Contaiable ビヘイビアは指定した欲しいものだけ取得できるの(除外したいものは指定しない)が便利ですわね♪
確認5.Containable ビヘイビアでモデルのフィールドまで指定すると。。。
先ほどは Account を指定して、User プラス Account のデータを取得しました。
次は Account モデルの url フィールドを指定するとどうなるでしょうか?
public function index() { $this->User->Behaviors->load('Containable'); $params = array('contain' => 'Account.url'); $data = $this->User->find('all', $params); debug($data); }
User の全データと、Account の url と user_id が取得されました。
指定していない user_id も取れてしまうのは、User のどのレコードと紐付いているかを保つための仕様なのだと思います。
確認6.Containable ビヘイビアで検索条件を設定すると。。。
Account モデルの url フィールドに検索条件を指定しますとどうなるでしょうか?
public function index() { $this->User->Behaviors->load('Containable'); $params = array('contain' => 'Account.url="http://example.com/user2/"'); $data = $this->User->find('all', $params); debug($data); }
条件にヒットした Account データと、それに紐づく User データを取得できました♪条件を満たさなかった Account データは取得されておりません。
ただし、User モデルは全てのデータが取得されました。これは、検索条件にヒットしなかった Account レコードに紐付いた User のデータも取得された、という意味です。
この点は注意が必要と思います。
また、Account モデルからは全フィールドが取得されました。url フィールドで条件を指定したからといって、取得データが url フィールドのみにはならない、ということですわね♪
ただ、検索条件を指定したモデルでフィールドも指定したい場合はどうすればよいのかしら?fields オプションを指定するのかしら?
確認7.Containable ビヘイビアで4つ離れたモデルのデータを取得できました。。。
最後の確認です!ER 図に描いた、全てのモデルのデータを全て1回の find で取得します。Containalbe ビヘイビアページにあった、深いアソシエーションのデータを取ります。
- User モデルからは username フィールドを取得
- PostAttachment モデルからは id と name フィールドを取得
- HistoryNote モデルからは id と note フィールドを取得
- Tag モデルで条件 ‘Tag.name LIKE’ => ‘%1%’ を指定
public function index() { $this->User->Behaviors->load('Containable'); $params = array( 'fields' => array( 'username' ), 'contain' => array( 'Profile', 'Account' => array( 'AccountSummary' ), 'Post' => array( 'PostAttachment' => array( 'fields' => array( 'id', 'name' ), 'PostAttachmentHistory' => array( 'HistoryNote' => array( 'fields' => array( 'id', 'note' ) ) ) ), 'Tag' => array( 'conditions' => array( 'Tag.name LIKE' => '%1%' ) ) ) ) ); $data = $this->User->find('all', $params); debug($data); }
指定した通りにデータを取得することができました。長く、収めることが難しいので、画像ではなくテキストで取得データを貼り付けます。
array( (int) 0 => array( 'User' => array( 'username' => 'user1name', 'id' => '1' ), 'Account' => array( (int) 0 => array( 'id' => '1', 'user_id' => '1', 'email' => 'user1@example.com', 'url' => 'http://example.com/user1/', 'status' => '1', 'created' => '2014-09-12 18:41:22', 'modified' => '2014-09-12 18:41:22', 'AccountSummary' => array( (int) 0 => array( 'id' => '1', 'account_id' => '1', 'first_name' => 'Tom', 'last_name' => 'Cat', 'color' => 'red', 'level' => '1', 'description' => 'user1 Description', 'created' => '2014-09-12 18:43:19', 'modified' => '2014-09-12 18:43:19' ) ) ) ), 'Post' => array( (int) 0 => array( 'id' => '1', 'user_id' => '1', 'title' => 'post1', 'content' => 'post1 content', 'created' => '2014-09-12 18:46:48', 'modified' => '2014-09-12 18:46:48', 'PostAttachment' => array( (int) 0 => array( 'id' => '1', 'name' => 'post1attachmentname', 'post_id' => '1', 'PostAttachmentHistory' => array( (int) 0 => array( 'id' => '1', 'post_attachment_id' => '1', 'histroy' => 'post1history', 'created' => '2014-09-12 18:51:56', 'modified' => '2014-09-12 18:51:56', 'HistoryNote' => array( (int) 0 => array( 'id' => '1', 'note' => 'post1 history note1', 'post_attachment_history_id' => '1' ), (int) 1 => array( 'id' => '2', 'note' => 'post1 history note2', 'post_attachment_history_id' => '1' ), (int) 2 => array( 'id' => '3', 'note' => 'post1 history note3', 'post_attachment_history_id' => '1' ) ) ) ) ) ), 'Tag' => array( (int) 0 => array( 'id' => '1', 'post_id' => '1', 'name' => 'tag1', 'created' => '2014-09-12 18:47:02', 'modified' => '2014-09-12 18:47:02' ) ) ) ), 'Profile' => array( (int) 0 => array( 'id' => '1', 'user_id' => '1', 'catch_phrase' => 'user1 Catch Phrase', 'self_introduction' => 'user1 Self Introduction', 'created' => '2014-09-12 18:38:26', 'modified' => '2014-09-12 18:38:26' ) ) ), (int) 1 => array( 'User' => array( 'username' => 'user2name', 'id' => '2' ), 'Account' => array( (int) 0 => array( 'id' => '2', 'user_id' => '2', 'email' => 'user2@example.com', 'url' => 'http://example.com/user2/', 'status' => '2', 'created' => '2014-09-12 18:41:47', 'modified' => '2014-09-12 18:41:47', 'AccountSummary' => array( (int) 0 => array( 'id' => '2', 'account_id' => '2', 'first_name' => 'John', 'last_name' => 'Dog', 'color' => 'blue', 'level' => '2', 'description' => 'user2 Description', 'created' => '2014-09-12 18:43:57', 'modified' => '2014-09-12 18:43:57' ) ) ) ), 'Post' => array( (int) 0 => array( 'id' => '2', 'user_id' => '2', 'title' => 'post2', 'content' => 'post2 content', 'created' => '2014-09-12 18:56:19', 'modified' => '2014-09-12 18:56:19', 'PostAttachment' => array( (int) 0 => array( 'id' => '2', 'name' => 'post2attachmentname', 'post_id' => '2', 'PostAttachmentHistory' => array( (int) 0 => array( 'id' => '2', 'post_attachment_id' => '2', 'histroy' => 'post2history', 'created' => '2014-09-12 19:07:25', 'modified' => '2014-09-12 19:08:11', 'HistoryNote' => array( (int) 0 => array( 'id' => '4', 'note' => 'post2 history note1', 'post_attachment_history_id' => '2' ) ) ) ) ) ), 'Tag' => array() ) ), 'Profile' => array( (int) 0 => array( 'id' => '2', 'user_id' => '2', 'catch_phrase' => 'user2 Catch Phrase', 'self_introduction' => 'user2 Self Introduction', 'created' => '2014-09-12 18:39:41', 'modified' => '2014-09-12 18:39:41' ) ) ) )
おわりに
今回の確認で、一番時間がかかったのは、Containable の書き方、、、ではなく、テーブルのフィールド決めて ER 図を描くところでしたの><。
AccountSummary テーブルってなんのためにあるのかしら?どんあフィールドを作るべきかさっぱりわかりませんの><。Post テーブルと Tag テーブルは HABTAM にするべきと存じますけれども><。。。などとギャーギャー過ごしておりましたら、あっという間に時間が経ってしまいました。
実際のアプリではありませんのであまり悩まずテキトーでよいですのにね><。
以上です。
テーブルとデータの SQL
コピーして「cake_containable.sql」などの sql ファイルにして MySQL にインポートすればすぐに本投稿の内容を確認することができます。
-- phpMyAdmin SQL Dump -- version 4.2.8 -- http://www.phpmyadmin.net -- -- Host: localhost -- Generation Time: 2014 年 9 月 12 日 19:13 -- サーバのバージョン: 5.5.39 -- PHP Version: 5.4.32 SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET time_zone = "+00:00"; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; -- -- Database: `cake2db` -- -- -------------------------------------------------------- -- -- テーブルの構造 `accounts` -- CREATE TABLE IF NOT EXISTS `accounts` ( `id` int(11) NOT NULL, `user_id` int(11) NOT NULL, `email` varchar(100) NOT NULL, `url` varchar(100) NOT NULL, `status` int(11) NOT NULL, `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- -- テーブルのデータのダンプ `accounts` -- INSERT INTO `accounts` (`id`, `user_id`, `email`, `url`, `status`, `created`, `modified`) VALUES (1, 1, 'user1@example.com', 'http://example.com/user1/', 1, '2014-09-12 18:41:22', '2014-09-12 18:41:22'), (2, 2, 'user2@example.com', 'http://example.com/user2/', 2, '2014-09-12 18:41:47', '2014-09-12 18:41:47'); -- -------------------------------------------------------- -- -- テーブルの構造 `account_summaries` -- CREATE TABLE IF NOT EXISTS `account_summaries` ( `id` int(11) NOT NULL, `account_id` int(11) NOT NULL, `first_name` varchar(45) DEFAULT NULL, `last_name` varchar(45) DEFAULT NULL, `color` varchar(45) DEFAULT NULL, `level` int(11) DEFAULT NULL, `description` text, `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- -- テーブルのデータのダンプ `account_summaries` -- INSERT INTO `account_summaries` (`id`, `account_id`, `first_name`, `last_name`, `color`, `level`, `description`, `created`, `modified`) VALUES (1, 1, 'Tom', 'Cat', 'red', 1, 'user1\r\nDescription', '2014-09-12 18:43:19', '2014-09-12 18:43:19'), (2, 2, 'John', 'Dog', 'blue', 2, 'user2\r\nDescription', '2014-09-12 18:43:57', '2014-09-12 18:43:57'); -- -------------------------------------------------------- -- -- テーブルの構造 `history_notes` -- CREATE TABLE IF NOT EXISTS `history_notes` ( `id` int(11) NOT NULL, `post_attachment_history_id` int(11) NOT NULL, `note` text NOT NULL, `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; -- -- テーブルのデータのダンプ `history_notes` -- INSERT INTO `history_notes` (`id`, `post_attachment_history_id`, `note`, `created`, `modified`) VALUES (1, 1, 'post1\r\nhistory\r\nnote1', '2014-09-12 18:53:32', '2014-09-12 19:10:25'), (2, 1, 'post1\r\nhistory\r\nnote2', '2014-09-12 19:10:19', '2014-09-12 19:10:19'), (3, 1, 'post1\r\nhistory\r\nnote3', '2014-09-12 19:10:46', '2014-09-12 19:10:46'), (4, 2, 'post2\r\nhistory\r\nnote1', '2014-09-12 19:11:05', '2014-09-12 19:11:05'); -- -------------------------------------------------------- -- -- テーブルの構造 `posts` -- CREATE TABLE IF NOT EXISTS `posts` ( `id` int(11) NOT NULL, `user_id` int(11) NOT NULL, `title` text NOT NULL, `content` longtext NOT NULL, `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- -- テーブルのデータのダンプ `posts` -- INSERT INTO `posts` (`id`, `user_id`, `title`, `content`, `created`, `modified`) VALUES (1, 1, 'post1', 'post1\r\ncontent', '2014-09-12 18:46:48', '2014-09-12 18:46:48'), (2, 2, 'post2', 'post2\r\ncontent', '2014-09-12 18:56:19', '2014-09-12 18:56:19'); -- -------------------------------------------------------- -- -- テーブルの構造 `post_attachments` -- CREATE TABLE IF NOT EXISTS `post_attachments` ( `id` int(11) NOT NULL, `post_id` int(11) NOT NULL, `name` varchar(45) NOT NULL, `pinged` text, `password` varchar(20) DEFAULT NULL, `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- -- テーブルのデータのダンプ `post_attachments` -- INSERT INTO `post_attachments` (`id`, `post_id`, `name`, `pinged`, `password`, `created`, `modified`) VALUES (1, 1, 'post1attachmentname', 'post1pinged', 'post1pass', '2014-09-12 18:50:50', '2014-09-12 18:50:50'), (2, 2, 'post2attachmentname', 'post2\r\nattachment\r\nname\r\npinged', 'post2attachmentpass', '2014-09-12 19:03:06', '2014-09-12 19:08:59'); -- -------------------------------------------------------- -- -- テーブルの構造 `post_attachment_histories` -- CREATE TABLE IF NOT EXISTS `post_attachment_histories` ( `id` int(11) NOT NULL, `post_attachment_id` int(11) NOT NULL, `histroy` varchar(45) DEFAULT NULL, `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- -- テーブルのデータのダンプ `post_attachment_histories` -- INSERT INTO `post_attachment_histories` (`id`, `post_attachment_id`, `histroy`, `created`, `modified`) VALUES (1, 1, 'post1history', '2014-09-12 18:51:56', '2014-09-12 18:51:56'), (2, 2, 'post2history', '2014-09-12 19:07:25', '2014-09-12 19:08:11'); -- -------------------------------------------------------- -- -- テーブルの構造 `profiles` -- CREATE TABLE IF NOT EXISTS `profiles` ( `id` int(11) NOT NULL, `user_id` int(11) NOT NULL, `catch_phrase` varchar(255) NOT NULL, `self_introduction` text, `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- -- テーブルのデータのダンプ `profiles` -- INSERT INTO `profiles` (`id`, `user_id`, `catch_phrase`, `self_introduction`, `created`, `modified`) VALUES (1, 1, 'user1 Catch Phrase', 'user1\r\nSelf Introduction', '2014-09-12 18:38:26', '2014-09-12 18:38:26'), (2, 2, 'user2 Catch Phrase', 'user2\r\nSelf\r\nIntroduction', '2014-09-12 18:39:41', '2014-09-12 18:39:41'); -- -------------------------------------------------------- -- -- テーブルの構造 `tags` -- CREATE TABLE IF NOT EXISTS `tags` ( `id` int(11) NOT NULL, `post_id` int(11) NOT NULL, `name` varchar(45) NOT NULL, `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; -- -- テーブルのデータのダンプ `tags` -- INSERT INTO `tags` (`id`, `post_id`, `name`, `created`, `modified`) VALUES (1, 1, 'tag1', '2014-09-12 18:47:02', '2014-09-12 18:47:02'), (2, 1, 'tag2', '2014-09-12 18:47:10', '2014-09-12 18:47:10'), (3, 1, 'tag3', '2014-09-12 18:47:16', '2014-09-12 18:47:16'), (4, 2, 'tag4', '2014-09-12 19:00:57', '2014-09-12 19:00:57'); -- -------------------------------------------------------- -- -- テーブルの構造 `users` -- CREATE TABLE IF NOT EXISTS `users` ( `id` int(11) NOT NULL, `username` varchar(255) NOT NULL, `password` varchar(64) NOT NULL, `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- -- テーブルのデータのダンプ `users` -- INSERT INTO `users` (`id`, `username`, `password`, `created`, `modified`) VALUES (1, 'user1name', 'user1pass', '2014-09-12 18:34:10', '2014-09-12 18:34:10'), (2, 'user2name', 'user2pass', '2014-09-12 18:37:03', '2014-09-12 18:37:03'); -- -- Indexes for dumped tables -- -- -- Indexes for table `accounts` -- ALTER TABLE `accounts` ADD PRIMARY KEY (`id`); -- -- Indexes for table `account_summaries` -- ALTER TABLE `account_summaries` ADD PRIMARY KEY (`id`); -- -- Indexes for table `history_notes` -- ALTER TABLE `history_notes` ADD PRIMARY KEY (`id`); -- -- Indexes for table `posts` -- ALTER TABLE `posts` ADD PRIMARY KEY (`id`); -- -- Indexes for table `post_attachments` -- ALTER TABLE `post_attachments` ADD PRIMARY KEY (`id`); -- -- Indexes for table `post_attachment_histories` -- ALTER TABLE `post_attachment_histories` ADD PRIMARY KEY (`id`); -- -- Indexes for table `profiles` -- ALTER TABLE `profiles` ADD PRIMARY KEY (`id`); -- -- Indexes for table `tags` -- ALTER TABLE `tags` ADD PRIMARY KEY (`id`); -- -- Indexes for table `users` -- ALTER TABLE `users` ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `username_UNIQUE` (`username`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `accounts` -- ALTER TABLE `accounts` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3; -- -- AUTO_INCREMENT for table `account_summaries` -- ALTER TABLE `account_summaries` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3; -- -- AUTO_INCREMENT for table `history_notes` -- ALTER TABLE `history_notes` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=5; -- -- AUTO_INCREMENT for table `posts` -- ALTER TABLE `posts` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3; -- -- AUTO_INCREMENT for table `post_attachments` -- ALTER TABLE `post_attachments` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3; -- -- AUTO_INCREMENT for table `post_attachment_histories` -- ALTER TABLE `post_attachment_histories` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3; -- -- AUTO_INCREMENT for table `profiles` -- ALTER TABLE `profiles` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3; -- -- AUTO_INCREMENT for table `tags` -- ALTER TABLE `tags` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=5; -- -- AUTO_INCREMENT for table `users` -- ALTER TABLE `users` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;