اذهب إلى المحتوى

السؤال

نشر

السلام عليكم,

Untitled.thumb.png.959a5b0adf339ce62cdc845cd6d35c28.png

في الصورة أعلاه من التوثيق الرسمي لإطار لارافل,

تقول بأنه إذا كان الصنف User لايستخدم العمود id كمفتاح أولي أو كنا نرغب بالعثور على النمودج المرتبط بإستعمال عمود آخر نمرر معامل ثالت لعمود من نفس الننمودج,

لم أفهم جيدا مايقصد بذلك,

مثلا لدينا جدول User :

            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->foreignId('current_team_id')->nullable();
            $table->string('profile_photo_path', 2048)->nullable();
            $table->timestamps();

ومررت أنا العمود  email كمعامل ثالت :

/**
 * Get the user that owns the phone.
 */
public function user()
{
    return $this->belongsTo(User::class, 'foreign_key', 'email');
}

ما الذي يؤثر على إسترجاع القيمة ؟

Phone::find($id)->user

وشكرا لكم جمعة مباركة

Recommended Posts

  • 0
نشر

في حال كان السجل من جدول النموذج Phone ينتمي لمستخدم واحد من جدول النموذج User، فطريقة الربط بين جدولين تكون بذكر المفتاح الأولي PK للمستخدم ضمن كل سجل من Phone لتكون الجداول كالتالي:

|  users  |             |   phones   |
-----------  يشير إلى   -------------
|   id    |    <--      |  user_id  |

المعامل الأول للتابع belongsTo هو اسم صنف النموذج الذي سيرتبط به النموذج الحالي، المعامل الثاني هو اسم المفتاح الخارجي FK من النموذج الحالي وهو user_id، أما المعامل الثالث هو المفتاح الأولي PK للجدول الذي نريد الربط معه، وآخر معاملين اختياريين عند عدم تمريرهما يمكن للارافل توقع اسماء تلك المفاتيح من اسم النموذج User، 

ما يشير إليه التوثيق هو الحالة التي يستخدم فيها الجدول الذي نريد الربط معه مفتاح أولي باسم مختلف عن id وهو ما يفترضه لارافل تلقائيًا عادةً، هنا يمكنك تمرير اسم المفتاح يدويًا حتى يعلم لارافل كيف يمكنه الاستعلام عن ذلك النموذج واتمام الربط بشكل صحيح :

|       users        |             |        phones        |
----------------------  يشير إلى   -----------------------
|   serial_number    |    <--      |  user_serial_number  |

فتمرر أسماء المفاتيح تلك يدويًا كالتالي:

public function user()
{
    return $this->belongsTo(User::class, 'user_serial_number', 'serial_number');
}

 

  • 0
نشر

أعرف كل ما قلته أخي حسان لكن سؤالي كان حول ما الذي يؤثر على القيمة المرجعة من دالة العلاقة (Phone::find($id)->user)في حال مررت عمود آخر مثل ماورد في التوثيق,

أعرف أن لارافل تلقائيا تفترض من خلال أسم اميثود أن المفتاح الرئيسي هو methodName_id وهاذي القيمة الأفتراضية للمعامل الثاني في حال إتبعنا العرف ,لكن الشيء الذي دعاني لطرح السؤال العبارة 

If the parent model does not use id as its primary key,// or you wish to find the associated model using a different column//

يقول لك إذا كان الصنف الأب لا يستخدم id كمفتاح رئيسي    أو    أو ترغب في العثور على النموذج المرتبط باستخدام عمود مختلف  

هنا لم أفهم جيدا مثلا مررت كمعامل ثالت عمود البريد الإلكتروني ('email'), و صنف المستخدمين في هذه الحالة يستخدم id كمفتاح رئيسي بشكل عادي معناه أنا الآن أرغي في العثور على النمودج المرتبط (User) بإستخدام عمود مختلف وهو email 

أرجوا أن تكون فهمتني

 


 

  • 0
نشر
بتاريخ الآن قال Brahim Semmani:

