نسخه:

الکوئنت: شروع کردن

معرفی

لاراول شامل Eloquent است، یک نقشه‌بردار شی رابطه‌ای (ORM) که تعامل با پایگاه داده شما را لذت‌بخش می‌کند. هنگام استفاده از Eloquent، هر جدول پایگاه داده یک "مدل" مربوطه دارد که برای تعامل با آن جدول استفاده می شود. علاوه بر بازیابی رکوردها از جدول پایگاه داده، مدل های Eloquent به شما اجازه می دهد تا رکوردها را از جدول وارد، به روز رسانی و حذف کنید.

قبل از شروع، حتماً یک اتصال پایگاه داده را در config/database.php فایل پیکربندی برنامه خود پیکربندی کنید. برای اطلاعات بیشتر در مورد پیکربندی پایگاه داده خود، اسناد پیکربندی پایگاه داده را بررسی کنید .

بوت کمپ لاراول

اگر به تازگی با لاراول آشنا شده اید، به راحتی وارد Bootcamp لاراول شوید . Laravel Bootcamp شما را در ساخت اولین برنامه Laravel با استفاده از Eloquent راهنمایی می کند. این یک راه عالی برای بازدید از همه چیزهایی است که لاراول و Eloquent ارائه می دهند.

تولید کلاس های مدل

برای شروع، بیایید یک مدل Eloquent ایجاد کنیم. مدل ها معمولاً در app\Models دایرکتوری زندگی می کنند و Illuminate\Database\Eloquent\Model کلاس را گسترش می دهند. می توانید از make:model دستور Artisan برای ایجاد یک مدل جدید استفاده کنید:

php artisan make:model Flight

اگر می خواهید هنگام ایجاد مدل، یک انتقال پایگاه داده --migration ایجاد کنید، می توانید از گزینه یا استفاده کنید -m :

php artisan make:model Flight --migration

هنگام تولید یک مدل، می‌توانید انواع مختلف کلاس‌های دیگر مانند کارخانه‌ها، بذرها، سیاست‌ها، کنترل‌کننده‌ها و درخواست‌های فرم را ایجاد کنید. علاوه بر این، این گزینه ها ممکن است برای ایجاد چندین کلاس به طور همزمان ترکیب شوند:

# Generate a model and a FlightFactory class...
php artisan make:model Flight --factory
php artisan make:model Flight -f
 
# Generate a model and a FlightSeeder class...
php artisan make:model Flight --seed
php artisan make:model Flight -s
 
# Generate a model and a FlightController class...
php artisan make:model Flight --controller
php artisan make:model Flight -c
 
# Generate a model, FlightController resource class, and form request classes...
php artisan make:model Flight --controller --resource --requests
php artisan make:model Flight -crR
 
# Generate a model and a FlightPolicy class...
php artisan make:model Flight --policy
 
# Generate a model and a migration, factory, seeder, and controller...
php artisan make:model Flight -mfsc
 
# Shortcut to generate a model, migration, factory, seeder, policy, controller, and form requests...
php artisan make:model Flight --all
php artisan make:model Flight -a
 
# Generate a pivot model...
php artisan make:model Member --pivot
php artisan make:model Member -p

بررسی مدل ها

گاهی اوقات تعیین تمام ویژگی‌ها و روابط موجود یک مدل تنها با مرور کد آن دشوار است. در عوض، model:show دستور Artisan را امتحان کنید، که یک نمای کلی راحت از تمام ویژگی ها و روابط مدل ارائه می دهد:

php artisan model:show Flight

قراردادهای مدل الکوئنت

مدل های تولید شده توسط make:model دستور در دایرکتوری قرار می گیرند app/Models . بیایید یک کلاس مدل پایه را بررسی کنیم و برخی از قراردادهای کلیدی Eloquent را مورد بحث قرار دهیم:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class Flight extends Model
{
// ...
}

نام جدول

پس از نگاهی اجمالی به مثال بالا، ممکن است متوجه شده باشید که ما به Eloquent نگفته ایم که کدام جدول پایگاه داده با Flight مدل ما مطابقت دارد. طبق قرارداد، نام جمع «snake case» به عنوان نام جدول استفاده می شود، مگر اینکه نام دیگری به صراحت مشخص شده باشد. بنابراین، در این مورد، Eloquent فرض می‌کند که Flight مدل رکوردها را در flights جدول ذخیره می‌کند، در حالی که یک AirTrafficController مدل رکوردها را در یک جدول ذخیره می‌کند air_traffic_controllers .

اگر جدول پایگاه داده مربوطه مدل شما با این قرارداد مطابقت ندارد، می‌توانید به صورت دستی نام جدول مدل را با تعریف یک table ویژگی روی مدل مشخص کنید:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class Flight extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'my_flights';
}

کلیدهای اصلی

Eloquent همچنین فرض خواهد کرد که جدول پایگاه داده مربوط به هر مدل دارای یک ستون کلید اصلی به نام است id . در صورت لزوم، می توانید یک $primaryKey ویژگی محافظت شده بر روی مدل خود تعریف کنید تا ستون دیگری را مشخص کنید که به عنوان کلید اصلی مدل شما عمل می کند:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class Flight extends Model
{
/**
* The primary key associated with the table.
*
* @var string
*/
protected $primaryKey = 'flight_id';
}

علاوه بر این، Eloquent فرض می‌کند که کلید اصلی یک مقدار صحیح افزایشی است، به این معنی که Eloquent به طور خودکار کلید اصلی را به یک عدد صحیح می‌فرستد. اگر می خواهید از یک کلید اصلی غیر افزایشی یا غیر عددی استفاده کنید، باید یک $incrementing ویژگی عمومی در مدل خود تعریف کنید که روی false :

<?php
 
class Flight extends Model
{
/**
* Indicates if the model's ID is auto-incrementing.
*
* @var bool
*/
public $incrementing = false;
}

اگر کلید اصلی مدل شما یک عدد صحیح نیست، باید یک $keyType ویژگی محافظت شده در مدل خود تعریف کنید. این ویژگی باید دارای مقدار زیر باشد string :

<?php
 
class Flight extends Model
{
/**
* The data type of the primary key ID.
*
* @var string
*/
protected $keyType = 'string';
}

کلیدهای اصلی "کامپوزیت".

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

کلیدهای UUID و ULID

به جای استفاده از اعداد صحیح افزایش خودکار به عنوان کلیدهای اصلی مدل Eloquent خود، ممکن است به جای آن از UUID استفاده کنید. UUID ها شناسه های آلفا-عددی منحصر به فرد جهانی هستند که 36 کاراکتر طول دارند.

اگر می‌خواهید مدلی از کلید UUID به جای کلید عدد صحیح افزایش‌دهنده خودکار استفاده کند، می‌توانید از Illuminate\Database\Eloquent\Concerns\HasUuids ویژگی روی مدل استفاده کنید. البته، باید مطمئن شوید که مدل دارای یک ستون کلید اولیه معادل UUID است :

use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Model;
 
class Article extends Model
{
use HasUuids;
 
// ...
}
 
$article = Article::create(['title' => 'Traveling to Europe']);
 
$article->id; // "8f8e8478-9035-4d23-b9a7-62f4d2612ce5"

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

شما می توانید فرآیند تولید UUID را برای یک مدل معین با تعریف یک newUniqueId روش روی مدل لغو کنید. علاوه بر این، می‌توانید با تعریف uniqueIds روشی روی مدل، مشخص کنید که کدام ستون‌ها باید UUID دریافت کنند:

use Ramsey\Uuid\Uuid;
 
/**
* Generate a new UUID for the model.
*/
public function newUniqueId(): string
{
return (string) Uuid::uuid4();
}
 
/**
* Get the columns that should receive a unique identifier.
*
* @return array<int, string>
*/
public function uniqueIds(): array
{
return ['id', 'discount_code'];
}

