この記事はLaravel 10.24環境での記事ですが、次のLaravel本体のコミットを見るに恐らく5.2.13以降のバージョンであれば同じ形で通用します。
Improve behavior of MySQL flag, add config · laravel/framework@318a046
LaravelはPHPのフレームワークです。LaravelにはMySQLとのやり取りをよしなにする機能が入っており、SQLモードもその機能に含まれています。SQLモードはMySQL自体が行うSQL構文やデータ検証についてのふるまい(ゼロ除算、日付の検査など)を設定できます。
MySQL :: MySQL 8.0 リファレンスマニュアル :: 5.1.11 サーバー SQL モード
LaravelのSQLモード設定はconfig/database.php
にあります。これは次の部分です。
// @see https://github.com/laravel/laravel/blob/c7098938d3a2ee7c24c03b88652b1361d04671f9/config/database.php#L59C1-L59C30 'connections' => [ 'mysql' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => null, 'prefix' => '', 'prefix_indexes' => true, // ↓ここ 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ],
strict を true にするといい感じに厳しめのSQLモードが設定され、LaravelがMySQLに接続するたび、そのSQLモードが適用されます(毎回set session sql_mode='SQLモード設定'
をやっています)。これはMySQLについてほぼ知らなくても比較的安全にSQLを扱えるという点で便利です。このため集計できていない集計クエリ、ゼロ除算などといった怪しい処理が自動でエラーとなります。
この bool によるざっくばらんなSQLモード設定は簡易に使えるという利点がありますが、逆にSQLモードを細かく設定したい場合もあります。この場合は次のように modes というキーにSQLモードの設定を入れると期待通りに動作します。
'connections' => [ 'mysql' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => null, 'prefix' => '', 'prefix_indexes' => true, // 配列で各SQLモードを入れる 'modes' => [ 'ONLY_FULL_GROUP_BY', 'STRICT_TRANS_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'ERROR_FOR_DIVISION_BY_ZERO', 'NO_ENGINE_SUBSTITUTION', // ここから↓はLaravelのstrict=true時のデフォルトに追加したモード 'PIPES_AS_CONCAT', 'REAL_AS_FLOAT', ], 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ],
こうするとSQLモードの細かい制御ができます。SQLモードの設定が期待通りかは次のコードで確認できます。
$modes = \DB::query()->selectRaw('@@session.sql_mode')->first(); dd($modes); /* {#528 ▼ +"@@session.sql_mode": "REAL_AS_FLOAT,PIPES_AS_CONCAT,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION" } */
余談ですがLaravelで使っているSQLモードを調べる場合はSELECT @@session.sql_mode;
やSHOW SESSION VARIABLES LIKE 'sql_mode';
を使ってセッションに設定されているSQLモードを見る必要があります。SQLモードを調べる方法で検索するとよく出てくるクエリにSELECT @@global.sql_mode;
がありますが、こちらはMySQLサーバー全体にかかるデフォルトのSQLモードの設定を表示するものであり、セッション単位でSQLモードを書き変えているLaravelのSQLモードを調べる方法としては適切でないです。