مدل Eloquent یک ابزار پیاده‌سازی رابط اشیاء یا ORM است که به صورت پیش‌فرض در بستر لاراول وجود دارد. برای پیش‌برد مراحل این آموزش، یک اپلیکیشن آزمایشی خواهیم داشت که مدل‌ها و روابط جدید را در مورد آن به کار خواهیم گرفت.

آموزش ایجاد رابطه یک به چند در مدل Eloquent لاراول

آموزش ایجاد رابطه یک به چند در مدل Eloquent لاراول

اپلیکیشن آزمایشی در این آموزش شامل یک جدول تکی پایگاه داده برای ذخیره لینک‌ها می‌شود. در اینجا می خواهیم ساختار این پایگاه داده را به گونه‌ای تغییر دهیم که یک جدول دوم در آن قرار گیرد. این جدول برای سازماندهی لینک‌ها درون یک لیست به کار گرفته می‌شود.

در مورد لینک‌ها و لیست‌هایی که در اینجا مورد استفاده قرار می‌گیرند باید گفت که هر کدام از لینک‌ها می‌تواند تنها بخشی از یک لیست باشد. این در حالی است که هر لیست می‌تواند شامل چند لینک باشد. این همان رابطه‌ای است که از آن به عنوان «یک به چند» یا one-to-many تأمین می‌شود.

رابطه یک به چند زمانی شکل می‌گیرد که به عنوان مثال، یک آیتم تیپ A می‌تواند به چندین آیتم در تیپ B متصل شود. در همین حال، خلاف این موضوع نمی‌تواند صادق باشد. یعنی هر کدام از آیتم‌های تیپ B می‌توانند تنها به یک ‌آیتم از تیپ A مرتبط باشند. اگر بخواهیم این موضوع را به مدل‌های کنونی اپلیکیشن آزمایشی منتقل کنیم، باید گفت که تیپ A لیست و تیپ B لینک است.

ایجاد مدل LinkList

برای شروع به کار، نیاز به ساخت یک مدل و جدول یک پایگاه داده شامل لیست لینک‌ها داریم. سپس نوبت به بروزرسانی مدل «لینک» کنونی و جدول برای ایجاد ارتباط بین دو مدل می‌رسد. به دلیل اینکه واژه List برای مصارف داخلی PHP رزرو شده است، امکان نامگذاری مدل جدید با این واژه وجود ندارد. به جای آن می‌توانید از عبارت LinkList استفاده کنید.

ابتدا دقت کنید که حتماً در دایرکتوری اپلیکیشن قرار داشته باشید.


cd ~/landing-laravel

با استفاده از artisan، یک مدل جدید ایجاد می‌کنیم.


docker-compose exec app php artisan make:model LinkList

در نتیجه، یک کلاس مدل جدید در دایرکتوری app/Model ساخته می‌شود.


app/Model/LinkList.php

تغییر نام فرمان CLI مربوط به LinkList

اگر نگاهی به دایرکتوری app/Console/Commands داشته باشید، متوجه وجود یک کلاس با نام LinkList.php می‌شوید. این را نباید با مدل Eloquent که تولید کرده‌اید، اشتباه بگیرید. این کلاس شامل یک فرمان CLI است که تمام لینک های موجود در پایگاه داده را با artisan لیست می‌کند.

برای جلوگیری از اشتباهات در آینده، اکنون زمان خوبی برای تغییر نام این کلاس و فرمان مربوطه است. در اینجا از عنوان LinkShow برای این کلاس استفاده می‌کنیم که بیانگر عملکرد آن نیز هست. به منظور تغییر نام app/Console/Commands/LinkList.php، فرمان زیر را در ترمینال اجرا نمایید.


mv app/Console/Commands/LinkList.php app/Console/Commands/LinkShow.php

سپس فایل app/Console/Commands/LinkShow.php را در ویرایشگر کدتان باز کنید تا تغییر نام کلاس از LinkList به LinkShow را انجام دهید. همچنین تغییر فرمان از link:list به link:show باید مطابق زیر انجام گیرد. در نتیجه، فایل انتهایی باید شرایطی مشابه زیر داشته باشد.


<?php

namespace App\Console\Commands;

use App\Models\Link;

use Illuminate\Console\Command;

class LinkShow extends Command

