Laravel - Eloquent converts a query parameter to an integer before comparison

I am trying to return a single row from a table based on a primary key.

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

For some reason, $idorSKU converted to and (int) before the comparison occurs. For example, when $isOrSKU = "9dfghfd" returns a string with identifier = 9. Why is this? He must not return anything! Can someone explain this?

Here is the corresponding table layout

 | id | int(10) unsigned | NO | PRI | NULL | name | varchar(255) | NO | | NULL | sku | varchar(255) | NO | | NULL 
+6
source share
2 answers

This is due to the database, not the Laravel attributing your string. Since you are executing the query in the int(10) column, mySQL forcibly changes your search string to int , causing your query to become 9 .

I can confirm the following:

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

Therefore your variable is 9dfghfd , because typecast is int (9) . But if your variable was "df9ghfd" - that would not be type casting, and it would not match.

Edit: The problem affects other things, such as route model binding:

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

I opened a ticket on Github to discuss it further - so check here for more info / discussion.

But overall, the problem is not a direct Laravel error.

Edit: it looks like the problem affects GitHub itself:

This works: https://github.com/laravel/framework/issues/5254

And so: https://github.com/laravel/framework/issues/5254typecast

+4
source

It turns out that here, using PostgreSQL, it works differently from your database when I do this:

 Route::any('test', function() { $code = '181rerum'; return Ad::where('id', $code)->orWhere('company_code', $code)->first(); }); 

I get this 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) 

So, Laravel, knowing that this is an integer column, passes it directly to the database without quotes, which throws a database exception, because PostgreSQL does not even try to use this row for an integer.

So, even if you get some help from the main Laravel developers, I think you should always do something like this to help you in these mixed situations:

 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(); }); 
+1
source

Source: https://habr.com/ru/post/973006/


All Articles