eloquent در لاراول یک مکانیزم کار با پایگاه داده است. روش هایی در eloquent برای کار با پایگاه داده وجود دارد که کمتر شناخته شده هستند. در این مقاله قصد معرفی این روش ها را داریم.
۱. Increement and Decrement
به جای استفاده از کد زیر:
$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
۲.متد X or Y
eloquent توابع زیادی برای ترکیب دو روش شرطی دارد:
به جای استفاده از کد زیر:
$user = User::find($id);
if (!$user) { abort (404); }
$user = User::findOrFail($id);
به جای استفاده از کد زیر:
$user = User::where('email', $email)->first();
if (!$user) {
User::create([
'email' => $email
]);
}
$user = User::firstOrCreate(['email' => $email]);
۳.متد 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();
});
}
۴. relation های جداول بر اساس شرط و مرتب سازی
کد زیر روش معمول ایجاد یک رابطه است:
public function users() {
return $this->hasMany('App\User');
}
اما آیا می دانستید که در این مرحله ما می توانیم OrderBy اضافه کنیم؟ برای مثال، اگر میخواهید رابطه خاصی برای برخی از کاربران ایجاد کنید و یا از طریق ایمیل، میتوانید این کار را انجام دهید:
public function approvedUsers() {
return $this->hasMany('App\User')->where('approved', 1)->orderBy('email');
}
۵. خواص مدل
چند پارامتر به شکل خواص آن کلاس از یک مدل 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
۶.ورودی های متعدد را پیدا کنید
روش معمول استفاده از find:
می توانید به این متد یک آرایه بدهید:
$users = User::find([1,2,3]);
۷. WhereX
به جای استفاده از کد زیر:
$users = User::where('approved', 1)->get();
از کد زیر استفاده کنید:
$users = User::whereApproved(1)->get();
۸. Order by relationship
اگر شما موضوعات مورد علاقه را دارید، اما می خواهید آنها را با آخرین پست سفارش دهید؟ ابتدا یک رابطه جداگانه برای آخرین پست در مورد موضوع بنویسید:
public function latestPost()
{
return $this->hasOne(\App\Post::class)->latest();
}
و سپس، در کنترل ما، می توانیم از کد زیر استفاده کنیم
$users = Topic::with('latestPost')->get()->sortByDesc('latestPost.created_at');
۹. 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'));
}
اما روش بهتری هم وجود دارد:
$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();
۱۰. BelongsTo Default Models
بگذارید بگوییم پست متعلق به نویسنده و سپس کد blade:
{{ $post->author->name }}
اما اگر نویسنده حذف شود، یا به دلایلی تنظیم نشده باشد چه اتفاقی میافتد؟ شما یک خطایی خواهید داشت، چیزی شبیه "property of non-object".
برای رفع این خطا از کد زیر استفاده کنید:
{{ $post->author->name ?? '' }}
اما شما می توانید این کار را در سطح رابطه Eloquent انجام دهید:
public function author()
{
return $this->belongsTo('App\Author')->withDefault();
}
در این مثال، نویسنده رابطه یک مدل خالی App \ Author را در صورتی که هیچ نویسنده ای به پست اضافه نشده باشد، باز می گردد. علاوه بر این، می توانیم مقادیر پیش فرض را به آن مدل پیش فرض اختصاص دهیم.
public function author()
{
return $this->belongsTo('App\Author')->withDefault([
'name' => 'Guest Author'
]);
}
۱۱. Order by 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!
۱۲. مرتب سازی پیش فرض در global scope
اگر می خواهید User :: all () را با نام field مرتب کنید، چه؟ شما می توانید global scope را اختصاص دهید. بیایید به متد boot () برویم، که قبلا در بالا ذکر شد.
protected static function boot()
{
parent::boot();
// Order by name ASC
static::addGlobalScope('order', function (Builder $builder) {
$builder->orderBy('name', 'asc');
});
}
13. Raw query methods
گاهی اوقات ما نیاز به اضافه کردن Raw Query به 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();
۱۴. Replicate: کپی از یک سطر
بهترین راه برای کپی کردن یک رکورد از پایگاه داده
$task = Tasks::find(1);
$newTask = $task->replicate();
$newTask->save();
۱۵. متد chunk برای جداول بزرگ
برای پردازش داده های بزرگتر، شما می توانید آنها را به قطعات کوچکتر تقسیم کنید. به جای استفاده از کد زیر:
$users = User::all();
foreach ($users as $user) {
// ...
از کد زیر استفاده کنید
User::chunk(100, function ($users) {
foreach ($users as $user) {
// ...
}
});
۱۶. هنگام ایجاد یک مدل، چیزهای اضافی ایجاد کنید
با دستور زیر آشنا هستید:
php artisan make:model Company
اما آیا می دانید سه Flag مفید برای تولید فایل های مربوط به مدل وجود دارد؟
php artisan make:model Company -mcr
- -m یک فایل migration ایجاد می کند
- -c یک controller ایجاد خواهد کرد
- -r نشان می دهد که Reource های کنترلر باید کامل باشد.
۱۷. غیر فعال کردن updated_at در زمان save
آیا می دانید تابع save پارامتر می پذیرد؟ میتوانیم فیلد updated_at که به طور پیش فرض با تاریخ و زمان فعلی پر می شود را غیر فعال کنیم
$product = Product::find($id);
$product->updated_at = '2019-01-01 10:00:00';
$product->save(['timestamps' => false]);
۱۸. نتیجه یک update چیست؟
$result = $products->whereNull('category_id')->update(['category_id' => 2]);
منظور این است که بروز رسانی در پایگاه داده انجام می شود، اما نتیجه چیست؟ پاسخ بر روی row ها تاثیر می گذارد. بنابراین اگر شما نیاز دارید که چند row را تحت تأثیر قرار دهید، نیازی به تماس با هیچ چیز دیگری ندارید، روش ()update این عدد را برای شما باز می گرداند.
۱۸. تبدیل query به یک پرس و جوی پیش فرض در eloquent
اگر شما در کد خود همزمان از and و or استفاده می کنید:
... 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);
راه درست کمی پیچیده تر است. با استفاده از sub-queries:
$q->where(function ($query) {
$query->where('gender', 'Male')
->where('age', '>=', 18);
})->orWhere(function($query) {
$query->where('gender', 'Female')
->where('age', '>=', 65);
})
۲۰. OrWhere با چند پارامتر
در نهایت شما می توانید آرایه ای از پارامترها را به orWhere () منتقل کنید.
به جای استفاده از کد زیر:
$q->where('a', 1);
$q->orWhere('b', 2);
$q->orWhere('c', 3);
از کد زیر استفاده کنید:
$q->where('a', 1);
$q->orWhere(['b' => 2, 'c' => 3]);