Laravel - Eloquent преобразует параметр запроса в целое число перед сравнением

StackOverflow https://stackoverflow.com//questions/25008004

  •  20-12-2019
  •  | 
  •  

Вопрос

Я пытаюсь вернуть одну строку из таблицы на основе первичного ключа.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top