LoginSignup
9
13

More than 5 years have passed since last update.

CakePHPで絞り込み機能の実装

Last updated at Posted at 2019-01-07

この記事は CakePHP Advent Calendar 2018 25日目の記事です。

空いていましたので、滑り込ませて頂きました。

やりたい事

ある一覧表のようなものから、絞り込み表示したい。

実装フロー

  1. マイグレーションファイルでテーブル作成
  2. マイグレーションファイルで仮データをインサート
  3. TableとEntity作成
  4. 対象テーブルにリレーションを張る
  5. Controller作成
  6. 対象テーブルから全データ取得
  7. View作成
  8. 取得データを表示
  9. フォームの作成
  10. 絞り込みボタン設置
  11. 絞り込みボタンが押されたらクエリパラメータをGETメソッドでリクエスト
  12. クエリパラメータを元にテーブルからデータを取得する際に絞り込む
  13. 絞り込まれたデータを表示

1. マイグレーションファイルでテーブル作成

今回は2つのテーブルを作成
- categories Table
- master_category_types Table

$ bin/cake migrations create CreateCategories
$ bin/cake migrations create CreateMasterCategoryType

マイグレーションファイル内のコードは下記参照

categoriesテーブル作成マイグレーションファイル

MigrationFile1
<?php
use Migrations\AbstractMigration;

class CreateCategories extends AbstractMigration
{
    public function up()
    {
        $table = $this->table('categories');
        $table->addColumn('name', 'string', [
            'null' => false
        ]);
        $table->addColumn('user_id', 'integer', [
            'null' => false
        ]);
        $table->addColumn('type_id', 'integer', [
            'null' => false
        ]);
        $table->create();
    }

    public function down()
    {
        $table = $this->table('categories');
        $table->drop();
    }
}

master_category_typesテーブル作成マイグレーションファイル

MigrationFile2
<?php
use Migrations\AbstractMigration;

class CreateMasterCategoryType extends AbstractMigration
{
    public function up()
    {
        $table = $this->table('master_category_type');
        $table->addColumn('name', 'string', [
            'null' => false
        ]);
        $table->create();
    }

    public function down()
    {
        $table = $this->table('master_category_type');
        $table->drop();
    }
}

2. マイグレーションファイルで仮データをインサート

それぞれのテーブルにデータをインサートするマイグレーションファイル作成

$ bin/cake migrations create InsertCategories
$ bin/cake migrations create InsertMasterCategoryType

categoriesテーブルにインサートするマイグレーションファイル

MigrationFile3
<?php
use Migrations\AbstractMigration;

class InsertCategories extends AbstractMigration
{
    public function up()
    {
        $table = $this->table('categories');
        $row = [
            [
                'name' => 'リンゴ',
                'user_id' => 2343,
                'type_id' => 1
            ],
            [
                'name' => 'ピアノ',
                'user_id' => 2343,
                'type_id' => 2
            ],
            [
                'name' => 'ビール',
                'user_id' => 2343,
                'type_id' => 3
            ],
            [
                'name' => 'バナナ',
                'user_id' => 2343,
                'type_id' => 1
            ],
            [
                'name' => 'ギター',
                'user_id' => 2343,
                'type_id' => 2
            ],
            [
                'name' => 'ワイン',
                'user_id' => 2343,
                'type_id' => 3
            ],
            [
                'name' => 'ブドウ',
                'user_id' => 2343,
                'type_id' => 1
            ],
            [
                'name' => 'ベース',
                'user_id' => 2343,
                'type_id' => 2
            ],
            [
                'name' => '日本酒',
                'user_id' => 2343,
                'type_id' => 3
            ],
            [
                'name' => 'ミカン',
                'user_id' => 2343,
                'type_id' => 1
            ],
        ];
        $table->insert($row);
        $table->saveData();
    }

    public function down()
    {
        $this->execute('DELETE FROM categories');
    }
}

master_category_typesテーブルにインサートするマイグレーションファイル

MigrationFile4
<?php
use Migrations\AbstractMigration;

class InsertMasterCategoryType extends AbstractMigration
{
    public function up()
    {
        $table = $this->table('master_category_type');
        $row = [
            [
                'name' => '食べ物'
            ],
            [
                'name' => '楽器'
            ],
            [
                'name' => 'お酒'
            ],
        ];
        $table->insert($row);
        $table->saveData();
    }

    public function down()
    {
        $this->execute('DELETE FROM master_category_type');
    }
}

3. TableとEntity作成

それぞれのTableクラスとEntityクラスを生成

$ bin/cake bake model categories
$ bin/cake bake model master_category_types

それぞれ中身はbake時から修正しています。

CategoriesTable
class CategoriesTable extends Table
{
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->setTable('categories');
        $this->setDisplayField('name');
        $this->setPrimaryKey('id');

