CakePHPでSelect2を階層型のセレクトボックスで実現する方法【階層型】


データベースの構成

■テーブル構成(placesテーブル)

カラム
id INT
parent_id INT
name VARCHAR

■テーブルの中身

id parent_id name
1 NULL 関東
2 1 東京都
3 1 埼玉県
4 1 栃木県
5 NULL 関西
6 5 大阪府
7 5 京都府
8 5 兵庫県

「parent_idがnullが親」、[parent_idがnullでないものが子」です。

  • 関東
    • 東京都
    • 埼玉県
    • 栃木県
  • 関西
    • 大阪府
    • 京都府
    • 兵庫県

コントローラでplacesテーブルから欲しい形で取得

下記のような形で$optinosに配列を定義したいです。

PostsController.php

$optinos = [
    '関東' => [
        2 => '東京都',
        3 => '埼玉県',
        4 => '栃木県',
    ],
    '関西' => [
        6 => '大阪府',
        7 => '京都府',
        8 => '兵庫県',
    ]
];


Collectionクラスを使ってデータを取得します。

PostsController.php

$parents = $this->Places->find()
    ->where([
        ['Places.parent_id is' => null]
    ]);

$places = $this->Places->find()
    ->join([
        'table' => $parents,
        'alias' => 'Parent',
        'type' => 'LEFT',
        'conditions' => 'Parent.Places__id = Places.parent_id'
    ])
    ->where([
            ['Places.parent_id is not' => null]
    ])
    ->select([
        'Places.id',
        'Places.parent_id',
        'Places.name',
        'Parent_name' => 'Parent.Places__name',
    ]);

$places = Collection($places);
$options = $places->combine('id', 'name', 'Parent_name')->toArray();

$this->set(compact('options'));

ビューに渡す

コントローラで取得した$optionsをセレクトボックスの引数に渡します。

add.ctp

$this->Form->select('id', $options, ['id' => 'select2'])

<script>
  $(document).ready(function() {
    $('#select2').select2();
  });
</script>

すると下記のようになります。

参考

Select2公式サイト
CakePHP公式サイト