LoginSignup
1
1

More than 5 years have passed since last update.

CakePHP3のSearchプラグインでconcat検索するときのNULL対策

Last updated at Posted at 2018-12-06

CakePHP:3.6
MySQL:5.7

CakePHP3でfriendsofcake/searchを使って文字列結合(concat)の検索を実装します。
usersテーブルにlast_name、first_nameというカラムがあり、検索項目はname(last_name + first_name)を例にしましょう。

usersテーブルはこのようになっています。
id:3のfirst_nameがNULLのレコードが今回のポイントです。

id last_name first_name
1 田中 一郎
2 山田 太郎
3 田中 NULL

nameに「田中一郎」と入力してid:1が取得できれば成功です。
実装はcallbackでconcatを利用することで実現できます。

/src/Template/Users/index.ctp
<?= $this->Form->create(null); ?>
<?= $this->Form->control('name') ?>
<?= $this->Form->submit('検索') ?>
<?= $this->Form->end(); ?>
/src/Model/Table/UsersTable.php
$searchManager
->add('name', 'Search.Callback', [
    'callback' => function ($query, $args, $manager) {
        return $query->where(function ($exp, $query) use ($args) {
            $name = $query->func()->concat([
                'last_name' => 'identifier',
                'first_name' => 'identifier'
            ]);
            return $exp->like($name, '%' . $args['name'] . '%');
        });
    },
]);

しかしこの方法では「田中」と入力したときにid:3のデータは検索に引っかかりません。
理由はMySQLではconcatしたときに片方のフィールドがNULLだと、もう一方の値にかかわらずNULLが返ってくる仕様のためです。

これを回避するにはIFNULL()が使えます。
[MySQL]nullを含むフィールドのconcat

CakePHP3のfriendsofcake/searchではこのように書けばOKです。
id:3のデータもちゃんと拾ってくれます。

/src/Model/Table/UsersTable.php
$searchManager
->add('name', 'Search.Callback', [
    'callback' => function ($query, $args, $manager) {
        return $query->where(function ($exp, $query) use ($args) {
            $name = $query->func()->concat([
                'IFNULL(last_name, "")' => 'identifier',
                'IFNULL(first_name, "")' => 'identifier'
            ]);
            return $exp->like($name, '%' . $args['name'] . '%');
        });
    },
]);
1
1
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
1
1