تعریف رابطه‌ی جدول‌ها در Modelها

The Relationship of Tables in Models

0
82
Laravel 7.0: تعریف رابطه ی جدول ها در Model ها (قسمت 21)

در قسمت قبل موفق شدیم که با استفاده از لایه پایگاه داده لاراول، در فایل های migration خود با استفاده از یک foreign key دو جدول را به هم متصل کنیم اما هنوز چیزی برای Model ایجاد شده ننوشته ایم. در حالت عادی (دور از فضای لاراول) زمانی که از PHP و MySQL برای چنین کاری استفاده می کنیم، باید دو مرحله را طی کنیم:

  • در مرحله اول با استفاده از کد های SQL یا با استفاده از PHPMyAdmin یک پایگاه داده می ساختیم و جدول های خودمان را با key های دلخواه به هم متصل می کردیم. این قسمت در سمت پایگاه داده انجام می شد و روابط جدول ها را مشخص می کرد.
  • در مرحله دوم باید حواسمان به نوشتن کوئری هایمان بود تا با استفاده از این foreign key هر دو جدول را هدف بگیریم. به طور مثال از دستورات join استفاده می کردیم (امیدوارم با MySQL آشنا باشید).

در لاراول هم باید همین منطق را پیاده کنیم اما به جای نوشتن دستورات SQL ساده از Eloquent استفاده می کنیم (مانند جلسه قبل). با این تفاسیر در این جلسه نوبت به پیاده سازی مرحله دوم یا نوشتن Model ما می رسد. نکته مهم در تمام این عملیات این است:

هر کاربر یک پروفایل دارد و هر پروفایل متعلق به یک کاربر است (رابطه یک به یک – One to One)

در روابط یک به یک دو کلیدواژه بسیار مهم داریم:

  • hasOne به معنی «دارد» یا «یک … دارد»
  • belongsTo به معنی «متعلق است به …»

در قدم اول به Profile.php یا همان فایل Model خود برای جدول profiles می رویم. ما می خواهیم بگوییم هر پروفایل به یک کاربر تعلق دارد بنابراین از belongsTo استفاده می کنیم:

class Profile extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

من در اینجا یک متد به نام user تعریف کرده ام که خصوصیتی به نام belongsTo را برمی گرداند و به آن کلاس User را داده ام (این کلاس در model آن یعنی User.php قرار دارد). در ضمن class:: یکی از قابلیت های php است و ربطی به لاراول ندارد. این دستور به شما اجازه می دهد که مسیر دقیق یک کلاس ها در namespace های مختلف به دست بیاورید. اگر کد بالا را به صورت انگلیسی ساده و نه کد بخوانید می شود: this$ (اشاره به این کلاس و پروفایل کاربر) متعلق است به کلاس User (که یک model است).

البته نکته بسیار مهمی وجود دارد که باید به آن توجه کنید. نام این متد در اینجا بسیار مهم است. لاراول نام این متد را برداشته و پسوند id_ را به آن اضافه می کند تا نام ستون foreign key ما را تشخیص دهد. بنابراین نام متد (user) گرفته شده و user_id به عنوان نام foreign key ما شناخته می شود و اگر نام این متد را چیز دیگری گذاشته بودیم با خطا روبرو می شدیم. به همین دلیل است که من در جلسه قبل نام user_id را به عنوان ستون foreign key انتخاب کردم. اگر شما دوست دارید که نام این متد را چیز دیگری بگذارید و خودتان به صورت دستی به لاراول بگویید که نام foreign key چیست، باید آن را به عنوان آرگومان دوم به belongsTo پاس بدهید (البته من چنین کاری نمی کنم):

return $this->belongsTo(User::class, 'YOUR_FOREIGN_KEY');

تا اینجا کاری کرده ایم که مشخص شده است هر پروفایل متعلق به یک کاربر است بنابراین می توانیم بر اساس یک پروفایل، یک کاربر را پیدا کنیم اما هنوز برعکس آن را انجام نداده ایم. یعنی هنوز مشخص نکرده ایم که هر کاربر یک پروفایل دارد. اگر در برنامه خود نیازی به دریافت پروفایل بر اساس کاربر ندارید نیازی به ادامه نیست اما برنامه ما آن را لازم دارد بنابراین به فایل Model آن (User.php) رفته و در انتهای کلاس متد خودمان را اضافه می کنیم:

