CakePHP 4 で MySQL の SUBSTR() を実行する方法

はじめに

今日は CakePHP 4 で MySQL の SUBSTR() 関数を実行する方法をご紹介します。

CakePHP
4.2.3
MariaDB
10.4.17
目次
  1. 下準備
  2. select() で使う方法
  3. where() で使う方法
  4. おわりに

1. 下準備

今回使用したデータベースです。

/config/Migrations/20210215000001_CreateDrinks.php
<?php
declare(strict_types=1);

use Migrations\AbstractMigration;

class CreateDrinks extends AbstractMigration
{
    public function change()
    {
        $table = $this->table('drinks');
        $table->addColumn('name', 'string', [
            'default' => null,
            'limit' => 255,
            'null' => false,
        ]);
        $table->create();
    }
}
/config/Seeds/DrinksSeed.php
<?php
declare(strict_types=1);

use Migrations\AbstractSeed;

class DrinksSeed extends AbstractSeed
{
    public function run()
    {
        $data = [
            ['id' => '1', 'name' => 'Coffee'],
            ['id' => '2', 'name' => 'Apple Juice'],
            ['id' => '3', 'name' => 'Cocoa'],
        ];
        $table = $this->table('drinks');
        $table->insert($data)->save();
    }
}

下記コマンドでマイグレーションを実行して、モデルを Bake で自動生成しました。

cd /path/to/cakephp4
bin/cake migrations migrate
bin/cake migrations seed
bin/cake bake model Drinks --no-test --no-fixture

2. select() で使う方法

CakePHP 4 の FunctionsBuilder には substr() は実装されていませんが、
下記のように $query->func()->substr() で SUBSTR() 関数を呼び出すことができます。

/src/Controller/DrinksController.php
<?php
declare(strict_types=1);

namespace App\Controller;

class DrinksController extends AppController
{
    public function index()
    {
        $query = $this->Drinks->find();
        $drinks = $query->select([
                'name',
                'initial' => $query->func()->substr(['Drinks.name' => 'identifier', 1, 1])
            ])
            ->all();
        // 取得データ表示
        foreach ($drinks as $drink) {
            debug($drink->toArray());
        }
        exit;
    }
}

3. where() で使う方法

WHERE 句で使う場合も同様に、下記のように実装できます。

/src/Controller/DrinksController.php
<?php
declare(strict_types=1);

namespace App\Controller;

class DrinksController extends AppController
{
    public function index()
    {
        $drinks = $this->Drinks->find()
            ->where(function ($exp, $query) {
                $initial = $query->func()->substr(['Drinks.name' => 'identifier', 1, 1]);
                return $exp->eq($initial, 'C');
            })
            ->all();
        foreach ($drinks as $drink) {
            debug($drink->toArray());
        }
        exit;
    }
}

4. おわりに

MySQL では SUBSTR() は SUBSTRING() と同意なので substring() と書くこともできます

$query->func()->substring(['Drinks.name' => 'identifier', 1, 1])

また今回ご紹介した方法は SUBSTR() に限らず、他の関数も実行可能です。