أعرف كل ما قلته أخي حسان لكن سؤالي كان حول ما الذي يؤثر على القيمة المرجعة من دالة العلاقة (Phone::find($id)->user)في حال مررت عمود آخر مثل ماورد في التوثيق,

أعرف أن لارافل تلقائيا تفترض من خلال أسم اميثود أن المفتاح الرئيسي هو methodName_id وهاذي القيمة الأفتراضية للمعامل الثاني في حال إتبعنا العرف ,لكن الشيء الذي دعاني لطرح السؤال العبارة 


If the parent model does not use id as its primary key,// or you wish to find the associated model using a different column//

يقول لك إذا كان الصنف الأب لا يستخدم id كمفتاح رئيسي    أو    أو ترغب في العثور على النموذج المرتبط باستخدام عمود مختلف  

هنا لم أفهم جيدا مثلا مررت كمعامل ثالت عمود البريد الإلكتروني ('email'), و صنف المستخدمين في هذه الحالة يستخدم id كمفتاح رئيسي بشكل عادي معناه أنا الآن أرغي في العثور على النمودج المرتبط (User) بإستخدام عمود مختلف وهو email 

أرجوا أن تكون فهمتني
 

هل حاولت ذلك ونجح الأمر؟ فالغرض من كون الحقل المشار إليه مفتاحًا أوليًا هو ضمان أن القيمة التي نشير إليها تابعة لسجل واحد فقط، بينما في حال أشرنا لأي حقل آخر قد يكون هناك عدة سجلات تملك قيمته وهنا سيحدث خطأ لأن علاقة belongsTo تفترض ضمنيًا وجود سجل واحد فقط من الجدول المقابل، بغض النظر عن استعمال unique فلارافل لا يتطلع على خصائص الجدول قبل الاستعلام ليتأكد من ذلك، ويعتمد على المطور في تحديد وتمرير أسماء حقول صحيحة

  • 0
نشر

المعامل الثالث هو إسم الحقل في النموذج الأب الذي يُشير إليه إسم الحقل الخاص بالمفتاح الثانوي في النموذج الإبن بالنسبة للعلاقة الموجودة بينهما.

بفرض أنه لدينا 3 نماذج User، Post، Comment:

users:
  - id (primary key)
  - ...
  - code

posts:
  - postID (primary key)
  - ...

comments:
  - commentID (primary key)
  - postID  	---> posts - postID
  - token 	---> users - code
  - ...

لو أردنا تعريف العلاقة post التي تربط بين النموذج Comment و النموذج Post من خلال العمود postID في الجدول comments الذي يُشير إلى العمود postID في الجدول posts و الذي يُعتبر في هذه الحالة مفتاح أولي سنكتب:

public function post() {
  return $this->belongsTo(Post::class, 'postID');
}

يجب تمرير المُعامل الثاني الذي يُشير إلى المفتاح الأجنبي، لأنه إذا لم نُمرره ستتوقع لارافل أن إسم الحقل هو post_id و ليس postID و سيحدث خطأ.

بخصوص المعامل الثالث ستكتشفه لارافل تلقائياً بشرط إعادة تحديد إسم المفتاح الأولي في النموذج Post:

protected $primaryKey = 'postID';

و إلا قم بتمرير الإسم في المعامل الثالث.

وجب الذكر أن توابع مثل find و غيرها تستخدم المفتاح الأولي في عملية الإستعلام و لارافل تعتبره id لذلك إن تم تغيير الإسم يجب إعادة تعريف الخاصية primaryKey كما تم الشرح أعلاه.

لو أردنا تعريف العلاقة owner التي تربط بين النموذج Comment و النموذج User من خلال العمود token في الجدول comments الذي يُشير إلى العمود code في الجدول users و الذي لا يُعتبر في هذه الحالة مفتاح أولي سنكتب:

public function owner() {
  return $this->belongsTo(User::class, 'token', 'code');
}

هنا يجب تمرير المُعاملات الثلاثة و إلا ستعتبر لارافل أن المُعامل الثاني هو owner_id، و المعامل الثالث هو id.

يُنصح دائما بإتباع نفس قواعد التسمية التي يتبعها الإطار و المتعارف عليها من طرف المطورين.

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...