この記事は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モードを調べる方法としては適切でないです。