        $this->belongsTo('Users', [
            'foreignKey' => 'user_id',
            'joinType' => 'INNER'
        ]);
        $this->belongsTo('MasterCategoryTypes', [
            'foreignKey' => 'type_id',
            'joinType' => 'INNER'
        ]);
    }

    public function validationDefault(Validator $validator)
    {
        return $validator;
    }
}
CategoryEntity
<?php
namespace App\Model\Entity;

use Cake\ORM\Entity;

class Category extends Entity
{
    protected $_accessible = [
        'name' => true,
        'user_id' => true,
        'type_id' => true,
    ];
}
MasterCategoryTypesTable
<?php
namespace App\Model\Table;

use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;

class MasterCategoryTypesTable extends Table
{
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->setTable('master_category_types');
        $this->setDisplayField('name');
        $this->setPrimaryKey('id');
    }

    public function validationDefault(Validator $validator)
    {
        return $validator;
    }
}
MasterCategoryTypeEntity
<?php
namespace App\Model\Entity;

use Cake\ORM\Entity;

class MasterCategoryType extends Entity
{
    protected $_accessible = [
        'name' => true
    ];
}

4. 対象テーブルにリレーションを張る

CategoriesTableに以下のリレーションを張りました。

$this->belongsTo('Users', [
    'foreignKey' => 'user_id',
    'joinType' => 'INNER'
]);
$this->belongsTo('MasterCategoryTypes', [
    'foreignKey' => 'type_id',
    'joinType' => 'INNER'
]);

5. Controller作成

SampleControllerを作成

$ bin/cake bake controller sample

6. 対象テーブルから全データ取得

<?php
namespace App\Controller;

use App\Controller\AppController;

class SampleController extends AppController
{
    public function initialize()
    {
        parent::initialize();
        $this->loadModel('Categories');
        $this->loadModel('MasterCategoryTypes');
    }

    public function index()
    {
        $categories = $this->Categories
            ->find()
            ->where(['user_id' => $this->Auth->user()['id']])
            ->all();
        $this->set(compact('categories'));

        $categoryTypes = $this->MasterCategoryTypes
            ->find()
            ->all();
        $this->set(compact('categoryTypes'));

        $this->render($this->request->action);
    }
}

7. View作成

$ pwd
project/src/Template
$ mkdir Sample
$ cd Sample
$ touch index.ctp

8. 取得データを表示

<h1>欲しい物リスト</h1>
<div>
    <ul>
        <?php foreach ($categories as $category): ?>
            <li><?= $category->name ?></li>
        <?php endforeach; ?>
    </ul>
</div>

9. フォームの作成

10. 絞り込みボタン設置

11. 絞り込みボタンが押されたらクエリパラメータをGETメソッドでリクエスト

<h1>欲しい物リスト</h1>
<div>
    <?= $this->Form->create('', [
        'type' => 'get',
        'url' => [
            'controller' => 'sample',
            'action' => 'index'
        ]
    ]) ?>
    <?= $this->Form->radio('selected_type_id', $options, $attributes) ?>
    <?= $this->Form->button('絞り込む', [
        'type' => 'submit'
    ]) ?>
    <?= $this->Form->end() ?>
    <ul>
        <?php foreach ($categories as $category): ?>
            <li><?= $category->name ?></li>
        <?php endforeach; ?>
    </ul>
</div>

12. クエリパラメータを元にテーブルからデータを取得する際に絞り込む

    public function index()
    {
        $categories = $this->Categories
            ->find()
            ->where(['user_id' => $this->Auth->user()['id']]);
        if (!empty($this->request->query['selected_type_id']) && $this->request->query['selected_type_id'] != 0) {
            $categories->where([
                'type_id' => $this->request->query['selected_type_id']
            ]);
        }
        $categories->all();
        $this->set(compact('categories'));

        $categoryTypes = $this->MasterCategoryTypes
            ->find()
            ->all();
        $this->set(compact('categoryTypes'));

        $options[0] = [
            0 => '一覧'
        ];
        foreach ($categoryTypes as $categoryType) {
            $options[$categoryType->id] = [
                $categoryType->id => $categoryType->name
            ];
        }
        $this->set(compact('options'));

        $attributes = [
            'value' => 0
        ];
        if (!empty($this->request->query['selected_type_id'])) {
            $attributes['value'] = $this->request->query['selected_type_id'];
        }
        $this->set(compact('attributes'));

        $this->render($this->request->action);
    }

13. 絞り込まれたデータを表示

8. 取得データを表示

と同様のロジックの為割愛

実際の挙動

ezgif.com-video-to-gif.gif

まとめ

復習も兼ねて実装してみました。
テーブル作成からやると若干大変でしたが、理解を深められたので良かったです。

おまけ

Twitterやってます!外部のエンジニアの方ともどんどん繋がりたいと考えていますので、是非フォローして頂ければと思います!@Tatsuo96
ブログ始めました!
https://note.mu/tatsuo_iriyama

9
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
13