Laravelはもちろん(Laravel に限らず PHP で PDO を使っている場合)DBの数値型カラムが文字列型で返ってくる事があります。
なぜこのような自動型変換が起こるかというと、PHPのMySQL PDOドライバの仕様だそうです。
ただし、次の条件の時に
1. mysqlのドライバーが 「mysqlnd(MySQLNaitiveDriver)」である。
2. PDO::ATTR_EMULATE_PREPARES属性が false である。
自動型変換を回避することが可能です。
phpinfo() の出力から確認しましょう。
または次のコマンドで mysqlnd が表示されれば使用されています
php -m | grep mysqlnd
$dbh = \DB::connection()->getPdo();
$attributes = [
"ATTR_CLIENT_VERSION",
"ATTR_EMULATE_PREPARES",
"ATTR_STRINGIFY_FETCHES",
"ATTR_AUTOCOMMIT",
"ATTR_ERRMODE",
"ATTR_CASE",
"ATTR_ORACLE_NULLS",
"ATTR_PERSISTENT",
"ATTR_PREFETCH",
"ATTR_SERVER_INFO",
"ATTR_SERVER_VERSION",
"ATTR_TIMEOUT",
];
foreach ($attributes as $val) {
echo "PDO::{$val}: ";
try {
echo $dbh->getAttribute(constant("PDO::{$val}")) . "<br>\n";
} catch (\Exception $e) {
echo "error not supported !!! <br>\n";
}
}
結果例
PDO::ATTR_CLIENT_VERSION: mysqlnd 5.0.12-dev - 20150407 - $Id: 38fea24f2847fa7519001be390c98ae0acafe387 $
PDO::ATTR_EMULATE_PREPARES: 0
↑ この例の場合は(mysqlnd有り)(PDO::ATTR_EMULATE_PREPARES: 0)なので、数値型カラムの値は数値型で返ってきます。
レンタルサーバで(おそらく昔の)XSERVERとかは mysqlnd が入ってないので、自動型変換は必ず起きると思われます。
Laravel の モデルには $casts プロパティがあり、これに型をセットすると、Eloquentが結果セットを返すときに、明示的にその方にキャストしてくれます。
/**
* 明示的なdb型変換
*
*/
protected $casts = [
'id' => 'int' ,
'shop_id' => 'int' ,
'is_active' => 'int' ,
'price_no' => 'int' ,
];
次のコードを実行してください。自動で生成します。( int のみ。) コントローラーから次のようなメソッドを実行します
/**
* Laravelのモデルの Casts を生成する
*
* [int, integer, real, float, double, string, bool, boolean, object, array, json, collection, date, datetime]
*
*
*/
public function getModelCasts(string $table_name = '')
{
print "<hr>\n";
echo "<strong>{$table_name}</strong>";
print "<hr>\n";
echo "<pre style='margin: 20px; border: solid #eee 1px;'>";
print <<< 'DOC_END'
/**
* カラムの明示的なdb型変換
*
*/
protected $casts = [
DOC_END;
$query = "SHOW COLUMNS FROM {$table_name}";
foreach (\DB::select($query) as $column) {
if (preg_match("{^int}", $column->Type)) {echo "'{$column->Field}' => 'int' ,\n";}
elseif (preg_match("{^tinyint}", $column->Type)) {echo "'{$column->Field}' => 'int' ,\n";}
elseif (preg_match("{^smallint}", $column->Type)) {echo "'{$column->Field}' => 'int' ,\n";}
elseif (preg_match("{^mediumint}", $column->Type)) {echo "'{$column->Field}' => 'int' ,\n";}
elseif (preg_match("{^bigint}", $column->Type)) {echo "'{$column->Field}' => 'int' ,\n";}
elseif (preg_match("{^(text|char|varchar)}", $column->Type)) {}
elseif (preg_match("{^}", $column->Type)) {}
else {
dump($column);
}
}
print <<< 'DOC_END'
];
DOC_END;
echo "</pre>";
print "<hr>\n";
}