Laravel - Eloquent 在比较之前将查询参数转换为整数
题
我试图根据主键从表中返回一行。
$product = Product::where('id', '=', $idOrSKU)
->orWhere('sku', '=', $idOrSKU)
->take(1)->get();
因为某些原因 $idorSKU
正在转换为 和 (int)
在比较发生之前。例如,当 $isOrSKU = "9dfghfd"
, ,返回 ID=9 的行。为什么是这样?它应该什么也不返回!有人可以解释一下吗?
这是相关的表格方案
| id | int(10) unsigned | NO | PRI | NULL
| name | varchar(255) | NO | | NULL
| sku | varchar(255) | NO | | NULL
解决方案
这与数据库有关,而不是 Laravel,对字符串进行类型转换。因为您正在执行查询 int(10)
列,mySQL 正在强制将您的搜索字符串更改为 int
, ,导致您的查询变成 9
.
我可以确认以下几点:
$test1 = Test::find('1');
echo $test1->id; // gives 1
$test2 = Test::find('1example');
echo $test2->id; // gives 1
因此你的变量 9dfghfd
因为类型转换为 int (9)
. 。但如果你的变量是“df9ghfd” - 它不会被类型转换,并且不会匹配。
编辑:该问题会影响其他方面,例如路由模型绑定:
domain.com/product/1
domain.com/product/1thisalsoworks // takes you to the page of ID 1
我已经在 Github 上开了一张票来进一步讨论它 - 所以请查看此处以获取更多信息/讨论。
但总的来说,这个问题并不是 Laravel 的直接错误。
编辑:看来这个问题影响了 GitHub 本身:
这有效: https://github.com/laravel/framework/issues/5254
这也是如此: https://github.com/laravel/framework/issues/5254typecast
其他提示
事实证明,这里使用 PostgreSQL,它的工作方式与你的数据库不同,当我这样做时:
Route::any('test', function()
{
$code = '181rerum';
return Ad::where('id', $code)->orWhere('company_code', $code)->first();
});
我收到此错误:
SQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input
syntax for integer: "181rerum" (SQL: select * from "ads" where
"id" = 181rerum or "company_code" = 181rerum limit 1)
因此,Laravel 知道它是一个整数列,因此不带引号将其直接传递到数据库,这会生成数据库异常,因为 PostgreSQL 甚至不会尝试将该字符串转换为整数。
因此,即使您从 Laravel 核心开发人员那里获得了一些帮助,我认为您也应该始终执行类似的操作来帮助您完成这些混合搜索:
Route::any('test/{id}', function($id)
{
/// You can always filter by a string here
$q = Ad::where('company_code', $id);
/// You just try to filter by id if the search string is entirely numeric
if (is_numeric($id))
{
$q->orWhere('id', $id);
}
return $q->first();
});