در صورت تمایل، می توانید به جای UUID از "ULIDs" استفاده کنید. ULID ها مشابه UUID ها هستند. با این حال، آنها تنها 26 کاراکتر طول دارند. مانند UUID های مرتب شده، ULID ها از نظر واژگانی برای نمایه سازی کارآمد پایگاه داده قابل مرتب سازی هستند. برای استفاده از ULID، باید Illuminate\Database\Eloquent\Concerns\HasUlids از ویژگی مدل خود استفاده کنید. همچنین باید مطمئن شوید که مدل دارای یک ستون کلید اولیه معادل ULID است :

use Illuminate\Database\Eloquent\Concerns\HasUlids;
use Illuminate\Database\Eloquent\Model;
 
class Article extends Model
{
use HasUlids;
 
// ...
}
 
$article = Article::create(['title' => 'Traveling to Asia']);
 
$article->id; // "01gd4d3tgrrfqeda94gdbtdk5c"

مهر زمانی

به‌طور پیش‌فرض، Eloquent انتظار دارد created_at و updated_at ستون‌هایی در جدول پایگاه داده مربوطه مدل شما وجود داشته باشد. Eloquent به طور خودکار مقادیر این ستون ها را هنگام ایجاد یا به روز رسانی مدل ها تنظیم می کند. اگر نمی‌خواهید این ستون‌ها به‌طور خودکار توسط Eloquent مدیریت شوند، باید یک $timestamps خاصیت را در مدل خود با مقدار زیر تعریف کنید false :

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class Flight extends Model
{
/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timestamps = false;
}

اگر می‌خواهید قالب مُهرهای زمانی مدل خود را سفارشی کنید، $dateFormat ویژگی را روی مدل خود تنظیم کنید. این ویژگی تعیین می کند که چگونه ویژگی های تاریخ در پایگاه داده و همچنین فرمت آنها در زمانی که مدل به یک آرایه یا JSON سریال می شود، ذخیره شود:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class Flight extends Model
{
/**
* The storage format of the model's date columns.
*
* @var string
*/
protected $dateFormat = 'U';
}

اگر می‌خواهید نام ستون‌هایی را که برای ذخیره مُهرهای زمانی استفاده می‌شوند سفارشی کنید، می‌توانید در مدل خود ثابت‌هایی را CREATED_AT تعریف کنید: UPDATED_AT

<?php
 
class Flight extends Model
{
const CREATED_AT = 'creation_date';
const UPDATED_AT = 'updated_date';
}

اگر می‌خواهید عملیات مدل را بدون updated_at تغییر مُهر زمانی آن انجام دهید، می‌توانید در بسته‌ای که به withoutTimestamps روش داده شده است، روی مدل کار کنید:

Model::withoutTimestamps(fn () => $post->increment(['reads']));

اتصالات پایگاه داده

به طور پیش فرض، همه مدل های Eloquent از اتصال پایگاه داده پیش فرض که برای برنامه شما پیکربندی شده است استفاده می کنند. اگر می خواهید اتصال متفاوتی را مشخص کنید که باید هنگام تعامل با یک مدل خاص استفاده شود، باید یک $connection ویژگی روی مدل تعریف کنید:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class Flight extends Model
{
/**
* The database connection that should be used by the model.
*
* @var string
*/
protected $connection = 'sqlite';
}

مقادیر مشخصه پیش فرض

به‌طور پیش‌فرض، یک نمونه مدل تازه نمونه‌سازی‌شده حاوی هیچ مقدار مشخصه نخواهد بود. اگر می‌خواهید مقادیر پیش‌فرض را برای برخی از ویژگی‌های مدل خود تعریف کنید، می‌توانید یک $attributes ویژگی در مدل خود تعریف کنید. مقادیر مشخصه قرار داده شده در $attributes آرایه باید در قالب خام و "قابل ذخیره" خود باشند، به گونه ای که گویی فقط از پایگاه داده خوانده شده اند:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class Flight extends Model
{
/**
* The model's default values for attributes.
*
* @var array
*/
protected $attributes = [
'options' => '[]',
'delayed' => false,
];
}

پیکربندی سختگیری Eloquent

لاراول چندین روش ارائه می دهد که به شما امکان می دهد رفتار و "سخت" Eloquent را در موقعیت های مختلف پیکربندی کنید.

ابتدا، preventLazyLoading روش یک آرگومان بولی اختیاری را می پذیرد که نشان می دهد آیا باید از بارگذاری تنبل جلوگیری شود. به عنوان مثال، ممکن است بخواهید فقط بارگذاری تنبل را در محیط های غیر تولیدی غیرفعال کنید تا محیط تولید شما به طور عادی به کار خود ادامه دهد حتی اگر یک رابطه بارگذاری تنبل به طور تصادفی در کد تولید وجود داشته باشد. به طور معمول، این روش باید در boot روش برنامه شما فراخوانی شود AppServiceProvider :

use Illuminate\Database\Eloquent\Model;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Model::preventLazyLoading(! $this->app->isProduction());
}

همچنین، می‌توانید به لاراول دستور دهید تا هنگام تلاش برای پر کردن یک ویژگی پر نشدنی با فراخوانی متد، یک استثنا ایجاد کند preventSilentlyDiscardingAttributes . این می تواند به جلوگیری از خطاهای غیرمنتظره در طول توسعه محلی هنگام تلاش برای تنظیم یک ویژگی که به آرایه مدل اضافه نشده است کمک کند fillable :

Model::preventSilentlyDiscardingAttributes(! $this->app->isProduction());

بازیابی مدل ها

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

use App\Models\Flight;
 
foreach (Flight::all() as $flight) {
echo $flight->name;
}

پرس و جوهای ساختمان

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

$flights = Flight::where('active', 1)
->orderBy('name')
->take(10)
->get();

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

مدل های با طراوت

اگر قبلاً نمونه‌ای از مدل Eloquent دارید که از پایگاه داده بازیابی شده است، می‌توانید با استفاده از متدهای fresh و مدل را «رفرش» کنید refresh . این fresh روش مدل را از پایگاه داده بازیابی می کند. نمونه مدل موجود تحت تأثیر قرار نخواهد گرفت:

$flight = Flight::where('number', 'FR 900')->first();
 
$freshFlight = $flight->fresh();

این refresh روش مدل موجود را با استفاده از داده های تازه از پایگاه داده هیدراته می کند. علاوه بر این، تمام روابط بارگذاری شده آن نیز به روز می شوند:

$flight = Flight::where('number', 'FR 900')->first();
 
$flight->number = 'FR 456';
 
$flight->refresh();
 
$flight->number; // "FR 900"

مجموعه ها

همانطور که دیدیم، متدهای Eloquent چندین رکورد را از پایگاه داده دوست دارند all و بازیابی می کنند. get با این حال، این روش ها یک آرایه PHP ساده را بر نمی گرداند. در عوض، یک نمونه از Illuminate\Database\Eloquent\Collection بازگشت داده می شود.

کلاس Eloquent کلاس Collection پایه لاراول را گسترش می دهد Illuminate\Support\Collection ، که انواع روش های مفید را برای تعامل با مجموعه داده ها ارائه می دهد. به عنوان مثال، این reject روش ممکن است برای حذف مدل‌ها از یک مجموعه بر اساس نتایج یک بسته شدن فراخوانی استفاده شود:

$flights = Flight::where('destination', 'Paris')->get();
 
$flights = $flights->reject(function (Flight $flight) {
return $flight->cancelled;
});

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

از آنجایی که تمام مجموعه‌های لاراول واسط‌های تکرارپذیر PHP را پیاده‌سازی می‌کنند، می‌توانید مجموعه‌ها را طوری حلقه بزنید که انگار یک آرایه هستند:

foreach ($flights as $flight) {
echo $flight->name;
}

نتایج تکه تکه شدن

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

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

use App\Models\Flight;
use Illuminate\Database\Eloquent\Collection;
 
Flight::chunk(200, function (Collection $flights) {
foreach ($flights as $flight) {
// ...
}
});

اولین آرگومان ارسال شده به chunk متد، تعداد رکوردهایی است که می خواهید در هر "تکه" دریافت کنید. بسته شدن به عنوان آرگومان دوم برای هر تکه ای که از پایگاه داده بازیابی می شود فراخوانی می شود. یک کوئری پایگاه داده برای بازیابی هر تکه از رکوردهای ارسال شده تا بسته شدن اجرا می شود.

