Laravel - Eloquent 在比较前将查询参数转换为整数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25008004/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel - Eloquent converts query parameter to integer before comparison
提问by Jen Zhang
I'm trying to return a single row from a table based on the primary key.
我试图从基于主键的表中返回一行。
$product = Product::where('id', '=', $idOrSKU)
->orWhere('sku', '=', $idOrSKU)
->take(1)->get();
For some reason $idorSKU
is being converted to and (int)
before the comparison happens. For example, when $isOrSKU = "9dfghfd"
, the row with ID=9 is returned. Why is this? It should return nothing at all! Can someone explain this?
出于某种原因$idorSKU
,正在转换为 和(int)
比较发生之前。例如,当 时$isOrSKU = "9dfghfd"
,返回 ID=9 的行。为什么是这样?它应该什么都不返回!有人可以解释一下吗?
Here is the relevant table scheme
这是相关的表方案
| id | int(10) unsigned | NO | PRI | NULL
| name | varchar(255) | NO | | NULL
| sku | varchar(255) | NO | | NULL
采纳答案by Laurence
This is related to the database, not Laravel, typecasting your string. Because you are doing a query on an int(10)
column, mySQL is forcably changing your search string to an int
, causing your query to become 9
.
这与数据库有关,而不是 Laravel,对字符串进行类型转换。因为您正在对int(10)
列进行查询,所以 mySQL 强行将您的搜索字符串更改为int
,从而导致您的查询变为9
.
I can confirm the following:
我可以确认以下几点:
$test1 = Test::find('1');
echo $test1->id; // gives 1
$test2 = Test::find('1example');
echo $test2->id; // gives 1
Therefore your variable of 9dfghfd
because typecast to int (9)
. But if your variable was "df9ghfd" - it would not be typecast, and it wont match.
因此你的变量9dfghfd
因为类型转换为int (9)
. 但是如果你的变量是“df9ghfd”——它不会被类型转换,也不会匹配。
Edit: The issue affects other things, like Route model binding:
编辑:这个问题会影响其他事情,比如路由模型绑定:
domain.com/product/1
domain.com/product/1thisalsoworks // takes you to the page of ID 1
I've opened a ticket on Github to discuss it further- so check here for further information/discussion.
我已经在 Github 上开了一张票来进一步讨论它- 所以在这里查看更多信息/讨论。
But overall the issue is not a direct fault of Laravel.
但总的来说,这个问题并不是 Laravel 的直接错误。
Edit: seems the issue affects GitHub itself:
编辑:似乎问题影响 GitHub本身:
This works: https://github.com/laravel/framework/issues/5254
这有效:https: //github.com/laravel/framework/issues/5254
And so does this: https://github.com/laravel/framework/issues/5254typecast
这样做也是如此:https: //github.com/laravel/framework/issues/5254typecast
回答by Antonio Carlos Ribeiro
Turns out that here, using PostgreSQL, it works differently from your database, when I do:
事实证明,在这里,使用 PostgreSQL,它的工作方式与您的数据库不同,当我这样做时:
Route::any('test', function()
{
$code = '181rerum';
return Ad::where('id', $code)->orWhere('company_code', $code)->first();
});
I get this error:
我收到此错误:
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)
So Laravel, knowing it is a integer column, is passing it directly to the database without quotes, which generates a database exception, since PostgreSQL will not even try to cast that string to integer.
所以 Laravel 知道它是一个整数列,直接将它传递给数据库而不带引号,这会产生一个数据库异常,因为 PostgreSQL 甚至不会尝试将该字符串转换为整数。
So, even if you get some help from Laravel core developers I think you should always do something like this to help you do those mixed seaches:
所以,即使你从 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();
});