続いて、もう1つのテーブルクラス「
MessagesTable」を作成しましょう。「
Table」フォルダ内に、「
MessagesTable.php」ファイルを作成して下さい。ソースコードは下のリスト欄のように記述しておきます。
この
MessagesTableは、
MembersTable側から
hasManyで関連付けられる側のテーブルクラスになります。基本的に、「関連付けられる側」には、特別な処理などは必要ありません。ごく一般的なテーブルクラスとして作成してかまいません。
ただし、今回は、この
MessagesTable側から、先ほどの
MembersTable側へ関連付ける設定を用意してあります。それは、以下の部分です。
$this->belongsTo('Members', [
'foreignKey' => 'members_id',
'joinType' => 'INNER'
]);
「
belongsTo」は、「多対1(belongs to)」のアソシエーションを設定するためのものでしたね。先に述べたように、
belongs toは、
has manyの逆方向からのアソシエーションです。これを用意することで、「
Memberのデータから、それに関連する
Messageを得る」というだけでなく、「
Messageのデータから、関連する
Memberを得る」ということも行えるようになります。
この
belongsToメソッドも、使い方は
hasManyと同じですね。第1引数には「
Members」を指定します。第2引数には、
foreignKeyとして「
members_id」が指定されています。これは、先ほどの
hasManyの場合とほぼ同じです。
重要なのはその後です。この他に、「
joinType」という値が設定されていますね。
belongs toは、SQLで「
Inner Join」と呼ばれる結合によって処理されます。両者の接続方式が、
hasOneや
hasManyなどとは違うのです。このため、
joinTypeを明示的に
'INNER'に設定しておきます。
■ルールチェッカーについて
また、その他に「
buildRules」というメソッドが追加されています。これは、「
ルールチェッカー(rules checker)」と呼ばれるオブジェクトを返すもので、「Messagesにmembers_idが用意されているか」を明示的にチェックするための仕組みです。(
Membersテーブルには外部キーはありませんでしたから、このメソッドは用意されていなかったのです)
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['members_id'], 'Members'));
return $rules;
}
引数に渡される
RulesCheckerインスタンスの「
add」メソッドを使い、ルールを追加します。引数には、
RulesCheckerの「
existsIn」というメソッドを使います。これは、第1引数の配列にあるフィールドが、第2引数のテーブルにすべて用意されているかチェックするものです。これで、ちゃんと用意されていればtrueが
addされますが、なければfalseが
addされ、ルールチェックでエラーになる、というわけです。
――とりあえず、これでモデル関係の作成はできました。アソシエーションそのものは、たったこれだけで使えるようになります。意外と簡単ですね!
<?php
namespace App\Model\Table;
use App\Model\Entity\Message;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class MessagesTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->table('messages');
$this->displayField('title');
$this->primaryKey('id');
$this->belongsTo('Members', [
'foreignKey' => 'members_id',
'joinType' => 'INNER'
]);
}
public function validationDefault(Validator $validator)
{
$validator
->add('id', 'valid', ['rule' => 'numeric'])
->allowEmpty('id', 'create');
$validator
->requirePresence('title', 'create')
->notEmpty('title');
$validator
->allowEmpty('comment');
return $validator;
}
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['members_id'], 'Members'));
return $rules;
}
}