//find()にQueryExpressionを使うサンプル
public function find() {
//絞り込んだ結果のエンティティ配列
$persons = [];
//リクエストの種別がPOSTであるなら
if ($this->request->is('post')) {
//添字の'find'とは、テンプレートの該当フォームのname属性に指定したもの
//テキストフォームの例: $this->Form->text( 'text1'←ここ )
//なお、data['find']やdata('find')はdeprecated
//getData('find')が現行バージョンでの推奨らしい
$find = $this->request->data['find'];
//最初にSELECT * FROM persons のクエリを作成する
//なお、条件を付加していく段階ではクエリは実行されない
//データが必要になった時、つまりテンプレートでのforeachで初めて実行される
//find('all')や、find()->all()などの場合はすぐに実行される
$query = $this->Persons->find();
//上のクエリに適合したクエリエクスプレッションを生成
$exp = $query->newExpr();
//絞込に使用するための無名関数を宣言
//第一引数にはクエリエクスプレッション、
//第二引数には、今回は名前が絞込の条件となるので、
//"まつもとゆきひろ, やくみつる"といったコンマ区切りの文字列を代入する
$fnc = function($exp, $f) {
return $exp
//名前がNULLでない
->isNotNull('name')
//メールアドレスがNULLでない
->isNotNull('mail')
//年齢が0より大きい
->gt('age',0)
//名前が第二引数で渡されたどれかに該当する
//なお、explode関数はコンマ区切りだった文字列を配列に変換している
->in('name', explode(',',$f));
};
//無名関数をwhere句に設定する
$persons = $query->where($fnc($exp,$find));
}
//クエリをテンプレートに渡すためにset()する
$this->set('persons', $persons);
$this->set('msg', null);
}
複数のテーブルのJOINした結果を表示
クエリビルダにおいて、innerJoinWith()やleftJoiinWith()でJOINしたものをテンプレートで表示するためには
$tenancy->_matchingData['Tenants']->stage
のように書きます。
もし不安な場合はdebugメソッドもしくは$tenancyのみで出力し確認します。
クエリビルダのcontain()で結合した場合は
$tenancy->tenant->stage
です。
グローバルにインストールしたcomposer.pharの場所
C:\ProgramData\ComposerSetup\bin内にある。
もしここにもない場合はEverything等のファイル検索ソフトを使う。
#1071 - 索引のキーが長すぎます。最大 767 バイトまでです。と出たとき
CREATE TABLE tags ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255), created DATETIME, modified DATETIME, UNIQUE KEY (title) );
このtitle属性は255文字までを格納する。
同じ文のタグを重複して登録することは許されないため、ユニークキーとして扱いたい。
しかし、例えば文字コードにutfmb4を設定しているとき、utfmb4は各文字4バイトで表現するので総バイト数は 4 * 255 = 1020Bとなり、 767バイトをゆうに超えてしまう。
解決策としては 各文字にかかるバイト数 * 最大文字数 < 767 となるようにSQLを変更する。
上記の場合では191文字が限界。そのため3行目が
title VARCHAR(191)
となる。
Unknown finder method とは
$bookmarks = $this->Bookmarks->find('tagged', [
テーブルのfindメソッドの第一引数が重要。
たとえば上記のようにBookmarks->find('tagged',のようになっているときは、
BookmarksTableクラスのfindTaggedメソッドを探しに行く。
ここで見つからないときUnknown finder method ("tagged")とエラーが出る。
見つかった時はfindTagged()に第二引数であるオプションを渡して結果をもらう。
ここから補足。
今回は、指定したタグが付いているブックマークの一覧を表示するためにタグ付きのブックマークを絞り込みたい。
そのためにはControllerはTableクラスに依頼し、絞り込んだ結果を返して貰いたい。
// タグ付きのブックマークを探すために BookmarksTable を使用
$bookmarks = $this->Bookmarks->find('tagged', [
'tags' => $tags
]);
これは、BookmarksControllerがBookmarksTableに依頼する。なぜならTableがDBとの通信を担当するから。
findTaggedメソッドに指定したタグを渡すことでBookmarksTableはブックマークを絞りこめるようになる。
さて、次はTableクラスの処理。
public function findTagged(Query $query, array $options)
{
まずここは、呼び出したクエリインスタンスと先程の第二引数(compact('tags'))が渡されることを意味する。
$bookmarks = $this->find()->select(['id', 'url', 'title', 'description']);
表示したい項目一覧を設定する。SELECT ID,URL, ...のような感じ
if (empty($options['tags'])) {
第二引数に何も渡されていなかったとき=タグが何も指定されていない時
$bookmarks->leftJoinWith('Tags')->where(['Tags.title IS' => null]);
タグがNULLの行を検索
} else {
$bookmarks->innerJoinWith('Tags')->where(['Tags.title IN ' => $options['tags']]);
指定したタグのどれかに合致する行を検索
}
return $bookmarks->group(['Bookmarks.id']);
IDでGROUP BYしたものを返却
}
protected function _setPassword($value)とは
結論はこれ。
[CakePHP3] Setter(セッター)とGetter(ゲッター)をざっくりと知る。 – gomokulog
以下補足。
C#にはプロパティという機能がある。
プロパティを実装すると、メンバ変数 x を持つクラスAがあるとき、a.x としても自動的にgetX()が呼び出されるというもの。つまりゲッタがメンバ変数としてふるまう。
これと似たようなノリでCakePHPでは、エンティティに値をセットするとき、
エンティティに_set{$変数名}というメソッドを作っていれば、自動でセッタが呼び出されるそうだ。
具体的には$entity->変数名 = 値; などを実行した時に_set{$変数名}というメソッドを探し、存在したら実行する。
逆に値をgetする時(テンプレート内など)は_get{$変数名}が探され呼び出されるらしい。