bakeで不具合が出た場合の対処について
(参考記事)
以下のように1つのテーブルに繰り返し外部キー制約が設定されている設計についてはCakePHPでbakeした後にコードの修正が必要となる。
不具合の例1) データの一覧表示画面で外部キーの値がそのまま表示される。以下の画像ではPlayerとPlayer2がidで表示されている。
不具合の例2) データ入力画面で入力項目が表示されない。以下の画像ではPlayer2の入力候補が表示されない。
この不具合を残したままでOK なら以下の作業は不必要
以下の様に試合結果テーブル results から playersテーブルに繰り返し外部参照を持つような場合 bake しても期待通りに動作するコードを生成できないことがある。
テーブル生成SQLの例)
create table players (
id int not null auto_increment primary key,
name varchar(10) not null
);
create table results (
id int not null auto_increment primary key,
player_id int not null,
player2_id int not null,
winner_id int not null,
FOREIGN KEY (player_id) REFERENCES players(id),
FOREIGN KEY (player2_id) REFERENCES players(id),
FOREIGN KEY (winner_id) REFERENCES players(id)
)
対処法:異なる名前で制約名を設定し外部参照のアソシエーションで使用するクラス名を指定する。
・モデルの修正
vs code で CakePHPをインストールした作業フォルダを開き、
src/Model/Table/ResultsTable.php
を開いて編集する。Resultsの部分は不具合を修正したいモデル名になる。
以下のように className を Player2s と Winners にそれぞれ追加して、
belongsTo('Players' を belongsTo('Player2s' や belongsTo('Winners' に修正する
class ResultsTable extends Table
{
public function initialize(array $config): void
{
// ...
$this->belongsTo('Players',[
'foreignKey' => 'player_id'
]);
$this->belongsTo('Player2s',[
'className' => 'Players',
'foreignKey' => 'player2_id'
]);
$this->belongsTo('Winners',[
'className' => 'Players',
'foreignKey' => 'winner_id'
]);
}
}
1つ目のアソシエーションbelongsToではclassNameを指定していないが、その場合は制約名 Players と同じ名前のモデルが使用されるらしい。
コマンドプロンプト(Shell)から作業ホルダに移動して以下のコマンドでコントローラとビューを修正する
bin\cake bake controller results
bin\cake bake template results
bakeした際に既にbakeで生成したファイルがあると以下のような上書き確認のプロンプトが表示されるので a を入力してenter を押してすべて上書きする。
以下のデータベースで
games テーブルには makers テーブルへの参照が2つある。
・maker_id フィールドの外部参照
・games_makers中間テーブルを介した多対多の参照
この様な場合では bake で生成したコードでは以下のように maker_id のフィールドに表示項目の name が利用できずに id が表示されてしまう
修正方法:
Model/Table/GamesTable.php
を修正して、コントローラーとビューをbakeしなおす。
belongsTo の Makers と belongsToMany の Makers が競合している
belongsTo の Makers を Maker2s に修正する(競合回避のために別名 Maker2s にする)
className として Makers を指定する。(これは元のクラス名のままでOK)
以下のgames_usersテーブルに対してはbakeでindexやaddなどのWebページをうまく生成できない。
以下のように対処が必要。
上の図のgames_users テーブルはcakephpの規約 「id フィールドを主キーとして持つ」に従っていない。
そのため bake all でMVCを自動生成できない。
bake all で games_usersテーブルのモデルを生成してしまった場合は、誤ったコードが生成されるので EntityとTableのコードを削除する必要がある。
対処法
bake でサブコマンド model を指定してモデルを作成する
オプションスイッチ --primary-key で複合主キーを指定
複合キー game_id,user_id と 追加した項目 date を --fields で指定
コマンドの例)
bin\cake bake model games_users --primary-key game_id,user_id --fields game_id,user_id,date
コントローラとビューをbakeする。
bin\cake bake controller games_users
bin\cake bake template games_users
動作確認:
http://localhost/3116999boardgame_rental/games-users ※ games と users の間は ハイフン記号 ‐
※ ここの作業は複合主キーに部分的な対応をしています。
動作するもの
games-users/index
動作しないもの
games-users/add
games-users/view
games-users/edit
games-users/delete
動作しない機能はtemplateの phpファイル中のコードから削除してもよい。
add を動作するように修正
src/template/GamesUsers/add.php に太字部分の2行を追記。
echo $this->Form->control('user_id', ['options' => $users,'type' => 'select']);
echo $this->Form->control('game_id', ['options' => $games,'type' => 'select']);
echo $this->Form->control('date', ['empty' => true]);
view , edit, deleteを動作するよう以下の赤文字の部分を参考にして修正
$id の代わりに複合キー$game_idと$user_idに変更する
src/Controller/GamesUsersController.php
public function view($game_id = null, $user_id = null)
{
$gamesUser = $this->GamesUsers->get([$game_id, $user_id], contain: ['Games', 'Users']);
public function edit($game_id = null, $user_id = null)
{
$gamesUser = $this->GamesUsers->get([$game_id, $user_id], contain: []);
public function delete($game_id = null, $user_id = null)
{
$this->request->allowMethod(['post', 'delete']);
$gamesUser = $this->GamesUsers->get([$game_id, $user_id]);
src/template/GamesUsers/index.php を修正
赤文字の部分を参考に
<td class="actions">
<?= $this->Html->link(__('View'), ['action' => 'view', $gamesUser->game_id,$gamesUser->user_id]) ?>
<?= $this->Html->link(__('Edit'), ['action' => 'edit', $gamesUser->game_id,$gamesUser->user_id]) ?>
<?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $gamesUser->game_id,$gamesUser->user_id], ['confirm' => __('Are you sure you want to delete # {0} # {1}?', $gamesUser->game_id,$gamesUser->user_id)]) ?>
</td>
応用
サブフォームを作成する。ChatGPTなどを利用して、
キャラ登録画面
新規ユーザ名
ユーザのハンドル名
ユーザ所持アイテム登録サブフォーム
アイテム1 個数
アイテム2 個数
のようなサブフォームに対応したControllerとtemplateを生成する