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

时间:2014-07-29 03:56:22

标签: php 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 

2 个答案:

答案 0 :(得分:4)

这与数据库有关,而不是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

I've opened a ticket on Github to discuss it further - 请点击此处查看更多信息/讨论。

但总体而言,这个问题不是Laravel的直接错误。

编辑:似乎问题会影响GitHub 本身

这有效:https://github.com/laravel/framework/issues/5254

这样做:https://github.com/laravel/framework/issues/5254typecast

答案 1 :(得分:1)

事实证明,在这里,当我这样做时,使用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();
});