【Laravel】mysql strict の注意点
【Laravel】mysql struct の注意点
Laravel では mysql への接続オプションとして strict(厳密)モードがあり気をつける必要があります。
strict 設定
config/database.php の mysql => strict の値が true だと有効になっています。
デフォルトの設定では true です。
Laravel 9.x config/database.php
<?php
return [
// 途中省略~~~
'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' => 'utf8mb4_unicode_ci',
'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 の内容
以下のソースに strict の内容が記載されています。
Laravel 9.x src/Illuminate/Database/Connectors/MySqlConnector.php
Mysql 8.0.11 以降の設定
set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
Mysql 8.0.11 未満の設定
set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
<?php
// 途中省略~~~
/**
* Get the query to enable strict mode.
*
* @param \PDO $connection
* @param array $config
* @return string
*/
protected function strictMode(PDO $connection, $config)
{
$version = $config['version'] ?? $connection->getAttribute(PDO::ATTR_SERVER_VERSION);
if (version_compare($version, '8.0.11') >= 0) {
return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'";
}
return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'";
}
strict 解説
ONLY_FULL_GROUP_BY- GROUP BY句 で指定されてない非集計カラムを許可
- MySQL :: MySQL 8.0 リファレンスマニュアル :: 12.20.3 MySQL での GROUP BY の処理
STRICT_TRANS_TABLES- 無効な値に対して近似値などを入れることなくエラーとする
- MySQL :: MySQL 5.6 リファレンスマニュアル :: 1.7.3.3 無効データの制約
NO_ZERO_IN_DATE- 無効な日時の挿入を禁止
- <a href=“https://dev.mysql.com/doc/refman/5.6/ja/sql-mode.html#name="sqlmode_no_zero_in_date”” target=“_blank” rel=“nofollow noopener”>MySQL :: MySQL 5.6 リファレンスマニュアル :: 5.1.7 サーバー SQL モード
NO_ZERO_DATE0000-00-00の日付を禁止- MySQL :: MySQL 5.6 リファレンスマニュアル :: 5.1.7 サーバー SQL モード
ERROR_FOR_DIVISION_BY_ZERO0の禁止。無効だとNULLが入る。- MySQL :: MySQL 5.6 リファレンスマニュアル :: 5.1.7 サーバー SQL モード
NO_AUTO_CREATE_USER- 自動的に新規ユーザを作成しない
- MySQL :: MySQL 5.6 リファレンスマニュアル :: 5.1.7 サーバー SQL モード
NO_ENGINE_SUBSTITUTION- 目的のストレージエンジンが利用できない場合にエラーが発生し、テーブルは作成または変更されません。
- MySQL :: MySQL 5.6 リファレンスマニュアル :: 5.1.7 サーバー SQL モード
個別に各種オプションを設定する
strict で一括で諸々の設定を有効にするのではなく個別にちゃんと設定したい場合は modes を追加することで可能です。
<?php
return [
// 途中省略~~~
'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' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
// 'strict' => true, // 厳密モードOFF
// 個別に設定
'modes' => [
'STRICT_TRANS_TABLES',
'NO_ZERO_IN_DATE',
'NO_ZERO_DATE',
'ERROR_FOR_DIVISION_BY_ZERO',
'NO_ENGINE_SUBSTITUTION'
],
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
// 途中省略~~~
];