Laravel: Eloquent convierte el parámetro de consulta en un número entero antes de la comparación
Pregunta
Estoy intentando devolver una sola fila de una tabla basada en la clave principal.
$product = Product::where('id', '=', $idOrSKU)
->orWhere('sku', '=', $idOrSKU)
->take(1)->get();
Por alguna razón $idorSKU
se está convirtiendo a y (int)
antes de que ocurra la comparación.Por ejemplo, cuando $isOrSKU = "9dfghfd"
, se devuelve la fila con ID=9.¿Por qué es esto?¡No debería devolver nada en absoluto!¿Alguien puede explicar esto?
Aquí está el esquema de tabla relevante.
| id | int(10) unsigned | NO | PRI | NULL
| name | varchar(255) | NO | | NULL
| sku | varchar(255) | NO | | NULL
Solución
Esto está relacionado con la base de datos, no con Laravel, encasillando su cadena.Porque estás haciendo una consulta sobre un int(10)
columna, MySQL está cambiando a la fuerza su cadena de búsqueda a una int
, haciendo que su consulta se convierta en 9
.
Puedo confirmar lo siguiente:
$test1 = Test::find('1');
echo $test1->id; // gives 1
$test2 = Test::find('1example');
echo $test2->id; // gives 1
Por lo tanto su variable de 9dfghfd
porque encasillado a int (9)
.Pero si su variable fuera "df9ghfd", no estaría encasillada y no coincidiría.
Editar:El problema afecta a otras cosas, como el enlace del modelo de ruta:
domain.com/product/1
domain.com/product/1thisalsoworks // takes you to the page of ID 1
Abrí un ticket en Github para discutirlo más a fondo. - así que consulte aquí para obtener más información/discusión.
Pero en general el problema no es culpa directa de Laravel.
Editar:Parece que el problema afecta a GitHub. sí mismo:
Esto funciona: https://github.com/laravel/framework/issues/5254
Y esto también: https://github.com/laravel/framework/issues/5254typecast
Otros consejos
Resulta que aquí, usando PostgreSQL, funciona diferente a tu base de datos, cuando yo lo hago:
Route::any('test', function()
{
$code = '181rerum';
return Ad::where('id', $code)->orWhere('company_code', $code)->first();
});
Recibo este error:
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)
Entonces Laravel, sabiendo que es una columna de números enteros, la pasa directamente a la base de datos sin comillas, lo que genera una excepción en la base de datos, ya que PostgreSQL ni siquiera intentará convertir esa cadena a un número entero.
Entonces, incluso si recibes ayuda de los desarrolladores principales de Laravel, creo que siempre deberías hacer algo como esto para ayudarte a realizar esas búsquedas mixtas:
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();
});