CakePHP3 アソシエーションの設定済みテーブル/ドット記法/contain済みデータを表示させるまで(19/9/29)

<h1>■今回、画像投稿型の...</h1>
...あるテーマに沿ったサイトを
ポートフォリオとして制作中に確認できた、
今後に活かせる(**未来の自分をハマらせない**)ちょっとした内容ですが、
しっかり記録を残しておこうと思います。

**■不明だったこと■**
公式ドキュメントを参照に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ファイル内に下記のように記述することで、
上記の「解消できたこと」につながりました。

```/src/Template/Ices/ranking.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; ?>

```



<h2>▽関係アリと思われる部分と解消方法▽</h2>

/src/Model/Table/CommentsTable.phpの、
foreignKeyがあったことで、Commentsテーブルに
紐づくUsersテーブルの情報が引っ張ってこれなかったようです。
そのモデル内の修正と、ctpファイルへの記述を変更し、
解決に至りました。


```/src/Model/Table/UsersTable.php

parent::initialize($config);
        // //　一部省略  // //
        $this->hasMany('Comments',[
            'foreignKey' => 'user_id'
        ]);
        $this->hasMany('Ices', [
            'foreignKey' => 'user_id'
        ]);    
        $this->hasMany('Comments', [
            'foreignKey' => 'user_id'
        ]);
```


```/src/Model/Table/IcesTable.php
public function initialize(array $config)
    {
          // //　一部省略  // //
        $this->belongsTo('Users', [
            'foreignKey' => 'user_id',
            'joinType' => 'INNER'
        ]);
        $this->hasMany('Comments', [
            'foreignKey' => 'ice_id'
        ]);
    }
```
```/src/Model/Table/CommentsTable.php
public function initialize(array $config)
    {
          // //　一部省略  // //
       
        $this->belongsTo('Ices', [
            'foreignKey' => 'ice_id',
            'joinType' => 'INNER'
        ]);
        
        $this->belongsTo('Users', [
            //'foreignKey' => 'id',
            //↑これがあったから、ひっぱってこれなかった
            'joinType' => 'INNER'
        ]);
    }
```

```/src/Controller/IcesController.php
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');
    }
   
    
    }
```


<h3>▽参考マニュアル(CakePHP公式ドキュメント)</h3>

https://book.cakephp.org/3.0/ja/orm/retrieving-data-and-resultsets.html
https://book.cakephp.org/3.0/ja/orm/associations.html


■最後に自分へ一言
-
debugをした結果、そこに取得希望のフィールドが表示されていなければ、
必ず取得の方法から見直すこと。
そうすれば、あとは表示方法を模索するだけ。