// بقیه کد ها //
protected $casts = [
    'email_verified_at' => 'datetime',
];

public function profile()
{
    return $this->hasOne(Profile::class);
}
// بقیه کد ها //

من نام این متد را profile گذاشته ام و باز هم به صورت پیش فرض لاراول در نظر می گیرد که ستون user_id همان foreign key ما است. اگر شما می خواهید به صورت دستی آن را مشخص کنید مثل قبل باید آرگومان دوم را به آن پاس بدهید.

در مرحله بعدی باید یک پروفایل را به صورت دستی به پایگاه داده اضافه کنیم (در آینده این کار را به صورت دستی انجام نمی دهیم اما فعلا برای یادگیری ایرادی ندارد). برای این کار یا از PHPMyAdmin استفاده کنید یا از Tinker. روش PHPMyAdmin بسیار ساده است و فقط باید یک ردیف در جدول profiles اضافه کنید بنابراین آن را توضیح نمی دهیم اما اگر دوست دارید روش Tinker را بدانید، کد هایش را برایتان قرار می دهیم. در ترمینال خود می گوییم:

php artisan tinker
$profile = new \App\Profile();
$profile->title = 'Cool Title';
$profile->description = 'description';
$profile->user_id = 1;
$profile->save();

اگر یادتان باشد در جلسات قبل که در مورد mass assignment صحبت کردیم به شما گفتم که روش دیگر اضافه کردن کاربر به پایگاه داده و استفاده از متد ()save چطور است. این همان روش است.

با اجرا کد بالا خطا می گیرید. چرا؟ به کد زیر در فایل migration نگاه کنید:

$table->foreignId('user_id')->references('id')->on('users')->onDelete('cascade');

من onDelete را روی cascade گذاشته ام تا اگر ردیفی از جدول پدر (Users) حذف شد، ردیف متناظر با آن از جدول فرزند (profiles) نیز حذف شود چرا که اگر کاربری حذف شود قطعا پروفایلش هم باید حذف شود. مشکل اینجاست که برای onUpdate چیزی نگفته ایم و مقدار پیش فرض آن روی Restrict (غیر مجاز) است. یعنی چه؟ یعنی کسی اجازه ندارد foreign key را به صورت مستقیم ویرایش کند (ما در کد بالا profile->user_id$ را به صورت دستی تعریف کرده ایم که نوعی ویرایش محسوب می شود).

روش استاندارد کار در MySQL همین کار است که اجازه ویرایش foreign key ها را به صورت مستقیم ندهید مگر در موارد خاص که foreign key شما روی id تنظیم نشده است و الی آخر. بنابراین من قصد ندارم onUpdate را نیز روی cascade بگذارم اما این کد ها را برایتان قرار دادم تا با آن آشنا شوید و اگر خواستید migration را دوباره انجام بدهید مشکلی نیست. باید کد migration را به شکل زیر تغییر دهید:

$table->foreignId('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');

من شخصا ردیف جدید را از PHPMyAdmin اضافه کردم تا راحت باشم. حالا دوباره وارد Tinker شوید (php artisan tinker) و دستور زیر را اجرا کنید:

$profile->user

با اجرای این دستور نتیجه زیر را می بینید:

App\User {#3998
     id: 1,
     name: "Amir",
     email: "myEmail@email.com",
     username: "AmirZM",
     email_verified_at: null,
     created_at: "2020-06-26 06:38:31",
     updated_at: "2020-06-26 06:38:31",
   }

آیا متوجه شدید؟ ما profile$ را داشتیم و کاربر (user) را از آن پیدا کردیم! انگار که کاربر درون profile$ است! برای تست می توانیم کد زیر را اجرا کنیم:

$profile

با این کار نتیجه زیر را می گیریم:

مشاهده این قسمت تنها برای افرادی که اشتراک جادویی داشته باشند، امکان‌پذیر است. با خرید اشتراک، به همه مطالب جادویی روکسوپلاس دسترسی داشته باشید.

ما مقداری برای url ننوشته بودیم بنابراین null است. امیدوارم این جلسه را درک کرده باشید.

ترتیبی که روکسو برای یادگیری مطالب سری ساخت اینستاگرام با Laravel 7 به شما توصیه می‌کند:

ارسال دیدگاه

لطفا دیدگاه خود را وارد کنید!
نام خود را وارد کنید