「CakePHP3」タグ選択機能を改善、コンマ区切りで記事投稿や編集時にもタグを追加・削除編【入門】

カテゴリー:PHP

今回は、タグ選択機能を改善していきます。コンマ区切りで、記事投稿や編集時にもタグを追加、削除できるようにします。

Model Entity Article.php を編集

まずは下記で、Collection クラスをインポートします。「namespace App\Model\Entity;」の下に追加します。

use Cake\Collection\Collection;

次に、下記をprotected $_accessibleの下に追加します。

    protected function _getTagString()
    {
        if (isset($this->_properties['tag_string'])) {
            return $this->_properties['tag_string'];
        }
        if (empty($this->tags)) {
            return '';
        }
        $tags = new Collection($this->tags);
        $str = $tags->reduce(function ($string, $tag) {
            return $string . $tag->title . ', ';
        }, '');
        return trim($str, ', ');
    }

ここまでで、Article.phpの編集は完了です。

Model Table ArticlesTable.php を編集

続いて、ArticlesTable.phpに下記を追加します。

    public function beforeSave($event, $entity, $options)
    {
        if ($entity->tag_string) {
            $entity->tags = $this->_buildTags($entity->tag_string);
        }
    }

     protected function _buildTags($tagString)
    {

        $newTags = array_map('trim', explode(',', $tagString));

        $newTags = array_filter($newTags);

        $newTags = array_unique($newTags);

        $out = [];
        $query = $this->Tags->find()
            ->where(['Tags.title IN' => $newTags]);

        foreach ($query->extract('title') as $existing) {
            $index = array_search($existing, $newTags);
            if ($index !== false) {
                unset($newTags[$index]);
            }
        }

        foreach ($query as $tag) {
            $out[] = $tag;
        }

        foreach ($newTags as $tag) {
            $out[] = $this->Tags->newEntity(['title' => $tag]);
        }
        return $out;
    }

ここまでで、ArticlesTable.phpの編集が完了です。

Template Articles add.ctp edit.ctp を編集

add.ctpとedit.ctpにあるフォーム内の下記の箇所を置き換えます。

    // これを
    echo $this->Form->control('tags._ids', ['options' => $tags]);

    // これに置き換え
    echo $this->Form->control('tag_string', ['type' => 'text']);

ここまでで、ctp関連の編集が完了です。

Controller ArticlesController.php を編集

最後にArticlesController.phpを編集して作業完了です。

編集する箇所は、「Add method」と 「Edit method」内です。下記のように編集します。

Add method

    public function add()
    {
        $article = $this->Articles->newEntity();
        if ($this->request->is('post')) {

            $query = $this->request->getData();

            $query['user_id'] = $this->Auth->user('id');

            $sluggedTitle = Text::slug($this->request->getData('title'));

            $query['slug'] = substr($sluggedTitle, 0, 191);

            // ここから追加
            $article->tag_string = $this->request->getData('tag_string');
            // ここまで追加

            $article = $this->Articles->patchEntity($article, $query);

            if ($this->Articles->save($article)) {
                $this->Flash->success(__('The article has been saved.'));

                return $this->redirect(['action' => 'index']);
            }

            $this->Flash->error(__('The article could not be saved. Please, try again.'));
        }
        $users = $this->Articles->Users->find('list', ['limit' => 200]);
        $tags = $this->Articles->Tags->find('list', ['limit' => 200]);
        $this->set(compact('article', 'users', 'tags'));
    }

Edit method

    public function edit($slug = null)
    {

        $article = $this->Articles->findBySlug($slug)->contain('Tags')->firstOrFail();

        if ($this->request->is(['patch', 'post', 'put'])) {

            $query = $this->request->getData();

            $sluggedTitle = Text::slug($this->request->getData('title'));
            $query['slug'] = substr($sluggedTitle, 0, 191);

            // ここから追加
            $article->tag_string = $this->request->getData('tag_string');
            // ここまで追加

            $article = $this->Articles->patchEntity($article, $query);

            if ($this->Articles->save($article)) {
                $this->Flash->success(__('The article has been saved.'));

                return $this->redirect(['action' => 'index']);
            }
            $this->Flash->error(__('The article could not be saved. Please, try again.'));
        }
        $users = $this->Articles->Users->find('list', ['limit' => 200]);
        $tags = $this->Articles->Tags->find('list', ['limit' => 200]);
        $this->set(compact('article', 'users', 'tags'));
    }

これで、クイックスタートガイドのコンテンツ管理チュートリアルを元にしたWebアプリが全て動作するようになりました。

MAMP環境で、確認をしながら作業してきましたが、CakePHP3のbake機能はかなり便利だと改めて思いました。

そして何より動かせるというこうとがプログラム初心者には一番嬉しい・楽しいですよね。クイックスタートガイドもわかりやすいので、これからCakePHP3を始める方、プログラムに興味がある方にオススメです。

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


タグ

関連する投稿

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