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 الأساسيين، أعتقد أنه يجب عليك دائمًا القيام بشيء كهذا لمساعدتك في إجراء عمليات البحث المختلطة:
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();
});