Laravel - Eloquent converte parâmetro de consulta em inteiro antes da comparação

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

  •  20-12-2019
  •  | 
  •  

Pergunta

Estou tentando retornar uma única linha de uma tabela com base na chave primária.

    $product = Product::where('id', '=', $idOrSKU)
        ->orWhere('sku', '=', $idOrSKU)
        ->take(1)->get();

Por algum motivo $idorSKU está sendo convertido para e (int) antes que a comparação aconteça.Por exemplo, quando $isOrSKU = "9dfghfd", a linha com ID=9 será retornada.Por que é isso?Não deve retornar nada!Alguém pode explicar isso?

Aqui está o esquema de tabela relevante

| id                         | int(10) unsigned | NO   | PRI | NULL      
| name                       | varchar(255)     | NO   |     | NULL                
| sku                        | varchar(255)     | NO   |     | NULL 
Foi útil?

Solução

Isso está relacionado ao banco de dados, não ao Laravel, ao digitar sua string.Porque você está fazendo uma consulta em um int(10) coluna, o MySQL está alterando forçosamente sua string de pesquisa para um int, fazendo com que sua consulta se torne 9.

Posso confirmar o seguinte:

$test1 = Test::find('1');
echo $test1->id; // gives 1

$test2 = Test::find('1example');
echo $test2->id; // gives 1

Portanto sua variável de 9dfghfd porque typecast para int (9).Mas se sua variável fosse "df9ghfd" - não seria typecast e não corresponderia.

Editar:O problema afeta outras coisas, como a vinculação do modelo de rota:

domain.com/product/1

domain.com/product/1thisalsoworks // takes you to the page of ID 1

Abri um ticket no Github para discutir mais sobre isso - então verifique aqui para mais informações/discussões.

Mas no geral o problema não é culpa direta do Laravel.

Editar:parece que o problema afeta o GitHub em si:

Isso funciona: https://github.com/laravel/framework/issues/5254

E o mesmo acontece com isso: https://github.com/laravel/framework/issues/5254typecast

Outras dicas

Acontece que aqui, usando PostgreSQL, funciona de forma diferente do seu banco de dados, quando eu faço:

Route::any('test', function()
{
    $code = '181rerum';

    return Ad::where('id', $code)->orWhere('company_code', $code)->first();
});

Eu recebo este erro:

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)

Então o Laravel, sabendo que é uma coluna inteira, está passando ela diretamente para o banco de dados sem aspas, o que gera uma exceção no banco de dados, já que o PostgreSQL nem tentará converter aquela string para inteiro.

Então, mesmo que você receba ajuda dos principais desenvolvedores do Laravel, acho que você deve sempre fazer algo assim para ajudá-lo a fazer essas pesquisas mistas:

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();
});
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top