الکوئنت: شروع کردن
- معرفی
- تولید کلاس های مدل
- قراردادهای مدل الکوئنت
- بازیابی مدل ها
- بازیابی مدل های منفرد / مصالح
- درج و به روز رسانی مدل ها
- حذف مدل ها
- مدل های هرس
- شبیه سازی مدل ها
- محدوده پرس و جو
- مقایسه مدل ها
- مناسبت ها
معرفی
لاراول شامل 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 --factoryphp artisan make:model Flight -f # Generate a model and a FlightSeeder class...php artisan make:model Flight --seedphp artisan make:model Flight -s # Generate a model and a FlightController class...php artisan make:model Flight --controllerphp artisan make:model Flight -c # Generate a model, FlightController resource class, and form request classes...php artisan make:model Flight --controller --resource --requestsphp 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 --allphp artisan make:model Flight -a # Generate a pivot model...php artisan make:model Member --pivotphp 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();