2014-07-29 2 views
6

Я пытаюсь вернуть одну строку из таблицы на основе первичного ключа.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 
+0

Можете ли вы подтвердить, что SQL в настоящее время выполняются, делая ' dd (end (DB :: getQueryLog())); 'после вашего' get() '? – Unnawut

+0

он должен корректно проверять $ isOrSKU, вы используете кастинг любого типа? перед запросом или он преобразуется в int до того, как в вашем запросе нет проблем –

+0

Это столбец int, что вы ожидаете, когда попытаетесь найти строку на нем? –

ответ

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» - это не было бы приведением типов, и она не будет соответствовать.

Edit: проблема влияет на другие вещи, как модель маршрута связывания:

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.

Edit: кажется, этот вопрос затрагивает GitHub сам:

Это работает: https://github.com/laravel/framework/issues/5254

И так же это: https://github.com/laravel/framework/issues/5254typecast

+0

По-моему, это правильный ответ, но мне все еще трудно понять, почему ОП пытается найти строку в столбце int. Ожидает ли он, что база данных будет создавать исключение? –

+1

Я предполагаю, что у него есть поле поиска, где пользователи могут помещать * либо * «id», либо «sku» (т. Е. Номер детали). Поэтому он выполняет поиск с использованием ввода. Но поиск возвращает неверные результаты, если sku начинается с числа, потому что база данных соответствует ему ID – Laurence

+0

Однако @AntonioCarlosRibeiro - он все еще оставляет проблему разрешения неправильных маршрутов URL-адресов ... хотя это и не главная проблема - это все еще не оптимальный ... – Laurence

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 Я думаю, что вы должны всегда делать что-то вроде этого, чтобы помочь вам сделать эту смешанную 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(); 
}); 
+0

Как насчет привязки маршрутной модели, где вы не контролируете ввод? – Laurence

+0

Ничего. Кажется, проблема затрагивает всех, даже самого GitHub. См. Мой отредактированный ответ. – Laurence

Смежные вопросы