「CakePHP3」タグ検索機能 検索フォーム作成 編【入門】

カテゴリー:PHP

前回までで、ユーザー関連・記事投稿関連・タグ関連の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>

参考:CakePHP3「CMS チュートリアル – タグとユーザー」


タグ

関連する投稿

ドラクエ好きな社会保険労務士有資格者・ファイナンシャルプランナー技能士検定2級正会員が運営をしています。当ブログではDQMSLを中心にWordPress・HTML・CSS・JS・PHPなどのTips備忘記録や資格関連の情報、その他雑記を発信して行きます。