اگر نتایج روش را chunk بر اساس ستونی فیلتر می‌کنید که در حین تکرار روی نتایج نیز به‌روزرسانی می‌کنید، باید از chunkById روش استفاده کنید. استفاده از chunk روش در این سناریوها می تواند منجر به نتایج غیرمنتظره و متناقض شود. در داخل، این روش همیشه مدل هایی را با ستونی بزرگتر از آخرین مدل در قطعه قبلی chunkById بازیابی می کند : id

Flight::where('departed', true)
->chunkById(200, function (Collection $flights) {
$flights->each->update(['departed' => false]);
}, $column = 'id');

خرد کردن با استفاده از مجموعه های تنبل

این روش lazy مشابه متد عمل می کند به chunk این معنا که در پشت صحنه، پرس و جو را به صورت تکه ای اجرا می کند. با این حال، این روش به جای اینکه هر بخش را مستقیماً به یک callback ارسال کند، مدل‌های Eloquent lazy مسطح را برمی‌گرداند LazyCollection که به شما امکان می‌دهد با نتایج به‌عنوان یک جریان واحد تعامل داشته باشید:

use App\Models\Flight;
 
foreach (Flight::lazy() as $flight) {
// ...
}

اگر نتایج روش را lazy بر اساس ستونی فیلتر می‌کنید که در حین تکرار روی نتایج نیز به‌روزرسانی می‌کنید، باید از lazyById روش استفاده کنید. در داخل، این روش همیشه مدل هایی را با ستونی بزرگتر از آخرین مدل در قطعه قبلی lazyById بازیابی می کند : id

Flight::where('departed', true)
->lazyById(200, $column = 'id')
->each->update(['departed' => false]);

می توانید نتایج را بر اساس ترتیب نزولی با id استفاده از lazyByIdDesc روش فیلتر کنید.

نشانگرها

مشابه lazy روش، این cursor روش ممکن است برای کاهش قابل توجه مصرف حافظه برنامه شما هنگام تکرار ده ها هزار رکورد مدل Eloquent استفاده شود.

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

از آنجایی که این cursor روش در هر زمان تنها یک مدل Eloquent را در حافظه نگه می دارد، نمی تواند مشتاق بارگذاری روابط باشد. اگر نیاز به بارگذاری مشتاقانه روابط دارید، به جای آن از روش استفاده lazy کنید .

در داخل، این روش از ژنراتورهای cursor PHP برای پیاده سازی این قابلیت استفاده می کند:

use App\Models\Flight;
 
foreach (Flight::where('destination', 'Zurich')->cursor() as $flight) {
// ...
}

cursor یک نمونه را برمی گرداند Illuminate\Support\LazyCollection . مجموعه‌های تنبل به شما این امکان را می‌دهند که از بسیاری از روش‌های جمع‌آوری موجود در مجموعه‌های معمولی لاراول استفاده کنید در حالی که هر بار فقط یک مدل را در حافظه بارگذاری می‌کنید:

use App\Models\User;
 
$users = User::cursor()->filter(function (User $user) {
return $user->id > 500;
});
 
foreach ($users as $user) {
echo $user->id;
}

اگرچه این cursor روش از حافظه بسیار کمتری نسبت به یک پرس و جو معمولی استفاده می کند (فقط با نگه داشتن یک مدل Eloquent در حافظه در یک زمان)، همچنان در نهایت حافظه آن تمام می شود. این به این دلیل است که درایور PDO PHP به صورت داخلی تمام نتایج جستجوی خام را در بافر خود ذخیره می کند . اگر با تعداد بسیار زیادی رکورد Eloquent سر و کار دارید، به جای آن از روش استفاده lazy کنید .

سوالات فرعی پیشرفته

فرعی انتخاب می کند

Eloquent همچنین پشتیبانی پیشرفته subquery را ارائه می دهد که به شما امکان می دهد اطلاعات را از جداول مرتبط در یک پرس و جو استخراج کنید. به عنوان مثال، بیایید تصور کنیم که یک جدول پرواز destinations و یک جدول از flights مقصد داریم. جدول flights شامل arrived_at ستونی است که نشان می دهد پرواز چه زمانی به مقصد رسیده است.

با استفاده از قابلیت subquery در دسترس برای سازنده پرس و جو select و addSelect روش ها، می توانیم همه destinations و نام پروازی را که اخیراً به آن مقصد رسیده است را با استفاده از یک جستجو انتخاب کنیم:

use App\Models\Destination;
use App\Models\Flight;
 
return Destination::addSelect(['last_flight' => Flight::select('name')
->whereColumn('destination_id', 'destinations.id')
->orderByDesc('arrived_at')
->limit(1)
])->get();

سفارش فرعی

علاوه بر این، تابع سازنده پرس orderBy و جو از سوالات فرعی پشتیبانی می کند. در ادامه استفاده از مثال پرواز خود، ممکن است از این قابلیت برای مرتب‌سازی همه مقصدها بر اساس آخرین پرواز به آن مقصد استفاده کنیم. باز هم، این ممکن است در حین اجرای یک کوئری پایگاه داده انجام شود:

return Destination::orderByDesc(
Flight::select('arrived_at')
->whereColumn('destination_id', 'destinations.id')
->orderByDesc('arrived_at')
->limit(1)
)->get();

بازیابی مدل های منفرد / مصالح

علاوه بر بازیابی همه رکوردهای منطبق با یک پرس و جو، می توانید رکوردهای تکی را نیز با استفاده از روش های find ، first یا بازیابی کنید firstWhere . این متدها به جای برگرداندن مجموعه ای از مدل ها، یک نمونه مدل را برمی گرداند:

use App\Models\Flight;
 
// Retrieve a model by its primary key...
$flight = Flight::find(1);
 
// Retrieve the first model matching the query constraints...
$flight = Flight::where('active', 1)->first();
 
// Alternative to retrieving the first model matching the query constraints...
$flight = Flight::firstWhere('active', 1);

گاهی اوقات ممکن است بخواهید عمل دیگری را انجام دهید اگر نتیجه ای یافت نشد. متدهای findOr و firstOr یک نمونه مدل منفرد را برمی گرداند یا اگر نتیجه ای یافت نشد، بسته شدن داده شده را اجرا می کند. مقدار بازگردانده شده توسط بسته شدن نتیجه روش در نظر گرفته می شود:

$flight = Flight::findOr(1, function () {
// ...
});
 
$flight = Flight::where('legs', '>', 3)->firstOr(function () {
// ...
});

موارد استثنا یافت نشد

گاهی اوقات ممکن است بخواهید در صورت پیدا نشدن یک مدل استثنایی ایجاد کنید. این به ویژه در مسیرها یا کنترلرها مفید است. متدهای findOrFail و firstOrFail اولین نتیجه پرس و جو را بازیابی خواهند کرد. با این حال، اگر هیچ نتیجه ای یافت نشد، یک Illuminate\Database\Eloquent\ModelNotFoundException پرتاب می شود:

$flight = Flight::findOrFail(1);
 
$flight = Flight::where('legs', '>', 3)->firstOrFail();

در صورت ModelNotFoundException عدم شناسایی، یک پاسخ HTTP 404 به طور خودکار به مشتری ارسال می شود:

use App\Models\Flight;
 
Route::get('/api/flights/{id}', function (string $id) {
return Flight::findOrFail($id);
});

بازیابی یا ایجاد مدل ها

این firstOrCreate روش سعی خواهد کرد یک رکورد پایگاه داده را با استفاده از جفت های ستون / مقدار داده شده پیدا کند. اگر مدل در پایگاه داده یافت نشد، یک رکورد با ویژگی های حاصل از ادغام آرگومان آرایه اول با آرگومان آرایه دوم اختیاری درج می شود:

این firstOrNew روش، مانند firstOrCreate ، تلاش خواهد کرد تا رکوردی را در پایگاه داده مطابق با ویژگی های داده شده قرار دهد. با این حال، اگر یک مدل پیدا نشد، یک نمونه مدل جدید برگردانده خواهد شد. توجه داشته باشید که مدل بازگشتی توسط firstOrNew هنوز در پایگاه داده حفظ نشده است. save برای تداوم آن باید به صورت دستی متد را فراخوانی کنید :

