CakePHP3、belongsToManyの中間テーブルに条件をつける

日本語が汚くてすいません

そのうちに直します

以下のようなことをして、belognsToManyアソシエーションで使う中間テーブルで条件指定可能にしています

  • 中間テーブルの hasMany() と association の belongsToMany() をつける
  • Tables#beforeMarshal() でなんとか加工
  • コントローラーなどで Contain で Tag1s を取得する
  • add.ctp/edit.ctp のテンプレートをうまいことする

みたいにすればおk

中間テーブルの hasMany() と association の belongsToMany() をつける

  • 中間テーブルの hasMany() と association の belongsToMany() をつける
  • Tables#beforeMarshal() でなんとか加工

します

<?php
class PostsTable
{

    public function initialize(array $config)
    {
        // $this->Tags->find('list') とかするため用の association
        $this->belongsToMany('Tags', [
            'className' => 'Tags',
            'joinTable' => 'posts_tags',
            'foreignKey' => 'post_id',
            'targetForeignKey' => 'tag_id',
        ]);

        $this->belongsToMany('Tag1s', [
            'className' => 'Tags',
            'joinTable' => 'posts_tags',
            'foreignKey' => 'post_id',
            'targetForeignKey' => 'tag_id',
            'conditions' => [
                'Tags.position' => 1
            ]
        ]);

        $this->hasMany('PostsTags1s', [
            'className' => 'Tags',
            'conditions' => [
                'Tags.position' => 1
            ]
        ]);
    }

    public function beforeMarshal(Event $event, ArrayObject $data, ArrayObject $options)
    {
        if ($data['tag1s']['_ids'] && !is_array($data['tag1s']['_ids'])) {
            $data['posts_tag1s'] = [
                ['tag_id' => $data['tag1s']['_ids'], 'position' => '1'],
            ];
        }
    }
}

コントローラーなどでContainを使ってTag1sを取得する

<?php

class PostsController
{
    public function edit($id = null)
    {
        $post = $this->Posts->get($id, [
            'contain' => [
                'Tag1s',
            ]
        ]);

        if ($this->request->is(['patch', 'post', 'put'])) {
            $post = $this->Posts->patchEntity($post, $this->request->getData());
            if ($this->Posts->save($post)) {
                $this->Flash->success();

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

        $tags = $this->Posts
            ->Tags
            ->find('list');

        $this->set(compact('post', 'tags'));
    }
}
?>

add.ctp/edit.ctpのテンプレートをうまいことする

<?= $this->Form->control('tag1s._ids', array(
    'label' => false,
    'type' => 'select',
    'options' => $tags,
    'empty' => true,
));
?>

まとめ

Enjoy CakePHP!