الکونت (Eloquent) یک نگاشت رابطه ای شی (ORM) است که به طور پیش فرض در فریمورک لاراول گنجانده شده است. ORM نرمافزاری است که با نمایش دادهها بهعنوان اشیاء، مدیریت سوابق پایگاهداده را تسهیل میکند و بهعنوان لایهای از آبسترک در بالای موتور پایگاه داده مورد استفاده برای ذخیره دادههای یک برنامه کاربردی کار میکند.
Eloquent کار تعامل با جداول پایگاه داده را تسهیل می کند، یک رویکرد شی گرا برای ایجاد، به روز رسانی، و حذف رکوردهای پایگاه داده ارائه می دهد، در حالی که یک رابط ساده برای اجرای کوئری های SQL پیچیده را نیز فراهم می کند.
بیاید با هم دیگر در آنوفل با 20 تا از مهمترین الکونت های لاراول آشنا شویم. اگر با لاراول 11 آشنا نیستید از طریق این مقاله می توانید با لاراول 11 اشنا شوید.
20 تا از مهم ترین متد های الکونت در لاراول
ORM گویا مکانیزمی ساده به نظر می رسد، اما در زیر هود، بسیاری از عملکردهای نیمه پنهان و راه های کمتر شناخته شده برای دستیابی به چیزهای بیشتر با آن وجود دارد. برای آشنایی با کد نویسی تمیز در لاراول نیز می توانید این مقاله را بررسی کنید.
1. افزایش و کاهش
به جای این:
$article = Article::find($article_id);
$article->read_count++;
$article->save();
شما می توانید این کار را انجام دهید:
$article = Article::find($article_id);
$article->increment('read_count');
همچنین کد زیر نیز:
Article::find($article_id)->increment('read_count');
Article::find($article_id)->increment('read_count', 10); // +10
Product::find($produce_id)->decrement('stock'); // -1
2. متد های XorY
Eloquent متد های کمی دارد که دو متد را ترکیب کند، مانند "لطفا X را انجام دهید، در غیر این صورت Y را انجام دهید".
مثال 1 : ()findOrFail
:
بجای کد زیر:
$user = User::find($id);
if (!$user) { abort (404); }
این کار را انجام دهید:
$user = User::findOrFail($id);
مثال 2 : ()firstOrCreate
:
بجای کد زیر:
$user = User::where('email', $email)->first();
if (!$user) {
User::create([
'email' => $email
]);
}
فقط این کار را انجام دهید:
$user = User::firstOrCreate(['email' => $email]);
برای آشنایی با 20 ترفند و نکات مهم در لاراول در سال 2024 این مقاله را بررسی کنید.
آیا با توسعه تست محور در لاراول آشنا هستید، اگر نیستید این مقاله را بررسی کنید.
3. متد ()boot
در مدل
یک متد جادویی به نام ()boot
در مدل Eloquent وجود دارد که می توانید رفتار پیش فرض را لغو کنید:
class User extends Model
{
public static function boot()
{
parent::boot();
static::updating(function($model)
{
// do some logging
// override some property like $model->something = transform($something);
});
}
}
احتمالاً یکی از محبوبترین مثالها تنظیم مقدار فیلد در لحظه ایجاد شی مدل است. فرض کنید می خواهید فیلد UUID را در آن لحظه ایجاد کنید.
public static function boot()
{
parent::boot();
self::creating(function ($model) {
$model->uuid = (string)Uuid::generate();
});
}
4. روابط با شرایط و سفارشی
این یک روش معمولی برای تعریف روابط است. اگر با روابط در لاراول آشنا نیستید این مقاله را بررسی کنید.
public function users() {
return $this->hasMany('App\User');
}
اما آیا می دانستید که در این مرحله ما می توانیم Where
یا orderBy
را اضافه کنیم؟ به عنوان مثال، اگر می خواهید یک رابطه خاص برای برخی از انواع کاربران، همچنین از طریق ایمیل سفارش داده شود، می توانید این کار را انجام دهید:
public function approvedUsers() {
return $this->hasMany('App\User')->where('approved', 1)->orderBy('email');
}
5. ویژگی های مدل: timestamps، ضمیمه ها و غیره
چند "پارامتر" از یک مدل Eloquent به شکل ویژگی های آن کلاس وجود دارد. احتمالاً محبوب ترین آنها عبارتند از:
class User extends Model {
protected $table = 'users';
protected $fillable = ['email', 'password']; // which fields can be filled with User::create()
protected $dates = ['created_at', 'deleted_at']; // which fields will be Carbon-ized
protected $appends = ['field1', 'field2']; // additional values returned in JSON
}
اما صبر کنید، موارد بیشتری وجود دارد:
protected $primaryKey = 'uuid'; // it doesn't have to be "id"
public $incrementing = false; // and it doesn't even have to be auto-incrementing!
protected $perPage = 25; // Yes, you can override pagination count PER MODEL (default 15)
const CREATED_AT = 'created_at';
const UPDATED_AT = 'updated_at'; // Yes, even those names can be overridden
public $timestamps = false; // or even not used at all
و حتی موارد بیشتری نیز وجود دارد، من جالبترین آنها را فهرست کردهام، برای اطلاعات بیشتر لطفاً کد کلاس مدل آبسترک پیشفرض را بررسی کنید و تمام ویژگیهای استفاده شده را بررسی کنید.
برای آشنایی با مهم ترین ترفند ها و روش ها در لاراول Restful API این مقاله را بررسی کنید.
آیا با تزریق وابستگی در لاراول آشنا هستید؟ اگر نیستید این مقاله می تواند برای شما مفید باشد.
6. ورودی های متعدد را پیدا کنید
همه متد ()find
را می شناسند، درست است؟
$user = User::find(1);
من کاملا متعجبم که چند نفر از این موضوع می دانند که می تواند چندین ID را به عنوان یک آرایه بپذیرد:
$users = User::find([1,2,3]);
7. الکونت WhereX
یک راه زیبا برای تبدیل این کد وجود دارد:
$users = User::where('approved', 1)->get();
به این کد:
$users = User::whereApproved(1)->get()
بله، می توانید نام هر فیلدی را تغییر دهید و آن را به عنوان پسوند به "where" اضافه کنید و با مجیک کار می کند.
همچنین چند متد از پیش تعریف شده در Eloquent مربوط به تاریخ/زمان وجود دارد:
User::whereDate('created_at', date('Y-m-d'));
User::whereDay('created_at', date('d'));
User::whereMonth('created_at', date('m'));
User::whereYear('created_at', date('Y'));
8. ترتیب بر اساس روابط
یک "ترفند" کمی پیچیده تر. اگر موضوعات فروم دارید اما می خواهید آنها را با آخرین پست سفارش دهید چه؟ نیاز بسیار رایج در انجمن ها با آخرین موضوعات به روز شده در بالا، درست است؟
ابتدا، یک رابطه جداگانه برای آخرین پست در مورد موضوع :
public function latestPost()
{
return $this->hasOne(\App\Post::class)->latest();
}
و سپس، در کنترلر خود، می توانیم این "مجیک" را انجام دهیم:
$users = Topic::with('latestPost')->get()->sortByDesc('latestPost.created_at');
برای آشنایی با هنر اعتبار سنجی در لاراول این مقاله را بررسی کنید.
9. ()Eloquent::when، دیگر if-else’s نیست
بسیاری از ما کوئری های شرطی را با "if-else
" می نویسیم، چیزی شبیه به این:
if (request('filter_by') == 'likes') {
$query->where('likes', '>', request('likes_amount', 0));
}
if (request('filter_by') == 'date') {
$query->orderBy('created_at', request('ordering_rule', 'desc'));
}
اما راه بهتری وجود دارد – استفاده از ()When
:
$query = Author::query();
$query->when(request('filter_by') == 'likes', function ($q) {
return $q->where('likes', '>', request('likes_amount', 0));
});
$query->when(request('filter_by') == 'date', function ($q) {
return $q->orderBy('created_at', request('ordering_rule', 'desc'));
});
ممکن است کوتاهتر یا ظریفتر به نظر نرسد، اما قدرتمندترین آن عبور از پارامترها است:
$query = User::query();
$query->when(request('role', false), function ($q, $role) {
return $q->where('role_id', $role);
});
$authors = $query->get();
آیا با لاراول Octane آشنا هستید این مقاله را بررسی کنید.
10. رابطه BelongsTo مدل های پیش فرض
فرض کنید پست متعلق به نویسنده و سپس کد Blade دارید:
{{ $post->author->name }}
اما اگر نویسنده حذف شود، یا به دلایلی تنظیم نشده باشد، چه؟ شما یک خطا دریافت خواهید کرد، چیزی مانند "property of non-object".
البته می توانید از این طریق جلوگیری کنید:
{{ $post->author->name ?? '' }}
اما می توانید این کار را در سطح رابطه Eloquent انجام دهید:
public function author()
{
return $this->belongsTo('App\Author')->withDefault();
}
در این مثال، رابطه ()author
یک مدل خالی App\Author
را برمیگرداند اگر هیچ نویسندهای به پست ضمیمه نشده باشد.
علاوه بر این، میتوانیم مقادیر ویژگی پیشفرض را به آن مدل پیشفرض اختصاص دهیم.
public function author()
{
return $this->belongsTo('App\Author')->withDefault([
'name' => 'Guest Author'
]);
}
11. سفارش توسط Mutator
تصور کنید این کد را دارید:
function getFullNameAttribute()
{
return $this->attributes['first_name'] . ' ' . $this->attributes['last_name'];
}
حالا، میخواهید با آن full_name
سفارش دهید؟ این کد زیر کار نخواهد کرد:
$clients = Client::orderBy('full_name')->get(); // doesn't work
راه حل کاملا ساده است. پس از دریافت نتایج باید سفارش دهیم.
$clients = Client::get()->sortBy('full_name'); // works!
توجه داشته باشید که نام تابع متفاوت است، orderBy
نیست، sortBy
است.
12. ترتیب پیش فرض در اسکوپ گلوبال
اگر بخواهید که ()User::all
همیشه بر اساس فیلد name
مرتب شود چه؟ شما می توانید یک اسکوپ گلوبال اختصاص دهید. بیایید به متد ()boot
که قبلاً در بالا به آن اشاره کردیم برگردیم.
protected static function boot()
{
parent::boot();
// Order by name ASC
static::addGlobalScope('order', function (Builder $builder) {
$builder->orderBy('name', 'asc');
});
}
13. متد های کوئری خام
گاهی لازم است کوئری های خام را به عبارات Eloquent خود اضافه کنیم. خوشبختانه، توابعی برای آن وجود دارد.
// whereRaw
$orders = DB::table('orders')
->whereRaw('price > IF(state = "TX", ?, 100)', [200])
->get();
// havingRaw
Product::groupBy('category_id')->havingRaw('COUNT(*) > 1')->get();
// orderByRaw
User::where('created_at', '>', '2016-01-01')
->orderByRaw('(updated_at - created_at) desc')
->get();
14. Replicate: یک کپی از یک ردیف بسازید
این یکی کوتاه است. بدون توضیح عمیق، در اینجا بهترین راه برای کپی کردن ورودی پایگاه داده وجود دارد:
$task = Tasks::find(1);
$newTask = $task->replicate();
$newTask->save();
15. متد ()Chunk
برای جداول بزرگ
دقیقاً مربوط به Eloquent نیست، بیشتر درباره Collection است، اما همچنان قدرتمند است، برای پردازش مجموعه داده های بزرگتر، می توانید آنها را به قطعات تکه تکه کنید.
بجای کد زیر:
$users = User::all();
foreach ($users as $user) {
// ...
شما می توانید این کد را بنویسید:
User::chunk(100, function ($users) {
foreach ($users as $user) {
// ...
}
});
16. هنگام ایجاد یک مدل چیزهای اضافی ایجاد کنید
همه ما این دستور Artisan را می دانیم:
php artisan make:model Company
اما آیا می دانید سه فلگ مفید برای تولید فایل های مرتبط با مدل وجود دارد؟
php artisan make:model Company -mcr
m- یک فایل مایگرشن ایجاد می کند
c -یک کنترلر ایجاد می کند
r- نشان خواهد داد که کنترلر باید resourceful باشد
17. هنگام ذخیره، updated_at
را لغو کنید
آیا می دانستید که متد ()save<-
می تواند پارامترها را بپذیرد؟ در نتیجه، میتوانیم به آن بگوییم که متد پیشفرض updated_at
را نادیده بگیرد تا با تایم زمانی فعلی پر شود.
این را ببینید:
$product = Product::find($id);
$product->updated_at = '2019-01-01 10:00:00';
$product->save(['timestamps' => false]);
در اینجا ما پیشفرض updated_at
را با نسخه از پیش تعریفشده خود لغو میکنیم.
18. نتیجه یک ()update چیست؟
آیا تا به حال فکر کرده اید که این کد در واقع چه چیزی را برمی گرداند؟
$result = $products->whereNull('category_id')->update(['category_id' => 2]);
منظورم این است که به روز رسانی در پایگاه داده انجام می شود، اما نتیجه result$
چه چیزی را شامل می شود؟
پاسخ ردیف های تحت تاثیر قرار می گیرد. بنابراین اگر باید بررسی کنید که چند ردیف تحت تأثیر قرار گرفته اند، نیازی نیست چیز دیگری را فراخوانی کنید - متد ()update
این شماره را برای شما برمی گرداند.
19. براکت ها را به یک کوئری Eloquent تبدیل کنید
اگر کوئریی SQL خود را داشته باشید و یا مخلوط کنید، مانند این، چه اتفاقی میافتد:
... WHERE (gender = 'Male' and age >= 18) or (gender = 'Female' and age >= 65)
چگونه آن را به Eloquent ترجمه کنیم؟ این راه اشتباه است:
$q->where('gender', 'Male');
$q->orWhere('age', '>=', 18);
$q->where('gender', 'Female');
$q->orWhere('age', '>=', 65);
ترتیب نادرست خواهد بود. راه درست کمی پیچیده تر است، با استفاده از closure functions به عنوان کوئری های فرعی:
$q->where(function ($query) {
$query->where('gender', 'Male')
->where('age', '>=', 18);
})->orWhere(function($query) {
$query->where('gender', 'Female')
->where('age', '>=', 65);
})
20. orWhere با چند پارامتر
در نهایت، میتوانید آرایهای از پارامترها را به ()orWhere
ارسال کنید. متد "معمول":
$q->where('a', 1);
$q->orWhere('b', 2);
$q->orWhere('c', 3);
شما می توانید این کار را به این صورت انجام دهید:
$q->where('a', 1);
$q->orWhere(['b' => 2, 'c' => 3]);
نتیجه
Eloquent یک ORM قدرتمند است که با چارچوب لاراول ساخته شده است. بسیاری از کوئری های پیچیدهای را که برای مقابله با روابط، ایجاد، بهروزرسانی، و حذف رکوردهای پایگاه داده و جستجو، فیلتر کردن و محدود کردن نتایج کوئری ضروری هستند، خلاصه میکند. اگر متد الکونت دیگری می شناسید که بسیار پر کاربرد است ولی در اینجا به آن اشاره نشده است در قسمت نظرات آن را با ما به اشتراک بگذارید.