use App\Models\Flight;
 
// Retrieve flight by name or create it if it doesn't exist...
$flight = Flight::firstOrCreate([
'name' => 'London to Paris'
]);
 
// Retrieve flight by name or create it with the name, delayed, and arrival_time attributes...
$flight = Flight::firstOrCreate(
['name' => 'London to Paris'],
['delayed' => 1, 'arrival_time' => '11:30']
);
 
// Retrieve flight by name or instantiate a new Flight instance...
$flight = Flight::firstOrNew([
'name' => 'London to Paris'
]);
 
// Retrieve flight by name or instantiate with the name, delayed, and arrival_time attributes...
$flight = Flight::firstOrNew(
['name' => 'Tokyo to Sydney'],
['delayed' => 1, 'arrival_time' => '11:30']
);

بازیابی مصالح

هنگام تعامل با مدل‌های Eloquent، می‌توانید از count , sum , max و سایر روش‌های انبوه ارائه‌شده توسط سازنده کوئری لاراول نیز استفاده کنید . همانطور که ممکن است انتظار داشته باشید، این روش ها به جای یک نمونه مدل Eloquent، یک مقدار اسکالر را برمی گرداند:

$count = Flight::where('active', 1)->count();
 
$max = Flight::where('active', 1)->max('price');

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

درج می کند

البته، هنگام استفاده از Eloquent، ما فقط نیازی به بازیابی مدل ها از پایگاه داده نداریم. همچنین باید رکوردهای جدیدی را وارد کنیم. خوشبختانه، Eloquent آن را ساده می کند. برای درج یک رکورد جدید در پایگاه داده، باید یک نمونه مدل جدید را نمونه سازی کنید و ویژگی هایی را روی مدل تنظیم کنید. سپس save متد موجود در نمونه مدل را فراخوانی کنید:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Models\Flight;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
 
class FlightController extends Controller
{
/**
* Store a new flight in the database.
*/
public function store(Request $request): RedirectResponse
{
// Validate the request...
 
$flight = new Flight;
 
$flight->name = $request->name;
 
$flight->save();
 
return redirect('/flights');
}
}

name در این مثال، فیلد درخواست HTTP ورودی را به name ویژگی نمونه مدل اختصاص می دهیم App\Models\Flight . وقتی متد را فراخوانی می کنیم save ، یک رکورد در پایگاه داده درج می شود. هنگامی که متد فراخوانی می شود ، مُهرها created_at و updated_at مُهرهای زمانی به طور خودکار تنظیم می شوند save ، بنابراین نیازی به تنظیم دستی آنها نیست.

از طرف دیگر، می‌توانید از create روشی برای «ذخیره» یک مدل جدید با استفاده از یک دستور PHP استفاده کنید. نمونه مدل درج شده با create روش زیر به شما بازگردانده می شود:

use App\Models\Flight;
 
$flight = Flight::create([
'name' => 'London to Paris',
]);

با این حال، قبل از استفاده از create متد، باید یک fillable یا guarded ویژگی را در کلاس مدل خود مشخص کنید. این ویژگی ها مورد نیاز هستند زیرا تمام مدل های Eloquent به طور پیش فرض در برابر آسیب پذیری های انتساب انبوه محافظت می شوند. برای کسب اطلاعات بیشتر در مورد تخصیص انبوه، لطفاً به مستندات انتساب انبوه مراجعه کنید .

به روز رسانی ها

این save روش همچنین ممکن است برای به‌روزرسانی مدل‌هایی که از قبل در پایگاه داده وجود دارد استفاده شود. برای به روز رسانی یک مدل، باید آن را بازیابی کنید و هر ویژگی را که می خواهید به روز کنید تنظیم کنید. سپس، باید متد مدل را فراخوانی کنید save . باز هم، updated_at مهر زمانی به طور خودکار به روز می شود، بنابراین نیازی به تنظیم دستی مقدار آن نیست:

use App\Models\Flight;
 
$flight = Flight::find(1);
 
$flight->name = 'Paris to London';
 
$flight->save();

گاهی اوقات، ممکن است لازم باشد یک مدل موجود را به روز کنید یا اگر مدل منطبقی وجود نداشته باشد، یک مدل جدید ایجاد کنید. مانند firstOrCreate متد، updateOrCreate متد نیز مدل را حفظ می کند، بنابراین نیازی به فراخوانی دستی متد نیست save .

در مثال زیر، اگر پروازی با departure مکان Oakland و destination مکان وجود داشته باشد، ستون ها و San Diego آن به روز می شوند. اگر چنین پروازی وجود نداشته باشد، یک پرواز جدید ایجاد می شود که دارای ویژگی های ناشی از ادغام آرایه آرگومان اول با آرایه آرگومان دوم است: price discounted

$flight = Flight::updateOrCreate(
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99, 'discounted' => 1]
);

به روز رسانی های انبوه

به‌روزرسانی‌ها را می‌توان در برابر مدل‌هایی که با یک پرس‌وجو مطابقت دارند نیز انجام داد. در این مثال، تمام پروازهایی که دارای active یک از هستند و دارای destination یک هستند San Diego ، به‌عنوان تاخیردار علامت‌گذاری می‌شوند:

Flight::where('active', 1)
->where('destination', 'San Diego')
->update(['delayed' => 1]);

این update روش انتظار دارد آرایه‌ای از جفت‌های ستون و مقادیر نشان دهنده ستون‌هایی باشد که باید به‌روزرسانی شوند. این update روش تعداد ردیف های تحت تأثیر را برمی گرداند.

هنگام صدور یک به‌روزرسانی انبوه از طریق Eloquent، رویدادهای saving , saved , updating و updated مدل برای مدل‌های به‌روزرسانی شده فعال نمی‌شوند. این به این دلیل است که مدل ها در هنگام صدور یک به روز رسانی انبوه هرگز بازیابی نمی شوند.

بررسی تغییرات صفت

Eloquent روش‌های isDirty ، isClean و و wasChanged را برای بررسی وضعیت داخلی مدل شما و تعیین اینکه چگونه ویژگی‌های آن نسبت به زمانی که مدل اولیه بازیابی شده است، تغییر کرده است، ارائه می‌کند.

این isDirty روش تعیین می کند که آیا هر یک از ویژگی های مدل از زمان بازیابی مدل تغییر کرده است یا خیر. شما می‌توانید یک نام مشخصه یا آرایه‌ای از ویژگی‌ها را به isDirty متد ارسال کنید تا مشخص کنید که آیا هر یک از ویژگی‌ها "کثیف" هستند یا خیر. این isClean روش تعیین می کند که آیا یک ویژگی از زمان بازیابی مدل بدون تغییر باقی مانده است یا خیر. این متد یک آرگومان ویژگی اختیاری را نیز می پذیرد:

use App\Models\User;
 
$user = User::create([
'first_name' => 'Taylor',
'last_name' => 'Otwell',
'title' => 'Developer',
]);
 
$user->title = 'Painter';
 
$user->isDirty(); // true
$user->isDirty('title'); // true
$user->isDirty('first_name'); // false
$user->isDirty(['first_name', 'title']); // true
 
$user->isClean(); // false
$user->isClean('title'); // false
$user->isClean('first_name'); // true
$user->isClean(['first_name', 'title']); // false
 
$user->save();
 
$user->isDirty(); // false
$user->isClean(); // true

این wasChanged روش تعیین می‌کند که آیا در آخرین ذخیره‌سازی مدل در چرخه درخواست فعلی، هیچ ویژگی تغییر کرده است یا خیر. در صورت نیاز، می توانید یک نام مشخصه را ارسال کنید تا ببینید آیا یک ویژگی خاص تغییر کرده است یا خیر:

$user = User::create([
'first_name' => 'Taylor',
'last_name' => 'Otwell',
'title' => 'Developer',
]);
 
$user->title = 'Painter';
 
$user->save();
 
$user->wasChanged(); // true
$user->wasChanged('title'); // true
$user->wasChanged(['title', 'slug']); // true
$user->wasChanged('first_name'); // false
$user->wasChanged(['first_name', 'title']); // true