{

/**

* The name and signature of the console command.

*

* @var string

*/

protected $signature = 'link:show';

/**

* The console command description.

*

* @var string

*/

protected $description = 'List links saved in the database';

/**

* Create a new command instance.

*

* @return void

*/

public function __construct()

{

parent::__construct();

}

/**

* Execute the console command.

*

* @return int

*/

public function handle()

{

$headers = [ 'id', 'url', 'description' ];

$links = Link::all(['id', 'url', 'description'])->toArray();

$this->table($headers, $links);

return 0;

}

}

پس از اتمام کار، فایل را ذخیره کرده و ببندید. برای بررسی صحت عملیات، فرمان جدید link:show artisan را اجرا نمایید.


docker-compose exec app php artisan link:show

نمونه خروجی به صورت زیر خواهد بود.


+----+-------------------------------------------------+----------------------------------+

| id | url                                             | description                      |

+----+-------------------------------------------------+----------------------------------+

| 1  | https://digitalocean.com/community              | DigitalOcean Community           |

| 2  | https://digitalocean.com/community/tags/laravel | Laravel Tutorias at DigitalOcean |

| 3  | https://digitalocean.com/community/tags/php     | PHP Tutorials at DigitalOcean    |

+----+-------------------------------------------------+----------------------------------+

ایجاد یک 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 داریم:


docker-compose exec app php artisan make:migration create_link_lists_table

خروجی


Created Migration: 2021_07_07_152554_create_link_lists_table

این فرمان موجب ایجاد یک فایل جدید در دایرکتوری database/migrations در اپلیکیشن لاراول شما می‌‌شود. ضمن انیکه نام این فایل به صورت خودکار بر اساس زمان و ساعت، و عنوان Migration گرفته می‌شود. این فایل شامل کدی است که می‌توانید آن را برای تنظیم جدول lists ویرایش نمایید.

با استفاده از ویرایشگر کد، فایل Migration تولید شده را باز کنید. این فایل در حال حاضر، ظاهری شبیه به زیر دارد.


<?php

use Illuminate\Database\Migrations\Migration;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Support\Facades\Schema;

class CreateLinkListsTable extends Migration

{

/**

* Run the migrations.

*

* @return void

*/

public function up()

{

Schema::create('link_lists', function (Blueprint $table) {

$table->id();

$table->timestamps();

});

}

/**

* Reverse the migrations.

*

* @return void

*/

public function down()

{

Schema::dropIfExists('link_lists');

}

}

Migration در صورتی که با فرمان artisan migrate اجرا شود، متد up() را به کار می‌گیرد. در اینجا تعریف جدول شما استفاده شده و به صورت پیش، یک فیلد شناسه کلید اولیه و دو فلید زمانی به صورت created_at و updated_at تولید می‌گردد. این فیلدها در هنگام ساخت و بروزرسانی مدل توسط Eloquent تکمیل می‌شوند. متد down() زمانی فراخوانی می‌شود که migration به وسیله artisan rollback بازگردانده شود. در این حالت، کد برای حذف جدول یا بازگردانی تغییرات ساختاری اجرا می‌شود.

در اینجا، متد up برای دربرداشتن فیلدهای زیر تغییر داده می‌شود:

  • title: رشته‌ای که بیانگر عنوان لیست است.
  • description: رشته‌ای که بیانگر توضیح یک لیست است.
  • slug: یک رشته منحصر به فرد و کوتاه بر اساس عنوان که معمولاً‌برای ساخت آدرس‌های اینترنتی ساده و قابل‌فهم استفاده می‌شود.

در رابطه «یک به چند»، سمت «چند» که در اینجا جدول links است، حاوی ستون مرجع یا کلید خارجی برای المان دیگر (مطابق با جدول Lists) خواهد بود. به این معنا که شما برای وارد کردن یک فیلد مرجع برای اتصال به جدول Lists، باید جدول links را ویرایش کنید.

از طرف دیگر، جدول list نیازی به هیچ‌گونه فیلدی برای ارجاع لینک‌هایش ندارد.

محتوای کنونی فایل migration را با کد زیر جایگزین نمایید.


<?php

use Illuminate\Database\Migrations\Migration;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Support\Facades\Schema;

class CreateLinkListsTable extends Migration

{

/**

* Run the migrations.

*

* @return void

*/

public function up()

{

Schema::create('link_lists', function (Blueprint $table) {

$table->id();

$table->timestamps();

$table->string('title', 60);

$table->string('slug', 60)->unique();

$table->text('description')->nullable();

});

}

/**

* Reverse the migrations.

*

* @return void

*/

public function down()

{

Schema::dropIfExists('link_lists');

}

}

