■今回、画像投稿型の...
...あるテーマに沿ったサイトを ポートフォリオとして制作中に確認できた、 今後に活かせる(**未来の自分をハマらせない**)ちょっとした内容ですが、 しっかり記録を残しておこうと思います。■不明だったこと■
公式ドキュメントを参照にcontain、belongs to、hasmanyに
ついて学び、Model(テーブル)と、controllerに記述はしたものの、
「では、ctpファイル(表示させる部分)にはどのように記述すればいいの?」
ということがわからない状況が続いていました。
■解消できたこと■
特定のキーワード(Icesテーブル内の特定フィールド)を元に
「検索」された「記事」に「他ユーザが投稿した、投稿済みコメント」
を表示させ、さらに「投稿済みコメントの投稿ユーザ」の「ニックネーム」
を表示させ、さらにその「ニックネーム」をクリックすると、
そのユーザーの詳細情報に画面遷移させることができるようになりました。
■テーブル■
Users(ユーザ情報が入る:ここにニックネーム有り)
Ices(ブログ記事が入る)
Comments(ブログ記事に対して他ユーザがコメント時のデータが入る)
■環境■
AWS Cloud9:無料枠
MySQL:ver5.7.26
CakePHP:ver3.8.2
PHP:ver7.2.19
■結果■
ctpファイル内に下記のように記述することで、
上記の「解消できたこと」につながりました。
<?php foreach ($ices as $ice): ?>
// // 一部省略 // //
<h3>ここからコメント</h3>
<?php if ($ice->comments): ?>
<p><?= h($ice->comments[0]->comment) ?></p>
//↓このpタグ内がポイント//
<p>BY<?= $this->Html
->link( h($ice->comments[0]->user->nickname),
['controller' => 'Users',
'action' => 'view',
$ice->comments[0]->user['id']]) ?></p>
//↑このpタグ内がポイント//
<?php else: ?>
<p>コメントはまだありません。</p>
<?php endif ?>
<?php endforeach; ?>
▽関係アリと思われる部分と解消方法▽
/src/Model/Table/CommentsTable.phpの、
foreignKeyがあったことで、Commentsテーブルに
紐づくUsersテーブルの情報が引っ張ってこれなかったようです。
そのモデル内の修正と、ctpファイルへの記述を変更し、
解決に至りました。
parent::initialize($config);
// // 一部省略 // //
$this->hasMany('Comments',[
'foreignKey' => 'user_id'
]);
$this->hasMany('Ices', [
'foreignKey' => 'user_id'
]);
$this->hasMany('Comments', [
'foreignKey' => 'user_id'
]);
public function initialize(array $config)
{
// // 一部省略 // //
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
$this->hasMany('Comments', [
'foreignKey' => 'ice_id'
]);
}
public function initialize(array $config)
{
// // 一部省略 // //
$this->belongsTo('Ices', [
'foreignKey' => 'ice_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Users', [
//'foreignKey' => 'id',
//↑これがあったから、ひっぱってこれなかった
'joinType' => 'INNER'
]);
}
public function search()
{
$ices = $this->Ices->find('all');
$manufacturer = isset($this->request->query['manufacturer']) ? $this->request->query['manufacturer'] : null;
$keyword = isset($this->request->query['keyword']) ? $this->request->query['keyword'] : null;
if($manufacturer){
$where = ['Ices.manufacturer' => $manufacturer];
if ($keyword) {
$where['OR']['Ices.ice_fraver LIKE'] = "%$keyword%";
$where['OR']['Ices.simple_comment LIKE'] = "%$keyword%";
}
$ices = $this->Ices->find();
$ices->where($where)
//↓ここがポイント!!
->contain(['Comments.Users','Users'])
//"Comments.Users"の意味は...
//Icesテーブルに紐づく、
//Commentsテーブルの情報と、
//Commentsテーブルに紐づく、Usersテーブルの情報。
//という意味で、
//"Users"の部分は、
//Icesテーブルに紐づく、
//Userテーブルの情報を含む...
//という意味になる。
->all();
$this->set('manufacturer', $manufacturer);
$this->set('keyword', $keyword);
$this->set('ices', $this->paginate($ices));
$this->render('ranking');
}
}
▽参考マニュアル(CakePHP公式ドキュメント)
https://book.cakephp.org/3.0/ja/orm/retrieving-data-and-resultsets.html
https://book.cakephp.org/3.0/ja/orm/associations.html
■最後に自分へ一言
debugをした結果、そこに取得希望のフィールドが表示されていなければ、
必ず取得の方法から見直すこと。
そうすれば、あとは表示方法を模索するだけ。