این getOriginal روش یک آرایه حاوی ویژگی های اصلی مدل را بدون توجه به هر گونه تغییر در مدل از زمان بازیابی آن برمی گرداند. در صورت نیاز، می توانید یک نام مشخصه را برای بدست آوردن مقدار اصلی یک ویژگی خاص ارسال کنید:

$user = User::find(1);
 
$user->name; // John
$user->email; // john@example.com
 
$user->name = "Jack";
$user->name; // Jack
 
$user->getOriginal('name'); // John
$user->getOriginal(); // Array of original attributes...

تکلیف انبوه

شما می توانید از create روش برای "ذخیره" یک مدل جدید با استفاده از یک دستور PHP استفاده کنید. نمونه مدل درج شده با روش زیر به شما بازگردانده می شود:

use App\Models\Flight;
 
$flight = Flight::create([
'name' => 'London to Paris',
]);

با این حال، قبل از استفاده از create متد، باید یک fillable یا guarded ویژگی را در کلاس مدل خود مشخص کنید. این ویژگی ها مورد نیاز هستند زیرا تمام مدل های Eloquent به طور پیش فرض در برابر آسیب پذیری های انتساب انبوه محافظت می شوند.

آسیب‌پذیری انتساب انبوه زمانی رخ می‌دهد که کاربر یک فیلد درخواست HTTP غیرمنتظره را پاس می‌کند و آن فیلد ستونی را در پایگاه داده شما تغییر می‌دهد که انتظارش را نداشتید. به عنوان مثال، یک کاربر مخرب ممکن است is_admin پارامتری را از طریق یک درخواست HTTP ارسال کند، که سپس به روش مدل شما ارسال می‌شود create و به کاربر اجازه می‌دهد تا خود را به یک سرپرست افزایش دهد.

بنابراین، برای شروع، باید مشخص کنید که کدام ویژگی مدل را می‌خواهید قابل تخصیص جرم کنید. می توانید این کار را با استفاده از $fillable ویژگی روی مدل انجام دهید. به عنوان مثال، بیایید name ویژگی جرم مدل خود را Flight قابل تخصیص کنیم:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class Flight extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['name'];
}

هنگامی که مشخص کردید کدام ویژگی ها قابل انتساب هستند، می توانید از create روش برای درج یک رکورد جدید در پایگاه داده استفاده کنید. متد create نمونه مدل جدید ایجاد شده را برمی گرداند:

$flight = Flight::create(['name' => 'London to Paris']);

اگر قبلاً یک نمونه مدل دارید، می توانید از fill روش برای پر کردن آن با آرایه ای از ویژگی ها استفاده کنید:

$flight->fill(['name' => 'Amsterdam to Frankfurt']);

تخصیص انبوه و ستون های JSON

هنگام تخصیص ستون های JSON، کلید قابل تخصیص انبوه هر ستون باید در $fillable آرایه مدل شما مشخص شود. برای امنیت، لاراول از به‌روزرسانی ویژگی‌های JSON تودرتو هنگام استفاده از ویژگی پشتیبانی نمی‌کند guarded :

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'options->enabled',
];

اجازه واگذاری انبوه

اگر می خواهید همه ویژگی های خود را قابل انتساب جرمی کنید، می توانید $guarded ویژگی مدل خود را به عنوان یک آرایه خالی تعریف کنید. اگر تصمیم گرفتید که از مدل خود محافظت نکنید، باید مراقب باشید که همیشه آرایه‌های ارسال شده به روش‌های Eloquent fill ، create و update روش‌های Eloquent را دستی بسازید :

/**
* The attributes that aren't mass assignable.
*
* @var array
*/
protected $guarded = [];

استثناهای تخصیص انبوه

به‌طور پیش‌فرض، ویژگی‌هایی که در آرایه گنجانده نشده‌اند، $fillable هنگام انجام عملیات تخصیص انبوه، بی‌صدا کنار گذاشته می‌شوند. در تولید، این رفتار مورد انتظار است. با این حال، در طول توسعه محلی می تواند منجر به سردرگمی در مورد اینکه چرا تغییرات مدل تأثیر نمی گذارد، شود.

در صورت تمایل، می‌توانید به لاراول دستور دهید هنگام تلاش برای پر کردن یک ویژگی غیرقابل پر کردن با فراخوانی متد، یک استثنا ایجاد کند preventSilentlyDiscardingAttributes . به طور معمول، این متد باید در boot متد کلاس برنامه شما فراخوانی شود AppServiceProvider :

use Illuminate\Database\Eloquent\Model;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Model::preventSilentlyDiscardingAttributes($this->app->isLocal());
}

بالاها

روش Eloquent upsert ممکن است برای به‌روزرسانی یا ایجاد رکوردها در یک عملیات اتمی استفاده شود. آرگومان اول متد شامل مقادیری است که باید درج یا به‌روزرسانی شوند، در حالی که آرگومان دوم ستون(هایی) را فهرست می‌کند که رکوردها را در جدول مرتبط شناسایی می‌کنند. آرگومان سوم و آخر متد، آرایه‌ای از ستون‌ها است که در صورت وجود رکورد منطبق در پایگاه داده، باید به روز شوند. اگر مهر زمانی در مدل فعال باشد، این روش به‌طور خودکار زمان و مُهر upsert را تنظیم می‌کند : created_at updated_at

