前回までで、ユーザー関連・記事投稿関連・タグ関連のCRUDが全て完成したので、今回はCakePHP3のコンテンツ管理チュートリアルを参考にした入門関連のタグ検索機能を実装していきます。
config/routes.phpを 編集
タグに追加された文言のURLでアクセスができるようにroutes.phpの「Router::defaultRouteClass(DashedRoute::class);」の下に下記を追加します。
Router::scope( '/articles', ['controller' => 'Articles'], function (RouteBuilder $routes) { $routes->connect('/tagged/*', ['action' => 'tags']); } );
追加後、下記urlにアクセスをするとtagsメソッドが存在しないとエラーメッセージが表示されます。
http://localhost/cms/articles/tagged
ここまででroutes.phpの編集は完了です。
Controller ArticlesController.php に tagsメソッドを追加
上記のエラーを解消するために下記tagsメソッドを ArticlesController.php に追加します。
public function tags() { if ($this->request->is('post')) { $tags = $this->request->getData(); $articles = $this->Articles->find('tagged', [ 'tags' => $tags ]); } else { $tags = $this->request->getParam('pass'); $articles = $this->Articles->find('tagged', [ 'tags' => $tags ]); } $this->set([ 'articles' => $articles, 'tags' => $tags ]); }
urlにtagを直打ち以外にもpostされたデータで検索ができるようにしてあります。
追加後に再度、下記のurlにアクセスをすると finder method “tagged” とファインダーメソッドがないと表示されます。
http://localhost/cms/articles/tagged
ここまででArticlesController.phpの編集は完了です。
Table ArticlesTable.php にファインダーメソッドを追加
続いて上記のエラーを解消するために下記ファインダーメソッドをTable ArticlesTable.phpに追加します。
public function findTagged(Query $query, array $options) { $columns = [ 'Articles.id', 'Articles.user_id', 'Articles.title', 'Articles.body', 'Articles.published', 'Articles.created', 'Articles.slug', ]; $query = $query ->select($columns) ->distinct($columns); if (empty($options['tags'])) { $query->leftJoinWith('Tags') ->where(['Tags.title IS' => null]); } else { $query->innerJoinWith('Tags') ->where(['Tags.title IN' => $options['tags']]); } return $query->group(['Articles.id']); }
追加後に再度下記のurlにアクセスをすると今度は Missing Template とテンプレートがないと表示されます。
http://localhost/cms/articles/tagged
ここまででArticlesTable.phpの編集は完了です。
Template Articles tags.ctp を作成
最後にtags.ctpをTemplate/Articlesフォルダ内に作成をして、タグ検索機能が完成です。
tags.ctp内に検索フォームを作成して、postでデータを送ってタグを検索できるようにしています。
<nav class="large-3 medium-4 columns" id="actions-sidebar"> <ul class="side-nav"> <li class="heading"><?= __('Actions') ?></li> <li><?= $this->Html->link(__('List Articles'), ['action' => 'index']) ?> </li> <li><?= $this->Html->link(__('New Article'), ['action' => 'add']) ?> </li> <li><?= $this->Html->link(__('List Users'), ['controller' => 'Users', 'action' => 'index']) ?> </li> <li><?= $this->Html->link(__('New User'), ['controller' => 'Users', 'action' => 'add']) ?> </li> <li><?= $this->Html->link(__('List Tags'), ['controller' => 'Tags', 'action' => 'index']) ?> </li> <li><?= $this->Html->link(__('New Tag'), ['controller' => 'Tags', 'action' => 'add']) ?> </li> </ul> </nav> <div class="articles form large-9 medium-8 columns content"> <?= $this->Form->create() ?> <fieldset> <legend><?= __('Find Articles') ?></legend> <?php echo $this->Form->control('tagged'); ?> </fieldset> <?= $this->Form->button(__('Submit')) ?> <?= $this->Form->end() ?> </div> <div class="articles view large-9 medium-8 columns content"> <h3>Articles tagged with <?= $this->Text->toList(h($tags), 'or') ?></h3> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th scope="col"><?= $this->Paginator->sort('id') ?></th> <th scope="col"><?= $this->Paginator->sort('user_id') ?></th> <th scope="col"><?= $this->Paginator->sort('title') ?></th> <th scope="col"><?= $this->Paginator->sort('slug') ?></th> <th scope="col"><?= $this->Paginator->sort('published') ?></th> <th scope="col"><?= $this->Paginator->sort('created') ?></th> <th scope="col"><?= $this->Paginator->sort('modified') ?></th> <th scope="col" class="actions"><?= __('Actions') ?></th> </tr> </thead> <tbody> <?php foreach ($articles as $article): ?> <tr> <td><?= $this->Number->format($article->id) ?></td> <td><?= $this->Html->link($article->user_id,['controller' => 'Users', 'action' => 'view', $article->user_id]) ?></td> <td><?= h($article->title) ?></td> <td><?= h($article->slug) ?></td> <td><?= h($article->published) ?></td> <td><?= h($article->created) ?></td> <td><?= h($article->modified) ?></td> <td class="actions"> <?= $this->Html->link(__('View'), ['action' => 'view', $article->slug]) ?> <?= $this->Html->link(__('Edit'), ['action' => 'edit', $article->slug]) ?> <?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $article->slug], ['confirm' => __('Are you sure you want to delete # {0}?', $article->id)]) ?> </td> </tr> <?php endforeach; ?> </tbody> </table> </div>
他の画面からもタグ検索機能に画面遷移ができるように、各ctpファイルのサイドナビに下記を追加して完了です。
// Articles/ 以下のctpファイル <li><?= $this->Html->link(__('Find Articles'), ['action' => 'tags']) ?> </li> // それ以外のctpファイル <li><?= $this->Html->link(__('Find Articles'), ['controller' => 'Articles','action' => 'tags']) ?> </li>