こんにちは!フリーランスの長野です。
findって使ってますか?
findはデータベースを検索してデータを取得する際に使われます。
この記事では、findについて
・findとは
・findの基本的な使い方
という基本的な内容から、
・findの応用的な使い方
など応用的な内容についても解説していきます。
今回はfindについて、使い方をわかりやすく解説します!
findとは
findとはエンティティを検索してデータを取得するためのメソッドです。
エンティティとはデータベースに用意されているテーブルのデータをPHPクラス用に抽象化したものです。
CakePHPでは、データベースに保存したり取り出したりしたデータは、エンティティのインスタンスになります。
したがって、findはデータベースのテーブルを検索してデータを取得する際に使用します。
findの基本的な使い方
findは下記のように記述して使用します。
findの記述方法:
find(‘all’, 連想配列);
第1引数には’all’や‘list’などを指定します。
・’all’ 全データを取得
・’list’ レコードのリストを取得
第2引数には連想配列で’limit’、‘conditions’などのオプションを設定します。
それではまずは第1引数に’all’や’list’などを指定する方法について確認していきましょう。
allで全データを取得する方法
findメソッドの第1引数に’all’を指定すると、全データを取得することができます。
サンプルコードで確認していきましょう。
なお、サンプルコードでは下記のSQLクエリで作成したテーブル「persons」を使用しています。
SQLクエリ:
CREATE TABLE persons ( id INTEGER PRIMARY KEY AUTO_INCREMENT, name TEXT NOT NULL, age INTEGER, mail TEXT );
personsテーブル:
id | name | age | |
---|---|---|---|
1 | Taro | 40 | taro@gmail.com |
2 | Jiro | 30 | jiro@gmail.com |
3 | Saburo | 25 | saburo@gmail.com |
4 | Hanako | 35 | hanako@gmail.com |
テーブル「persons」を作成後、bakeでmodelを作成しています。
bakeの実行例(linux):
bin/cake bake model persons
findメソッドの第1引数に‘all’を使用して全データを取得するソースコード「/src/Controller/PersonsController.php」は下記のとおりです。
URL「/persons/index」を指定した場合に、findメソッドで取得したデータを表示するように記述しています。
URL「/persons/index」のテンプレートは「/src/Template/Persons/index.ctp」で記述しています。
/src/Controller/PersonsController.php:
<?php namespace App\Controller; use App\Controller\AppController; class PersonsController extends AppController { public function index() { // Entity全ての取得 $this->set('persons', $this->Persons->find('all')); } }
/src/Template/Persons/index.ctp:
<div> <h3>List Persons</h3> <table> <thead> <tr> <th>ID</th> <th>NAME</th> <th>AGE</th> <th>MAIL</th> </tr> </thead> <tbody> <?php foreach ($persons as $person): ?> <tr> <td><?=$person->id ?></td> <td><?=h($person->name) ?></td> <td><?=h($person->age) ?></td> <td><?=h($person->mail) ?></td> </tr> <?php endforeach; ?> </tbody> </table> </div>
実行結果 URL「/persons/index」:
この場合は、入力した全てのデータが表示されています。
なお、先ほどbakeでmodelを作成しました。
bakeの詳しい説明についてはこちらを参照してくださいね。
listでリストを配列で取得する方法
findメソッドの第1引数に’list’を指定すると、レコードのリストを配列で取得することができます。
‘list’を指定する際に、第2引数の連想配列で‘keyField’と‘valueField’オプションを使うことで、取得する配列のキーと値に使われるフィールドを設定することも出来ます。
サンプルコードで確認していきましょう。
このサンプルコードでは、findメソッドの第2引数の連想配列に‘limit’を指定してリストの取得数を指定しています。
また、‘keyField’と‘valueField’オプションを使い、取得する配列のキーと値を設定しています。
/src/Controller/PersonsController.php:
<?php namespace App\Controller; use App\Controller\AppController; class PersonsController extends AppController { public function index() { // データの値を配列として取得 $this->set('persons', $this->Persons->find('list', ['limit'=>3])); $this->set('data', $this->Persons->find('list', ['keyField' => 'name', 'valueField' => 'mail', 'limit'=>3])); } }
/src/Template/Persons/index.ctp:
<div> <h3>List Persons</h3> <table> <thead> <tr> <th>NAME</th> </tr> </thead> <tbody> <?php foreach ($persons as $person): ?> <tr> <td><?=$person ?></td> </tr> <?php endforeach; ?> </tbody> </table> <pre><?php print_r($persons->toArray()) ?></pre> <table> <thead> <tr> <th>MAIL</th> </tr> </thead> <tbody> <?php foreach ($data as $datum): ?> <tr> <td><?=$datum ?></td> </tr> <?php endforeach; ?> </tbody> </table> <pre><?php print_r($data->toArray()) ?></pre> </div>
実行結果 URL「/persons/index」:
findメソッドの第2引数の連想配列に‘limit’を指定してリストの取得数を3に指定していますので、1つ目の表には3つのレコードのデータが表示されています。
また、リストの配列もあわせて表示しています。
なお、データとしてフィールド’name’の値が表示されています。
これはmodelをbakeした際に生成された「src/Model/Table/PersonsTable.php」の記述でdisplayFieldメソッドの引数が’name’で指定されているためです。
注意しましょう!
また、‘keyField’と‘valueField’オプションを使い、取得する連想配列のキーを’name’に、値を’mail’に設定しているので、2つ目の表には‘mail’の値が表示されています。
こちらもリストの配列をあわせて表示しています。
src/Model/Table/PersonsTable.php:
<?php namespace App\Model\Table; use Cake\ORM\Query; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Validation\Validator; class PersonsTable extends Table { public function initialize(array $config) { parent::initialize($config); $this->table('persons'); $this->displayField('name'); // 'list'で取得するフィールドの設定 $this->primaryKey('id'); } public function validationDefault(Validator $validator) { $validator ->integer('id') ->allowEmpty('id', 'create'); $validator ->requirePresence('name', 'create') ->notEmpty('name'); $validator ->integer('age') ->allowEmpty('age'); $validator ->allowEmpty('mail'); return $validator; } }
findの応用的な使い方
findメソッドは第2引数の連想配列でオプションを設定することができます。
また、findメソッドの後ろに「->」(アロー演算子)を使ってオプションを設定することもできます。
firstで1つ目の結果を取得する方法
findメソッドの後ろに「->」(アロー演算子)を使ってfirstを記述することで1つ目の結果を取得することができます。
firstの記述方法:
find('all')->first()
それではサンプルコードで確認していきましょう。
/src/Controller/PersonsController.php:
<?php namespace App\Controller; use App\Controller\AppController; class PersonsController extends AppController { public function index() { // Entity全ての取得 $query = $this->Persons->find('all'); // 1つ目の結果を取得 $this->set('person', $query->first()); } }
/src/Template/Persons/index.ctp:
<div> <h3>List Persons</h3> <table> <thead> <tr> <th>ID</th> <th>NAME</th> <th>AGE</th> <th>MAIL</th> </tr> </thead> <tbody> <tr> <td><?=$person->id ?></td> <td><?=h($person->name) ?></td> <td><?=h($person->age) ?></td> <td><?=h($person->mail) ?></td> </tr> </tbody> </table> </div>
実行結果 URL「/persons/index」:
このサンプルコードではfind(‘all’)で全てのデータを取得し、firstを使って1つ目のデータを取得し表示しています。
firstの他にも、lastを使用すると最後のデータを取得することができます。
また、countを使用するとレコード数を取得することができます。
conditionsで条件を設定する方法
findメソッドの第2引数の連想配列のキーに‘conditions’を指定することで条件を設定してデータを取得することができます。
それではサンプルコードで確認していきましょう。
/src/Controller/PersonsController.php:
<?php namespace App\Controller; use App\Controller\AppController; class PersonsController extends AppController { public function index() { // フィールド’name’の値で「ro」が含まれるデータを取得 $this->set('persons', $this->Persons->find('all', ['conditions' => ['name like' => '%ro%']])); } }
/src/Template/Persons/index.ctp:
<div> <h3>List Persons</h3> <table> <thead> <tr> <th>ID</th> <th>NAME</th> <th>AGE</th> <th>MAIL</th> </tr> </thead> <tbody> <?php foreach ($persons as $person): ?> <tr> <td><?=$person->id ?></td> <td><?=h($person->name) ?></td> <td><?=h($person->age) ?></td> <td><?=h($person->mail) ?></td> </tr> <?php endforeach; ?> </tbody> </table> </div>
実行結果 URL「/persons/index」:
このサンプルコードではデータベースのテーブル「persons」のフィールド’name’の値で「ro」が含まれるデータを取得し表示しています。
containで関連テーブルからリストを生成する方法(Joinの代替方法)
CakePHP2.xなどでは「JOIN」句を使って関連するテーブルを結合していましたが、CakePHP3.xでは関連テーブルからリストを生成するためにcontainを使用します。
containの記述方法:
find('all')->contain([‘テーブル名1’, ‘テーブル名2’, ・・・])
それではサンプルコードで確認していきましょう。
前述のテーブル「persons」にカラム「job_id」を追加します。
personsテーブル:
id | name | age | job_id | |
---|---|---|---|---|
1 | Taro | 40 | taro@gmail.com | 1 |
2 | Jiro | 30 | jiro@gmail.com | 2 |
3 | Saburo | 25 | saburo@gmail.com | 3 |
4 | Hanako | 35 | hanako@gmail.com | 4 |
関連するテーブルとして「jobs」を作成します。
SQLクエリ:
CREATE TABLE jobs ( id INTEGER PRIMARY KEY AUTO_INCREMENT, name TEXT NOT NULL );
jobsテーブル:
id | name |
---|---|
1 | teacher |
2 | policeman |
3 | doctor |
4 | nurse |
テーブル「jobs」を作成後、bakeでmodelを作成しています。
bakeの実行例(linux):
bin/cake bake model jobs
/src/Controller/PersonsController.php:
<?php namespace App\Controller; use App\Controller\AppController; class PersonsController extends AppController { public function index() { // 関連テーブルのリスト取得 $this->set('persons', $this->Persons->find('all')->contain(['Jobs'])); } }
/src/Template/Persons/index.ctp:
<div> <h3>List Persons</h3> <table> <thead> <tr> <th>ID</th> <th>NAME</th> <th>AGE</th> <th>MAIL</th> <th>JOB</th> </tr> </thead> <tbody> <?php foreach ($persons as $person): ?> <tr> <td><?=$person->id ?></td> <td><?=h($person->name) ?></td> <td><?=h($person->age) ?></td> <td><?=h($person->mail) ?></td> <td><?=h($person->job->name) ?></td> // 関連テーブルのフィールド </tr> <?php endforeach; ?> </tbody> </table> </div>
またテーブル「src/Model/Table/PersonsTable.php」にbelongsToを使って関連するテーブルを指定する記述を行う必要があります。
src/Model/Table/PersonsTable.php:
<?php namespace App\Model\Table; use Cake\ORM\Query; use Cake\ORM\RulesChecker; use Cake\ORM\Table; class PersonsTable extends Table { public function initialize(array $config) { parent::initialize($config); $this->table('persons'); $this->displayField('name'); $this->primaryKey('id'); $this->belongsTo('Jobs'); // 関連するテーブルの指定 } }
実行結果:
このサンプルコードではテーブル「persons」とテーブル「jobs」のフィールド「job」を結合して表示しています。
まとめ
ここでは、findの使い方について説明しました。
findはデータを検索して取得し使用する場合によく使われます。
使いこなすことができるように、この記事を何度も参考にして下さいね!