Flight::upsert([
['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],
['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]
], uniqueBy: ['departure', 'destination'], update: ['price']);

همه پایگاه‌های داده به جز SQL Server نیاز دارند که ستون‌های آرگومان دوم متد upsert دارای یک فهرست «اولیه» یا «محصول» باشند. علاوه بر این، درایور پایگاه داده MySQL آرگومان دوم متد را نادیده می گیرد upsert و همیشه از شاخص های "اولیه" و "یک" جدول برای شناسایی رکوردهای موجود استفاده می کند.

حذف مدل ها

برای حذف یک مدل، می توانید delete متد موجود در نمونه مدل را فراخوانی کنید:

use App\Models\Flight;
 
$flight = Flight::find(1);
 
$flight->delete();

می توانید truncate متد را برای حذف تمام رکوردهای پایگاه داده مرتبط مدل فراخوانی کنید. این truncate عملیات همچنین شناسه‌های افزایش‌دهنده خودکار در جدول مربوط به مدل را بازنشانی می‌کند:

Flight::truncate();

حذف یک مدل موجود توسط کلید اصلی آن

در مثال بالا، قبل از فراخوانی delete متد، مدل را از پایگاه داده بازیابی می کنیم. با این حال، اگر کلید اصلی مدل را می‌دانید، می‌توانید با فراخوانی متد، مدل را بدون بازیابی صریح حذف کنید destroy . این روش علاوه بر پذیرش کلید اصلی، چندین کلید اصلی، آرایه ای از کلیدهای اصلی یا مجموعه ای از کلیدهای اصلی destroy را می پذیرد :

Flight::destroy(1);
 
Flight::destroy(1, 2, 3);
 
Flight::destroy([1, 2, 3]);
 
Flight::destroy(collect([1, 2, 3]));

متد destroy هر مدل را به صورت جداگانه بارگذاری می کند و delete متد را فراخوانی می کند تا رویدادها deleting و deleted رویدادها به درستی برای هر مدل ارسال شوند.

حذف مدل ها با استفاده از پرس و جو

البته، ممکن است یک پرس و جو Eloquent بسازید تا تمام مدل های مطابق با معیارهای پرس و جو خود را حذف کنید. در این مثال، ما تمام پروازهایی را که به عنوان غیرفعال علامت گذاری شده اند حذف می کنیم. مانند به‌روزرسانی‌های انبوه، حذف‌های انبوه رویدادهای مدل را برای مدل‌هایی که حذف می‌شوند ارسال نمی‌کند:

$deleted = Flight::where('active', 0)->delete();

هنگام اجرای دستور حذف انبوه از طریق Eloquent، رویدادهای مدل deleting و deleted برای مدل‌های حذف شده ارسال نمی‌شوند. این به این دلیل است که مدل ها در هنگام اجرای دستور حذف هرگز بازیابی نمی شوند.

حذف نرم

Eloquent علاوه بر حذف واقعی رکوردها از پایگاه داده شما، می تواند مدل های "نرم افزار" را نیز حذف کند. وقتی مدل ها به نرمی حذف می شوند، در واقع از پایگاه داده شما حذف نمی شوند. در عوض، یک deleted_at ویژگی بر روی مدل تنظیم می شود که تاریخ و زمانی را که مدل در آن "حذف شده است" را نشان می دهد. برای فعال کردن حذف های نرم برای یک مدل، این Illuminate\Database\Eloquent\SoftDeletes ویژگی را به مدل اضافه کنید:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
 
class Flight extends Model
{
use SoftDeletes;
}

این ویژگی به طور خودکار ویژگی را به یک نمونه / برای شما SoftDeletes ارسال می کند . deleted_at DateTime Carbon

همچنین باید deleted_at ستون را به جدول پایگاه داده خود اضافه کنید. سازنده طرحواره لاراول حاوی یک روش کمکی برای ایجاد این ستون است:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
Schema::table('flights', function (Blueprint $table) {
$table->softDeletes();
});
 
Schema::table('flights', function (Blueprint $table) {
$table->dropSoftDeletes();
});

حالا وقتی delete متد را روی مدل فراخوانی می کنید، deleted_at ستون روی تاریخ و زمان فعلی تنظیم می شود. با این حال، رکورد پایگاه داده مدل در جدول باقی خواهد ماند. هنگام جستجوی مدلی که از حذف های نرم افزاری استفاده می کند، مدل های حذف شده نرم به طور خودکار از همه نتایج پرس و جو حذف می شوند.

برای تعیین اینکه آیا یک نمونه مدل معین به نرمی حذف شده است، می توانید از trashed روش زیر استفاده کنید:

if ($flight->trashed()) {
// ...
}

بازیابی مدل های نرم حذف شده

گاهی اوقات ممکن است بخواهید یک مدل نرم افزاری حذف شده را حذف کنید. برای بازیابی یک مدل نرم افزاری حذف شده، می توانید restore متد را در یک نمونه مدل فراخوانی کنید. این روش ستون restore مدل را به صورت زیر تنظیم می کند : deleted_at null

$flight->restore();

همچنین می توانید از این restore روش در یک کوئری برای بازیابی چندین مدل استفاده کنید. دوباره، مانند سایر عملیات "انبوه"، این هیچ رویداد مدلی را برای مدل هایی که بازیابی می شوند ارسال نمی کند:

Flight::withTrashed()
->where('airline_id', 1)
->restore();

این روش همچنین ممکن است هنگام ایجاد پرس و جوهای رابطه restore استفاده شود :

$flight->history()->restore();

حذف دائمی مدل ها

گاهی اوقات ممکن است لازم باشد یک مدل را واقعاً از پایگاه داده خود حذف کنید. می توانید از این forceDelete روش برای حذف دائمی یک مدل نرم افزاری حذف شده از جدول پایگاه داده استفاده کنید:

$flight->forceDelete();

همچنین می توانید از این forceDelete روش در هنگام ساخت پرس و جوهای رابطه Eloquent استفاده کنید:

$flight->history()->forceDelete();

پرس و جو از مدل های حذف شده نرم

از جمله مدل های نرم حذف شده

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

use App\Models\Flight;
 
$flights = Flight::withTrashed()
->where('account_id', 1)
->get();

این withTrashed متد همچنین ممکن است هنگام ساخت یک پرس و جو رابطه فراخوانی شود :

$flight->history()->withTrashed()->get();

بازیابی فقط مدل های نرم حذف شده

این onlyTrashed روش فقط مدل های حذف شده نرم را بازیابی می کند:

$flights = Flight::onlyTrashed()
->where('airline_id', 1)
->get();

مدل های هرس

گاهی اوقات ممکن است بخواهید به طور دوره ای مدل هایی را که دیگر مورد نیاز نیستند حذف کنید. برای انجام این کار، می توانید ویژگی Illuminate\Database\Eloquent\Prunable یا Illuminate\Database\Eloquent\MassPrunable ویژگی را به مدل هایی که می خواهید به طور دوره ای هرس کنید اضافه کنید. پس از افزودن یکی از ویژگی‌ها به مدل، روشی را پیاده‌سازی کنید prunable که سازنده پرس و جو Eloquent را برمی‌گرداند که مدل‌هایی که دیگر مورد نیاز نیستند را حل می‌کند:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable;
 
class Flight extends Model
{
use Prunable;
 
/**
* Get the prunable model query.
*/
public function prunable(): Builder
{
return static::where('created_at', '<=', now()->subMonth());
}
}

هنگام علامت‌گذاری مدل‌ها به‌عنوان Prunable ، می‌توانید pruning روشی را نیز بر روی مدل تعریف کنید. این متد قبل از حذف مدل فراخوانی می شود. این روش می تواند برای حذف هرگونه منبع اضافی مرتبط با مدل، مانند فایل های ذخیره شده، قبل از حذف دائمی مدل از پایگاه داده مفید باشد:

/**
* Prepare the model for pruning.
*/
protected function pruning(): void
{
// ...
}

پس از پیکربندی مدل قابل هرس خود، باید model:prune دستور Artisan را در فایل برنامه خود زمان بندی کنید routes/console.php . شما آزاد هستید که فاصله زمانی مناسبی را که این دستور باید در آن اجرا شود را انتخاب کنید:

use Illuminate\Support\Facades\Schedule;
 
Schedule::command('model:prune')->daily();

در پشت صحنه، این model:prune فرمان به طور خودکار مدل های «Prunable» را در فهرست برنامه شما شناسایی می کند app/Models . اگر مدل‌های شما در مکان دیگری هستند، می‌توانید از این --model گزینه برای تعیین نام کلاس مدل استفاده کنید:

Schedule::command('model:prune', [
'--model' => [Address::class, Flight::class],
])->daily();

اگر می‌خواهید مدل‌های خاصی را در حین هرس کردن همه مدل‌های شناسایی‌شده دیگر حذف کنید، می‌توانید از این --except گزینه استفاده کنید:

Schedule::command('model:prune', [
'--except' => [Address::class, Flight::class],
])->daily();

می توانید prunable با اجرای model:prune دستور با --pretend گزینه پرس و جو خود را آزمایش کنید. هنگام تظاهر، model:prune فرمان به سادگی گزارش می دهد که اگر فرمان واقعاً اجرا شود، چند رکورد هرس می شود:

php artisan model:prune --pretend

مدل‌های حذف نرم به‌طور دائم حذف می‌شوند ( forceDelete ) اگر با جستار قابل هرس مطابقت داشته باشند.

هرس انبوه

هنگامی که مدل ها با این Illuminate\Database\Eloquent\MassPrunable ویژگی مشخص می شوند، مدل ها با استفاده از پرس و جوهای حذف انبوه از پایگاه داده حذف می شوند. بنابراین، pruning روش فراخوانی نمی شود، deleting و deleted رویدادهای مدل و نیز ارسال نمی شوند. این به این دلیل است که مدل‌ها هرگز قبل از حذف بازیابی نمی‌شوند، بنابراین فرآیند هرس بسیار کارآمدتر می‌شود:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\MassPrunable;
 
class Flight extends Model
{
use MassPrunable;
 
/**
* Get the prunable model query.
*/
public function prunable(): Builder
{
return static::where('created_at', '<=', now()->subMonth());
}
}

شبیه سازی مدل ها

می توانید با استفاده از replicate روش، یک کپی ذخیره نشده از یک نمونه مدل موجود ایجاد کنید. این روش به ویژه زمانی مفید است که نمونه های مدلی دارید که بسیاری از ویژگی های مشابه را به اشتراک می گذارند:

use App\Models\Address;
 
$shipping = Address::create([
'type' => 'shipping',
'line_1' => '123 Example Street',
'city' => 'Victorville',
'state' => 'CA',
'postcode' => '90001',
]);
 
$billing = $shipping->replicate()->fill([
'type' => 'billing'
]);
 
$billing->save();

برای حذف یک یا چند ویژگی از تکرار در مدل جدید، می توانید یک آرایه را به replicate متد ارسال کنید:

$flight = Flight::create([
'destination' => 'LAX',
'origin' => 'LHR',
'last_flown' => '2020-03-04 11:00:00',
'last_pilot_id' => 747,
]);
 
$flight = $flight->replicate([
'last_flown',
'last_pilot_id'
]);

محدوده پرس و جو

دامنه های جهانی

دامنه جهانی به شما امکان می دهد برای یک مدل معین، محدودیت هایی را به همه پرس و جوها اضافه کنید. قابلیت حذف نرم خود لاراول از دامنه های جهانی استفاده می کند تا فقط مدل های «حذف نشده» را از پایگاه داده بازیابی کند. نوشتن دامنه های جهانی خود می تواند یک راه راحت و آسان برای اطمینان از اینکه هر پرس و جو برای یک مدل معین محدودیت های خاصی را دریافت می کند، ارائه دهد.

تولید دامنه ها

برای ایجاد یک دامنه جهانی جدید، می توانید make:scope دستور Artisan را فراخوانی کنید، که محدوده تولید شده را در فهرست برنامه شما قرار می دهد app/Models/Scopes :

php artisan make:scope AncientScope

نوشتن دامنه های جهانی

نوشتن یک دامنه جهانی ساده است. ابتدا از make:scope دستور برای ایجاد کلاسی که Illuminate\Database\Eloquent\Scope رابط را پیاده سازی می کند استفاده کنید. رابط Scope از شما می خواهد که یک روش را پیاده سازی کنید: apply . این apply روش ممکن است where در صورت نیاز، محدودیت‌ها یا انواع دیگری از عبارت‌ها را به پرس و جو اضافه کند:

<?php
 
namespace App\Models\Scopes;
 
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
 
class AncientScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*/
public function apply(Builder $builder, Model $model): void
{
$builder->where('created_at', '<', now()->subYears(2000));
}
}

اگر دامنه جهانی شما ستون‌هایی را به عبارت انتخابی پرس و جو اضافه می‌کند، باید addSelect به جای استفاده از روش از select . این از جایگزینی ناخواسته عبارت انتخابی موجود در پرس و جو جلوگیری می کند.

بکارگیری دامنه های جهانی

برای اختصاص دادن یک دامنه جهانی به یک مدل، می‌توانید به سادگی این ScopedBy ویژگی را روی مدل قرار دهید:

<?php
 
namespace App\Models;
 
use App\Models\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Attributes\ScopedBy;
 
#[ScopedBy([AncientScope::class])]
class User extends Model
{
//
}

یا، می توانید به صورت دستی دامنه جهانی را با نادیده گرفتن روش مدل ثبت کنید booted و روش مدل را فراخوانی کنید addGlobalScope . این addGlobalScope روش نمونه ای از محدوده شما را به عنوان تنها آرگومان خود می پذیرد:

<?php
 
namespace App\Models;
 
use App\Models\Scopes\AncientScope;
use Illuminate\Database\Eloquent\Model;
 
class User extends Model
{
/**
* The "booted" method of the model.
*/
protected static function booted(): void
{
static::addGlobalScope(new AncientScope);
}
}

پس از افزودن دامنه در مثال بالا به App\Models\User مدل، یک فراخوانی به User::all() متد، کوئری SQL زیر را اجرا می کند:

select * from `users` where `created_at` < 0021-02-18 00:00:00

دامنه های جهانی ناشناس

Eloquent همچنین به شما این امکان را می‌دهد که با استفاده از بسته‌ها، دامنه‌های جهانی را تعریف کنید، که به ویژه برای محدوده‌های ساده که کلاس جداگانه‌ای را تضمین نمی‌کنند، مفید است. هنگام تعریف یک دامنه جهانی با استفاده از یک بسته، باید یک نام محدوده انتخابی خود را به عنوان اولین آرگومان متد ارائه دهید addGlobalScope :

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
 
class User extends Model
{
/**
* The "booted" method of the model.
*/
protected static function booted(): void
{
static::addGlobalScope('ancient', function (Builder $builder) {
$builder->where('created_at', '<', now()->subYears(2000));
});
}
}

حذف دامنه های جهانی

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

User::withoutGlobalScope(AncientScope::class)->get();

یا، اگر دامنه جهانی را با استفاده از یک بسته تعریف کرده اید، باید نام رشته ای را که به دامنه جهانی اختصاص داده اید ارسال کنید:

User::withoutGlobalScope('ancient')->get();

اگر می‌خواهید چندین یا حتی همه حوزه‌های جهانی پرس و جو را حذف کنید، می‌توانید از withoutGlobalScopes روش زیر استفاده کنید:

// Remove all of the global scopes...
User::withoutGlobalScopes()->get();
 
// Remove some of the global scopes...
User::withoutGlobalScopes([
FirstScope::class, SecondScope::class
])->get();

محدوده های محلی

دامنه های محلی به شما امکان می دهد مجموعه های مشترکی از محدودیت های پرس و جو را تعریف کنید که می توانید به راحتی در سراسر برنامه خود دوباره از آنها استفاده کنید. به عنوان مثال، ممکن است لازم باشد مکرراً همه کاربرانی را که "محبوب" در نظر گرفته می شوند، بازیابی کنید. برای تعریف یک محدوده، پیشوند یک متد مدل Eloquent را با scope .

Scopes همیشه باید همان نمونه سازنده query را برگرداند یا void :

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
 
class User extends Model
{
/**
* Scope a query to only include popular users.
*/
public function scopePopular(Builder $query): void
{
$query->where('votes', '>', 100);
}
 
/**
* Scope a query to only include active users.
*/
public function scopeActive(Builder $query): void
{
$query->where('active', 1);
}
}

استفاده از Local Scope

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

use App\Models\User;
 
$users = User::popular()->active()->orderBy('created_at')->get();

ترکیب چندین محدوده مدل Eloquent از طریق یک or عملگر query ممکن است نیاز به استفاده از بسته‌ها برای دستیابی به گروه‌بندی منطقی صحیح داشته باشد :

$users = User::popular()->orWhere(function (Builder $query) {
$query->active();
})->get();

با این حال، از آنجایی که این کار می تواند دست و پا گیر باشد، لاراول یک orWhere روش "ترتیب بالاتر" را ارائه می دهد که به شما امکان می دهد بدون استفاده از بسته شدن، دامنه ها را به طور روان به هم متصل کنید:

$users = User::popular()->orWhere->active()->get();

دامنه های دینامیک

گاهی اوقات ممکن است بخواهید محدوده ای را تعریف کنید که پارامترها را بپذیرد. برای شروع، فقط پارامترهای اضافی خود را به امضای روش محدوده خود اضافه کنید. پارامترهای محدوده باید بعد از پارامتر تعریف شوند $query :

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
 
class User extends Model
{
/**
* Scope a query to only include users of a given type.
*/
public function scopeOfType(Builder $query, string $type): void
{
$query->where('type', $type);
}
}

هنگامی که آرگومان های مورد انتظار به امضای متد scope شما اضافه شد، می توانید آرگومان ها را هنگام فراخوانی scope ارسال کنید:

$users = User::ofType('admin')->get();

مقایسه مدل ها

گاهی اوقات ممکن است لازم باشد تعیین کنید که آیا دو مدل "یکسان" هستند یا خیر. روش‌های is و isNot ممکن است برای تأیید سریع اینکه دو مدل دارای کلید اصلی، جدول و اتصال پایگاه داده یکسان هستند یا نه استفاده شوند:

if ($post->is($anotherPost)) {
// ...
}
 
if ($post->isNot($anotherPost)) {
// ...
}

و هنگام استفاده از روابط ، is و ، و isNot نیز در دسترس هستند . این روش مخصوصاً زمانی مفید است که بخواهید یک مدل مرتبط را بدون ارسال پرس و جو برای بازیابی آن مدل مقایسه کنید: belongsTo hasOne morphTo morphOne

if ($post->author()->is($user)) {
// ...
}

مناسبت ها

آیا می خواهید رویدادهای Eloquent خود را مستقیماً در برنامه سمت مشتری خود پخش کنید؟ پخش رویداد مدل لاراول را بررسی کنید .

مدل‌های الکوئنت چندین رویداد را ارسال می‌کنند و به شما امکان می‌دهند به لحظات زیر در چرخه عمر یک retrieved مدل بپیوندید : creating created updating updated saving saved deleting deleted trashed forceDeleting forceDeleted restoring restored replicating

retrieved هنگامی که یک مدل موجود از پایگاه داده بازیابی شود، رویداد ارسال می شود . هنگامی که یک مدل جدید برای اولین بار ذخیره می شود، creating و created رویدادها ارسال می شوند. هنگامی که یک مدل موجود اصلاح شود و متد فراخوانی شود، updating / رویدادها ارسال می شود. رویدادهای / هنگامی که یک مدل ایجاد یا به‌روزرسانی می‌شود ارسال می‌شود - حتی اگر ویژگی‌های مدل تغییر نکرده باشند. نام رویدادهایی که به آن ختم می‌شوند قبل از تداوم هرگونه تغییر در مدل ارسال می‌شوند، در حالی که رویدادهایی که با پایان می‌شوند پس از تداوم تغییرات در مدل ارسال می‌شوند. updated save saving saved -ing -ed

برای شروع گوش دادن به رویدادهای مدل، یک $dispatchesEvents ویژگی در مدل Eloquent خود تعریف کنید. این ویژگی نقاط مختلف چرخه عمر مدل Eloquent را به کلاس‌های رویداد خودتان ترسیم می‌کند . هر کلاس رویداد مدل باید انتظار داشته باشد که نمونه ای از مدل تحت تأثیر را از طریق سازنده خود دریافت کند:

<?php
 
namespace App\Models;
 
use App\Events\UserDeleted;
use App\Events\UserSaved;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
 
class User extends Authenticatable
{
use Notifiable;
 
/**
* The event map for the model.
*
* @var array<string, string>
*/
protected $dispatchesEvents = [
'saved' => UserSaved::class,
'deleted' => UserDeleted::class,
];
}

پس از تعریف و ترسیم رویدادهای Eloquent خود، می توانید از شنوندگان رویداد برای مدیریت رویدادها استفاده کنید.

هنگام صدور به‌روزرسانی انبوه یا حذف درخواست از طریق Eloquent، saved رویدادهای مدل updated ،، deleting و deleted مدل برای مدل‌های آسیب‌دیده ارسال نمی‌شوند. این به این دلیل است که مدل ها در هنگام انجام به روز رسانی یا حذف انبوه هرگز بازیابی نمی شوند.

استفاده از بسته ها

به جای استفاده از کلاس‌های رویداد سفارشی، می‌توانید بسته‌هایی را ثبت کنید که هنگام ارسال رویدادهای مدل مختلف اجرا می‌شوند. به طور معمول، شما باید این بسته ها را در booted روش مدل خود ثبت کنید:

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class User extends Model
{
/**
* The "booted" method of the model.
*/
protected static function booted(): void
{
static::created(function (User $user) {
// ...
});
}
}

در صورت نیاز، می توانید هنگام ثبت رویدادهای مدل از شنوندگان رویداد ناشناس در صف استفاده کنید. این به لاراول دستور می دهد تا شنونده رویداد مدل را در پس زمینه با استفاده از صف برنامه شما اجرا کند :

use function Illuminate\Events\queueable;
 
static::created(queueable(function (User $user) {
// ...
}));

ناظران

تعریف ناظران

اگر در حال گوش دادن به بسیاری از رویدادها در یک مدل خاص هستید، می توانید از ناظران برای گروه بندی همه شنوندگان خود در یک کلاس واحد استفاده کنید. کلاس‌های مشاهده‌گر دارای نام‌های متدهایی هستند که رویدادهای Eloquent را که می‌خواهید گوش دهید، منعکس می‌کنند. هر یک از این روش ها مدل تحت تأثیر را به عنوان تنها استدلال خود دریافت می کنند. دستور make:observer Artisan ساده ترین راه برای ایجاد یک کلاس مشاهدهگر جدید است:

php artisan make:observer UserObserver --model=User

این دستور مشاهده گر جدید را در app/Observers دایرکتوری شما قرار می دهد. اگر این دایرکتوری وجود نداشته باشد، Artisan آن را برای شما ایجاد می کند. مشاهده گر تازه کار شما به شکل زیر خواهد بود:

<?php
 
namespace App\Observers;
 
use App\Models\User;
 
class UserObserver
{
/**
* Handle the User "created" event.
*/
public function created(User $user): void
{
// ...
}
 
/**
* Handle the User "updated" event.
*/
public function updated(User $user): void
{
// ...
}
 
/**
* Handle the User "deleted" event.
*/
public function deleted(User $user): void
{
// ...
}
 
/**
* Handle the User "restored" event.
*/
public function restored(User $user): void
{
// ...
}
 
/**
* Handle the User "forceDeleted" event.
*/
public function forceDeleted(User $user): void
{
// ...
}
}

برای ثبت یک ناظر، می توانید ObservedBy ویژگی را در مدل مربوطه قرار دهید:

use App\Observers\UserObserver;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
 
#[ObservedBy([UserObserver::class])]
class User extends Authenticatable
{
//
}

یا، می‌توانید با فراخوانی observe روش روی مدلی که می‌خواهید مشاهده کنید، یک ناظر را به صورت دستی ثبت کنید. می توانید ناظران را در boot روش کلاس برنامه خود ثبت کنید AppServiceProvider :

use App\Models\User;
use App\Observers\UserObserver;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
User::observe(UserObserver::class);
}

