بلاگ/آموزش ایجاد رابطه یک به چند در مدل Eloquent لاراول
بهروز شده
آموزش ایجاد رابطه یک به چند در مدل Eloquent لاراول
مدل Eloquent یک ابزار پیادهسازی رابط اشیاء یا ORM است که به صورت پیشفرض در بستر لاراول وجود دارد. برای پیشبرد مراحل این آموزش، یک اپلیکیشن آزمایشی خواهیم داشت که مدلها و روابط جدید را در مورد آن به کار خواهیم گرفت. [caption id="attachment_15564" align="aligncenter" width="1000"] آموزش ایجاد...
1400/04/302552 بازدید
مدل Eloquent یک ابزار پیادهسازی رابط اشیاء یا ORM است که به صورت پیشفرض در بستر لاراول وجود دارد. برای پیشبرد مراحل این آموزش، یک اپلیکیشن آزمایشی خواهیم داشت که مدلها و روابط جدید را در مورد آن به کار خواهیم گرفت.
آموزش ایجاد رابطه یک به چند در مدل Eloquent لاراول
اپلیکیشن آزمایشی در این آموزش شامل یک جدول تکی پایگاه داده برای ذخیره لینکها میشود. در اینجا می خواهیم ساختار این پایگاه داده را به گونهای تغییر دهیم که یک جدول دوم در آن قرار گیرد. این جدول برای سازماندهی لینکها درون یک لیست به کار گرفته میشود.
در مورد لینکها و لیستهایی که در اینجا مورد استفاده قرار میگیرند باید گفت که هر کدام از لینکها میتواند تنها بخشی از یک لیست باشد. این در حالی است که هر لیست میتواند شامل چند لینک باشد. این همان رابطهای است که از آن به عنوان «یک به چند» یا one-to-many تأمین میشود.
رابطه یک به چند زمانی شکل میگیرد که به عنوان مثال، یک آیتم تیپ A میتواند به چندین آیتم در تیپ B متصل شود. در همین حال، خلاف این موضوع نمیتواند صادق باشد. یعنی هر کدام از آیتمهای تیپ B میتوانند تنها به یک آیتم از تیپ A مرتبط باشند. اگر بخواهیم این موضوع را به مدلهای کنونی اپلیکیشن آزمایشی منتقل کنیم، باید گفت که تیپ A لیست و تیپ B لینک است.
ایجاد مدل LinkList
برای شروع به کار، نیاز به ساخت یک مدل و جدول یک پایگاه داده شامل لیست لینکها داریم. سپس نوبت به بروزرسانی مدل «لینک» کنونی و جدول برای ایجاد ارتباط بین دو مدل میرسد. به دلیل اینکه واژه List برای مصارف داخلی PHP رزرو شده است، امکان نامگذاری مدل جدید با این واژه وجود ندارد. به جای آن میتوانید از عبارت LinkList استفاده کنید.
ابتدا دقت کنید که حتماً در دایرکتوری اپلیکیشن قرار داشته باشید.
در نتیجه، یک کلاس مدل جدید در دایرکتوری app/Model ساخته میشود.
php
1app/Model/LinkList.php
تغییر نام فرمان CLI مربوط به LinkList
اگر نگاهی به دایرکتوری app/Console/Commands داشته باشید، متوجه وجود یک کلاس با نام LinkList.php میشوید. این را نباید با مدل Eloquent که تولید کردهاید، اشتباه بگیرید. این کلاس شامل یک فرمان CLI است که تمام لینک های موجود در پایگاه داده را با artisan لیست میکند.
برای جلوگیری از اشتباهات در آینده، اکنون زمان خوبی برای تغییر نام این کلاس و فرمان مربوطه است. در اینجا از عنوان LinkShow برای این کلاس استفاده میکنیم که بیانگر عملکرد آن نیز هست. به منظور تغییر نام app/Console/Commands/LinkList.php، فرمان زیر را در ترمینال اجرا نمایید.
سپس فایل app/Console/Commands/LinkShow.php را در ویرایشگر کدتان باز کنید تا تغییر نام کلاس از LinkList به LinkShow را انجام دهید. همچنین تغییر فرمان از link:list به link:show باید مطابق زیر انجام گیرد. در نتیجه، فایل انتهایی باید شرایطی مشابه زیر داشته باشد.
php
1<?php23namespace App\Console\Commands;45use App\Models\Link;67use Illuminate\Console\Command;89class LinkShow extends Command1011{1213/**1415* The name and signature of the console command.1617*1819* @var string2021*/2223protected $signature = 'link:show';2425/**2627* The console command description.2829*3031* @var string3233*/3435protected $description = 'List links saved in the database';3637/**3839* Create a new command instance.4041*4243* @return void4445*/4647public function __construct()4849{5051parent::__construct();5253}5455/**5657* Execute the console command.5859*6061* @return int6263*/6465public function handle()6667{6869$headers = [ 'id', 'url', 'description' ];7071$links = Link::all(['id', 'url', 'description'])->toArray();7273$this->table($headers, $links);7475return 0;7677}7879}
پس از اتمام کار، فایل را ذخیره کرده و ببندید. برای بررسی صحت عملیات، فرمان جدید link:show artisan را اجرا نمایید.
php
1docker-compose exec app php artisan link:show
نمونه خروجی به صورت زیر خواهد بود.
php
1+----+-------------------------------------------------+----------------------------------+23| id | url | description |45+----+-------------------------------------------------+----------------------------------+67| 1 | https://digitalocean.com/community | DigitalOcean Community |89| 2 | https://digitalocean.com/community/tags/laravel | Laravel Tutorias at DigitalOcean |1011| 3 | https://digitalocean.com/community/tags/php | PHP Tutorials at DigitalOcean |1213+----+-------------------------------------------------+----------------------------------+
ایجاد یک Migration برای مدل LinkList
کلاس app/Model/LinkList.php که قبلاً با فرمان artisan make:model ایجاد کرده بودید، شامل یک کد generic برای یک کلاس جدید Eloquent است. برخلاف سایر ORM ها مانند Doctrine، Eloquent ساختار پایگاه داده را تغییر نداده و فقط بر روی خودِ دادهها کار میکند. مدلهای Eloquent معمولاً کمحجم هستند و مشخصات کلاس به صورت خودکار از ساختار جدول مدل گرفته میشود.
رویکرد مدیریت دادهها با Eloquent به این معنی است که نیازی به تنظیم هیچگونه مشخصات برای کلاس LinkList نیست. به این دلیل که این مشخصات از ساختار جدول پایگاه داده برای مدل گرفته میشوند.
عملیات ساختاری پایگاه داده در لاراول معمولاً به صورت Migration انجام میشوند. Migration ها این امکان را برای توسعهدهندگان ایجاد میکنند که بتوانند تغییرات ساختاری از جمله: ساخت، اصلاح و حذف جداول را برای پایگاه داده تعریف کنند.
اکنون به ایجاد یک Migration جدید برای تنظیم جدول lists در پایگاه داده میپردازیم.
ابزار خط فرمان artisan که به صورت پیشفرض با لاراول همراه است، شامل برخی روشهای سودمند برای استفاده از مؤلفههای جدید مانند کنترلرها، مدلها، Migration ها و ... است. برای ساخت یک Migration جدید با استفاده از artisan داریم:
این فرمان موجب ایجاد یک فایل جدید در دایرکتوری database/migrations در اپلیکیشن لاراول شما میشود. ضمن انیکه نام این فایل به صورت خودکار بر اساس زمان و ساعت، و عنوان Migration گرفته میشود. این فایل شامل کدی است که میتوانید آن را برای تنظیم جدول lists ویرایش نمایید.
با استفاده از ویرایشگر کد، فایل Migration تولید شده را باز کنید. این فایل در حال حاضر، ظاهری شبیه به زیر دارد.
php
1<?php23use Illuminate\Database\Migrations\Migration;45use Illuminate\Database\Schema\Blueprint;67use Illuminate\Support\Facades\Schema;89class CreateLinkListsTable extends Migration1011{1213/**1415* Run the migrations.1617*1819* @return void2021*/2223public function up()2425{2627Schema::create('link_lists', function (Blueprint $table) {2829$table->id();3031$table->timestamps();3233});3435}3637/**3839* Reverse the migrations.4041*4243* @return void4445*/4647public function down()4849{5051Schema::dropIfExists('link_lists');5253}5455}
Migration در صورتی که با فرمان artisan migrate اجرا شود، متد up() را به کار میگیرد. در اینجا تعریف جدول شما استفاده شده و به صورت پیش، یک فیلد شناسه کلید اولیه و دو فلید زمانی به صورت created_at و updated_at تولید میگردد. این فیلدها در هنگام ساخت و بروزرسانی مدل توسط Eloquent تکمیل میشوند. متد down() زمانی فراخوانی میشود که migration به وسیله artisan rollback بازگردانده شود. در این حالت، کد برای حذف جدول یا بازگردانی تغییرات ساختاری اجرا میشود.
در اینجا، متد up برای دربرداشتن فیلدهای زیر تغییر داده میشود:
title: رشتهای که بیانگر عنوان لیست است.
description: رشتهای که بیانگر توضیح یک لیست است.
slug: یک رشته منحصر به فرد و کوتاه بر اساس عنوان که معمولاًبرای ساخت آدرسهای اینترنتی ساده و قابلفهم استفاده میشود.
در رابطه «یک به چند»، سمت «چند» که در اینجا جدول links است، حاوی ستون مرجع یا کلید خارجی برای المان دیگر (مطابق با جدول Lists) خواهد بود. به این معنا که شما برای وارد کردن یک فیلد مرجع برای اتصال به جدول Lists، باید جدول links را ویرایش کنید.
از طرف دیگر، جدول list نیازی به هیچگونه فیلدی برای ارجاع لینکهایش ندارد.
محتوای کنونی فایل migration را با کد زیر جایگزین نمایید.
php
1<?php23use Illuminate\Database\Migrations\Migration;45use Illuminate\Database\Schema\Blueprint;67use Illuminate\Support\Facades\Schema;89class CreateLinkListsTable extends Migration1011{1213/**1415* Run the migrations.1617*1819* @return void2021*/2223public function up()2425{2627Schema::create('link_lists', function (Blueprint $table) {2829$table->id();3031$table->timestamps();3233$table->string('title', 60);3435$table->string('slug', 60)->unique();3637$table->text('description')->nullable();3839});4041}4243/**4445* Reverse the migrations.4647*4849* @return void5051*/5253public function down()5455{5657Schema::dropIfExists('link_lists');5859}6061}
وقتی کارتان تمام شد، فایل را ذخیره کنید.
بروزرسانی عملیات Migration برای جدول Links
حالا نوبت به باز کردن فایل کنونی Migration برای جدول Links در ویرایشگر کد میرسد. در پروژه آزمایشی، این فایل را در آدرس زیر پیدا خواهید کرد.
php
12020_11_18_165241_create_links_table.php
ابتدا از ابزار use برای ارجاع به نام کامل کلاس LinkList در ابتدای فایل استفاده کنید.
متد foreignIdFor() موجب ایجاد یک ستون «کلید خارجی» برای مدل Eloquent خواهد شد. برای این منظور از سیستم نامگذاری پیشفرض مرتبط با فیلد کلید اولیه جدول استفاده میشود.
بعد از اتمام این کارها، کلاس کامل migration به صورت زیر خواهد بود.
php
1<?php23use Illuminate\Database\Migrations\Migration;45use Illuminate\Database\Schema\Blueprint;67use Illuminate\Support\Facades\Schema;89use App\Models\LinkList;1011class CreateLinksTable extends Migration1213{1415/**1617* Run the migrations.1819*2021* @return void2223*/2425public function up()2627{2829Schema::create('links', function (Blueprint $table) {3031$table->id();3233$table->string('url', 200);3435$table->text('description');3637$table->foreignIdFor(LinkList::class);3839$table->timestamps();4041});4243}4445/**4647* Reverse the migrations.4849*5051* @return void5253*/5455public function down()5657{5859Schema::dropIfExists('links');6061}6263}
پس از ویرایش، فایل را ذخیره کنید. حالا پایگاه داده را پاک کنید و با اجرای دوباره فرمان migration، ساختار پایگاه داده با فایلهای بروز شده migration، بازسازی نمایید.
هم اکنون جداول پایگاه داده تنظیم شدهاند. با این وجود، هنوز نیاز به تنظیم مدلهای Eloquent برای تعریف روابط بین آنها داریم.
در مدل List که یک طرف رابطه محسوب میشود، یک متد جدید با نام links تنظیم میکنیم. این متد به عنوان یک پروکسی برای دسترسی به لینکهای مرتبط با هر لیست عمل خواهد کرد. چنین کاری با استفاده از متد hasMany از کلاس مادر Illuminate\Database\Eloquent\Model انجام میشود.
در ویرایشگر کد، فایل app/Model/LinkList.php را باز کنید. سپس کد کنونی را با محتوای زیر جایگزین نمایید.
حالا فایل را ذخیره کنید.
در مرحله بعد، ویرایش طرف «چند» رابطه انجام میشود تا یک ارجاع به مدل List در آن وارد گردد. در نتیجه، لینکها میتوانند به لیستهای مربوطه دسترسی داشته باشند. چنین کاری با استفاده از متد belongsTo از کلاس مادر Model صورت میگیرد. این روش برای برای تعریف سمت برگشتی رابطه یک به چند استفاده میشود.
مدل Link را در ویرایشگر کدتان باز کنید.
php
1app/Model/Link.php23 45خطوط کد زیر را در فایل Link.php جایگزین نمایید.6789<?php1011namespace App\Models;1213use Illuminate\Database\Eloquent\Model;1415class Link extends Model1617{1819public function link_list()2021{2223return $this->belongsTo(LinkList::class);2425}2627}
پس از اتمام کار، فایل را ذخیره کنید.
پس از بروزرسانی دو مدل، پایگاه داده شما به طور کامل تنظیم شده و البته، در حال حاضر خالی است. مدل Eloquent برای وارد کردن رکوردهای جدید به پایگاه نیز به کار گرفته میشود که از شما دعوت میکنیم مطالب آینده وبلاگ آریانت را در این زمینه دنبال کنید.