CakePHPで関連テーブル(連携テーブル)のデータを更新するときの罠
こんにちは、SGKです。
今回はCakePHPで関連テーブル(連携テーブル)のデータを更新するときの罠を紹介します。
関連テーブルについては以前このブログで取り上げています。
CakePHP save belongs to many associative data
今回は関連テーブルのデータ更新には罠があるよ!という事と、、
前記事は英語なので日本語でおさらいしつつといった内容です。
さて早速、以前の内容に合わせて以下のようなテーブル構成があったとします。
エンジニア
エンジニアスキル
スキル
エンジニアタイプ
ここでは「エンジニアタイプ」というテーブルが追加されており、
それを絡めた要件は以下の通りです。
– エンジニアは複数のスキルを選択可能
– 選択したスキルはエンジニアスキルに保存される
– エンジニアは自身のエンジニアタイプによって選択できるスキルが異なる
– スキルはエンジニアタイプによって区分けされている
画面にすると以下のような感じで
タイプのラジオボタンを切り替えるとそのタイプに合わせたスキルに切り替わるという様式です。
そしてここには当然以下のような要件が設定されます。
「選択した自身のスキルタイプ以外のスキルは選択できないようにする」
まぁとりあえずこの要件は置いておくとして、、、
CakePHP を使ってこのエンジニアスキルにデータを保存するための方法ですが、
EngineerTableクラスの関連定義に、エンジニアスキルの定義をして、
$this->hasMany('EngineersSkills', [
'foreignKey' => 'engineer_id',
'saveStrategy' => 'replace',
]);
そしてエンティティ側 Entity¥Engineer クラスの $_accessible に EngineersSkills の
連携更新を許可するよう ‘engineers_skills’ => true がセットされていれば
protected $_accessible = [
// ~ 略 ~
'engineers_skills' => true,
];
以下のようなコードで
$tblEngineers = \Cake\ORM\TableRegistry::getTableLocator()->get( 'Engineers' );
$tblEngineers->patchEntity( $entEngineer, [
'type_id' => $params['type_id'],
'skills' => $params['skill_id'],
] );
$tblEngineers->save( $entEngineer );
$entEngineer のエンジニアIDと紐づいた状態でエンジニアスキルにチェックしたスキルが保存されます。
しかしここで問題が生じます。
置いておいた「選択した自身のスキルタイプ以外のスキルは選択できないようにする」という点で、
ユーザーが開発パネルなどで勝手にスキルIDを書き換えたりすると
本来選択したタイプに属さないスキルを保存できてしまいます。
これが今回注意しなければいけない罠です。
なので、チェックされているスキルが選択されたタイプに属するものかバリデーションしないとダメです。
例えば以下のように。
$tblSkills = \Cake\ORM\TableRegistry::getTableLocator()->get( 'Skills' );
$querySkills = $tblSkills->find()->where(['id IN'=>$params['skill_id'], 'type_id' => $params['type_id']]);
if( $querySkills->count() != count($params['skill_id']) ){
//選択できないスキルがチェックされています!!
}
関連テーブルの保存に関してはよく見るのですが、ここを説明している記事はないな、と思ったので今回あげてみました。
もしかするとこれ見てぞっとするCakeエンジニアって少なくないのかも、、
以上、CakePHPで関連テーブル(連携テーブル)のデータを更新するときの罠、についてでした。