رویدادهای دیگری وجود دارد که ناظر می تواند به آنها گوش دهد، مانند saving و retrieved . این رویدادها در مستندات رویدادها توضیح داده شده است .

ناظران و معاملات پایگاه داده

هنگامی که مدل‌ها در یک تراکنش پایگاه داده ایجاد می‌شوند، ممکن است بخواهید به یک ناظر دستور دهید که تنها پس از انجام تراکنش پایگاه داده، کنترل‌کننده‌های رویداد خود را اجرا کند. شما می توانید این کار را با پیاده سازی ShouldHandleEventsAfterCommit رابط بر روی ناظر خود انجام دهید. اگر تراکنش پایگاه داده در حال انجام نباشد، کنترل کننده رویداد بلافاصله اجرا می کند:

<?php
 
namespace App\Observers;
 
use App\Models\User;
use Illuminate\Contracts\Events\ShouldHandleEventsAfterCommit;
 
class UserObserver implements ShouldHandleEventsAfterCommit
{
/**
* Handle the User "created" event.
*/
public function created(User $user): void
{
// ...
}
}

نادیده گرفتن رویدادها

گاهی اوقات ممکن است نیاز داشته باشید که به طور موقت همه رویدادهایی که توسط یک مدل اجرا می شود را "بی صدا" کنید. شما ممکن است با استفاده از withoutEvents روش به این امر برسید. روش withoutEvents بسته شدن را به عنوان تنها آرگومان خود می پذیرد. هر کدی که در این بسته اجرا شود، رویدادهای مدل را ارسال نخواهد کرد، و هر مقداری که با بسته شدن بازگردانده شود، با روش زیر برگردانده می شود withoutEvents :

use App\Models\User;
 
$user = User::withoutEvents(function () {
User::findOrFail(1)->delete();
 
return User::find(2);
});

ذخیره یک مدل بدون رویداد

گاهی اوقات ممکن است بخواهید یک مدل داده شده را بدون ارسال هیچ رویدادی "ذخیره" کنید. شما می توانید این کار را با استفاده از saveQuietly روش زیر انجام دهید:

$user = User::findOrFail(1);
 
$user->name = 'Victoria Faith';
 
$user->saveQuietly();

همچنین می‌توانید یک مدل را بدون ارسال هیچ رویدادی «به‌روزرسانی»، «حذف»، «حذف نرم»، «بازیابی» و «تکرار» کنید:

$user->deleteQuietly();
$user->forceDeleteQuietly();
$user->restoreQuietly();