Laravel -在比较之前,将查询参数转换为整数

时间:2022-10-16 00:14:30

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转换为and (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 

2 个解决方案

#1


4  

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”,那么它就不会是typecast,它不会匹配。

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

#2


1  

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甚至不会尝试将该字符串转换为integer。

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的核心开发人员那里得到了一些帮助,我认为你也应该做一些类似的事情来帮助你完成那些复杂的seaches:

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();
});

#1


4  

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”,那么它就不会是typecast,它不会匹配。

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

#2


1  

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甚至不会尝试将该字符串转换为integer。

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的核心开发人员那里得到了一些帮助,我认为你也应该做一些类似的事情来帮助你完成那些复杂的seaches:

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();
});