روابط یک به چند - پست‌ها و پروفایل کاربری

Posts and User Profiles

Laravel 7.0: روابط یک به چند - پست ها و پروفایل کاربری (قسمت 23)

در جلسه قبل توضیح دادم که رابطه کاربر با پست هایش از نوع رابطه یک به یک نیست. هر کاربر چندین پست خواهد داشت و تمام پست ها متعلق به یک کاربر خواهند بود بنابراین رابطه ما از نوع یک به چند (One to Many Relationship) می باشد. البته روابطی که از آن حرف می زنم روابط عادی هستند. توضیحات روابط Polymorphic را در فصل ضمیمه همین دوره پیدا می کنید. از آنجایی که ساخت model ها را یاد گرفته ایم به راحتی در ترمینال می گوییم:

php artisan make:model Post -m

با این کار model و migration ما ساخته می شوند. در قدم اول به migration خود می رویم (نامی شبیه به create post table خواهد داشت). در آنجا در متد up می گوییم:

public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id')->references('id')->on('users')->onDelete('cascade');
        $table->string('caption');
        $table->string('image');
        $table->timestamps();
    });
}

به صورت خودکار در این فایل کلاس ما وجود خواهد داشت (مثل دفعات قبل) بنابراین ما فقط باید ستون ها را مشخص کنیم که من مشخص کرده ام. ابتدا یک ستون foreignId را داریم که نامش را user_id قرار داده ام و از ساختار همیشگی مان برای مشخص کردن ستون جدول پدر استفاده کرده ام. یعنی گفته ام این ستون (user_id) به ستونی به نام id در جدول پدر (users) اشاره می کند و اگر ردیف متناظر در جدول پدر حذف شود باید ردیف های مربوطه در این جدول نیز حذف شوند (cascade). تمام این موارد را در جلسات قبل بررسی کرده بودیم. سپس یک ستون به نام caption داریم که همان توضیح عکس است و در آخر ستونی به نام image داریم که مسیرِ تصویرِ پست در آن ذخیره می شود. امیدوارم به اندازه ای با دنیای وب آشنا باشید که بدانید تصویر مستقیما در پایگاه داده ذخیره نمی شود بلکه همیشه آدرس آن را ذخیره می کنیم. حالا که کدهایمان را تکمیل کرده ایم دستور زیر را اجرا می کنیم تا این فایل نیز migrate کند:

php artisan migrate

با این کار جدول جدید ما در پایگاه داده اضافه می شود (ایجاد تغییرات در سطح پایگاه داده) و حالا نوبت به تعریف این روابط در سطح لاراول است. در ابتدا باید به User.php برویم (Model مربوط به کاربران) و بگوییم که هر کاربر می تواند چندین پست داشته باشد:

// بقیه کدها //
public function posts()
{
    return $this->hasMany(Post::class);
}

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

این کد به جای hasOne (یکی دارد) از hasMany (چند تا دارد) استفاده می کند چرا که هر کاربر چندین پست خواهد داشت به همین دلیل s جمع را نیز برای post قرار داده ام (نام متد را می گویم). یادتان باشد که قوانین توضیح داده شده در جلسات قبل هنوز هم پابرجاست؛ یعنی لاراول به صورت پیش فرض نام کلاس (User) را گرفته و رشته id_ را به انتهای آن اضافه خواهد کرد تا ستون foreign key را تشخیص بدهد (ما نام آن ستون را در فایل migration چه گذاشتیم؟ user_id) و برای این کار از نوشتار snake case استفاده می کند یعنی تمام حروف به صورت کوچک نوشته شده و با آندرلاین از هم جدا می شوند. اگر case های مختلف نوشتاری در برنامه نویسی را نمی دانید به تصویر زیر توجه کنید:

case های مختلف در برنامه نویسی
case های مختلف در برنامه نویسی

اگر می خواهید Foreign key را خودتان مشخص کنید مثل hasOne می توانید آرگومان دوم را به عنوان Foreign key پاس بدهید. حالا به model پست ها یعنی Post.php می رویم و می گوییم:

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

یعنی هر پست، متعلق به یک کلاس به نام User (کاربر) است. از آنجایی که این کار را قبلا هم انجام داده ایم چیز جدیدی برای گفتن وجود ندارد.

در مرحله بعدی باید دکمه ای را اضافه کنیم که به ما اجازه پست گذاشتن بدهد. پست گذاشتن از طریق وب سایت اینستاگرام ممکن نیست اما ما می خواهیم لاراول را تمرین کنیم بنابراین مهم نیست. برای انجام این کار وارد فایل home.blade.php می شویم و یک لینک ساده را در کنار username کاربر قرار می دهیم:

<div class="d-flex justify-content-between align-items-baseline">
    <h1>{{ $user->username }}</h1>
    <a href="#">Add New Post</a>
</div>

بعد از اضافه کردن تگ <a>، کلاس های بوت استرپ بالا را نیز به div اصلی اضافه کرده ام تا لینک ما به سمت راست صفحه برود. سوال اینجاست که اگر کاربر روی این لینک کلید کند، چه چیزی را باید ببیند؟ اینستاگرام برای نمایش پست ها معمولا در url خود از ساختار زیر استفاده می کند:

https://www.instagram.com/p/CBx8UDjprzQ/

یعنی پس از اینستاگرام یک p داریم که مخفف post است و سپس id یکتا و منحصر به فرد آن پست ذکر می شود. از آنجایی که قرار است تا حد ممکن شبیه به اینستاگرام طراحی کنیم، من نیز از ساختاری شبیه به همین ساختار برای نمایش پست ها استفاده می کنم اما برای ایجاد پست دکمه ای نداریم بنابراین باید یک URL فرضی برای خودمان ایجاد کنیم. مثلا:

website.com/p/create

اگر یادتان باشد قرار شد در طول این دوره از قرار داد های RESTful برای مدیریت منابع استفاده کنیم:

قرارداد نام گذاری و مدیریت route ها بر اساس RESTful resource controller
قرارداد نام گذاری و مدیریت route ها بر اساس RESTful resource controller

همانطور که می بینید create یک مسیر GET است (ردیف دوم تصویر بالا) که فرمی را برایتان نمایش خواهد داد، سپس این فرم خودش POST استفاده می کند (ردیف سوم از تصویر بالا) تا داده های جدید (پست کاربر) را در پایگاه داده ذخیره کند. با این حساب در جلسه بعد باید شروع به ساختن route جدید و فرم هایمان کنیم.

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

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.