Laravel - Eloquent преобразует параметр запроса в целое число перед сравнением
Вопрос
Я пытаюсь вернуть одну строку из таблицы на основе первичного ключа.
$product = Product::where('id', '=', $idOrSKU)
->orWhere('sku', '=', $idOrSKU)
->take(1)->get();
По какой - то причине $idorSKU
преобразуется в и (int)
до того, как произойдет сравнение.Например, когда $isOrSKU = "9dfghfd"
, возвращается строка с идентификатором=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 Core Developers, я думаю, вы всегда должны делать что-то подобное, чтобы помочь вам сделать эти смешанные клетки:
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();
});
.