وقتی کارتان تمام شد، فایل را ذخیره کنید.

 بروزرسانی عملیات Migration برای جدول Links

حالا نوبت به باز کردن فایل کنونی Migration برای جدول Links در ویرایشگر کد می‌رسد. در پروژه آ‌زمایشی، این فایل را در آ‌درس زیر پیدا خواهید کرد.


2020_11_18_165241_create_links_table.php

ابتدا از ابزار use برای ارجاع به نام کامل کلاس LinkList در ابتدای فایل استفاده کنید.


…

use Illuminate\Support\Facades\Schema;

use App\Models\LinkList;

...

سپس خطوط زیر را در تعریف جدول، بعد از متد up  و قبل از شروع فیلد description وارد نمایید.


$table->text('description');

$table->foreignIdFor(LinkList::class);

متد foreignIdFor() موجب ایجاد یک ستون «کلید خارجی» برای مدل Eloquent  خواهد شد. برای این منظور از سیستم نامگذاری پیش‌فرض مرتبط با فیلد کلید اولیه جدول استفاده می‌شود.

بعد از اتمام این کارها، کلاس کامل migration به صورت زیر خواهد بود.


<?php

use Illuminate\Database\Migrations\Migration;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Support\Facades\Schema;

use App\Models\LinkList;

class CreateLinksTable extends Migration

{

/**

* Run the migrations.

*

* @return void

*/

public function up()

{

Schema::create('links', function (Blueprint $table) {

$table->id();

$table->string('url', 200);

$table->text('description');

$table->foreignIdFor(LinkList::class);

$table->timestamps();

});

}

/**

* Reverse the migrations.

*

* @return void

*/

public function down()

{

Schema::dropIfExists('links');

}

}

پس از ویرایش، فایل را ذخیره کنید. حالا پایگاه داده را پاک کنید و با اجرای دوباره فرمان migration، ساختار پایگاه داده با فایل‌های بروز شده migration، بازسازی نمایید.


docker-compose exec app php artisan db:wipe

docker-compose exec app php artisan migrate

تنظیم روابط مدل Eloquent

هم اکنون جداول پایگاه داده تنظیم شده‌اند. با این وجود، هنوز نیاز به تنظیم مدل‌های Eloquent برای تعریف روابط بین آنها داریم.

در مدل List که یک طرف رابطه محسوب می‌شود، یک متد جدید با نام links تنظیم می‌کنیم. این متد به عنوان یک پروکسی برای دسترسی به لینک‌های مرتبط با هر لیست عمل خواهد کرد. چنین کاری با استفاده از متد hasMany از کلاس مادر Illuminate\Database\Eloquent\Model انجام می‌شود.

در ویرایشگر کد، فایل app/Model/LinkList.php را باز کنید. سپس کد کنونی را با محتوای زیر جایگزین نمایید.


<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Database\Eloquent\Model;

class LinkList extends Model

{

use HasFactory;

public function links()

{

return $this->hasMany(Link::class);

}

}

حالا فایل را ذخیره کنید.

در مرحله بعد، ویرایش طرف «چند» رابطه انجام می‌شود تا یک ارجاع به مدل List در آن وارد گردد. در نتیجه، لینک‌ها می‌توانند به لیست‌های مربوطه دسترسی داشته باشند. چنین کاری با استفاده از متد belongsTo از کلاس مادر Model صورت می‌گیرد. این روش برای برای تعریف سمت برگشتی رابطه یک به چند استفاده می‌شود.

مدل Link را در ویرایشگر کدتان باز کنید.


app/Model/Link.php

&nbsp;

خطوط کد زیر را در فایل Link.php جایگزین نمایید.

[php]

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Link extends Model

{

public function link_list()

{

return $this->belongsTo(LinkList::class);

}

}

پس از اتمام کار، فایل را ذخیره کنید.

پس از بروزرسانی دو مدل، پایگاه داده شما به طور کامل تنظیم شده و البته، در حال حاضر خالی است. مدل Eloquent برای وارد کردن رکوردهای جدید به پایگاه نیز به کار گرفته می‌شود که از شما دعوت می‌کنیم مطالب آینده  وبلاگ آریانت را در این زمینه دنبال کنید.