نکته و ترفند Eloquent در لاراول
- دسته بندی : لاراول
- تاریخ انتشار : ۰۷ دی ۱۳۹۹
- تاریخ به روز رسانی : ۱۱ دی ۱۳۹۹

استفاده از Eloquent ها میتواند در طراحی و برنامه نویسی بسیار کمک کند. در این مقاله سعی شده نکات Eloquent را که با عنوان های ۲۰ نکته و ترفند درباره Eloquent در لاراول یا ۶ ترفند Eloquent که هر توسعه دهنده laravel باید بداند و …. مطرح شده ، گردآوری و توضیح داده شود.
Eloquent ORM به نظر میرسد یک مکانیزم ساده است، اما اگر به درون آن دقت کنیم، بسیاری از کارکردهای نیمهپنهان و روشهای کمتر شناخته شده برای دستیابی بیشتر به آن وجود دارد.
۱ – افزایش و کاهش ( Increments and Decrements )
به جای این:
$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 یا Y
Eloquent دارای چندین فانکشن ( functions ) است که دو متد را ترکیب می کند ، مانند “لطفا X را انجام بده ، در غیر این صورت Y را انجام بده”.
مثال ۱ – findOrFail() :
بجای این کار :
$user = User::find($id); if (!$user) { abort (404); }
این کار را انجام بده :
$user = User::findOrFail($id);
مثال ۲ – firstOrCreate() :
بجای این کار :
$user = User::where('email', $email)->first(); if (!$user) { User::create([ 'email' => $email ]); }
این کار را انجام بده :
$user = User::firstOrCreate(['email' => $email]);
۳ – متد Model boot()
یک مکان جادویی به نام boot () در Eloquent model وجود دارد که می توانید رفتار پیش فرض را نادیده بگیرید :
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); }); } }
احتمالاً یکی از محبوبترین نمونهها تعیین مقدار فیلد در زمان ساخت model object است. بیایید بگوییم که شما در آن لحظه میخواهید فیلدUUID را تولید کنید.
public static function boot() { parent::boot(); self::creating(function ($model) { $model->uuid = (string)Uuid::generate(); }); }
۴- ارتباط با شرایط و ترتیب
این یک روش معمول برای تعریف رابطه است:
public function users() { return $this->hasMany('App\User'); }
اما آیا می دانید در این مرحله می توانیم where یا orderBy را اضافه کنیم؟
برای مثال ، اگر تو میخوای یه رابطه خاصی برای بعضی از کاربران داشته باشی ، میتوانی با ایمیل آنهارا مرتب کنی، برای اینکار :
public function approvedUsers() { return $this->hasMany('App\User')->where('approved', 1)->orderBy('email'); }
۵- ویژگیهای مدل: timestamp ها ،append ها و …
چند پارامتر از یک Eloquent model ، در قالب ویژگی های آن کلاس وجود دارد. مشهورترین آن ها احتمالاً این موارد هستند :
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
و حتی موارد جالب دیگری نیز وجود دارد که من جالب ترین آن ها را ذکر کردم، برای اطلاعات بیشتر لطفاً کد abstract Model class پیش فرض را چک کنید و تمام صفات مورد استفاده را بررسی کنید.
۶- پیدا کردن چند ورودی
همه متد find() را میشناسند، درست است؟
$user = User::find(1);
من خیلی تعجب کردم که چطور تعداد کمی از این موضوع آگاه هستند که این دستور میتوان چند آیدی را به عنوان یک آرایه بپذیرند:
$users = User::find([1,2,3]);
۷- Where X
یک روش زیبا برای برگرداندن وجود دارد:
$users = User::where('approved', 1)->get();
در این مورد:
$users = User::whereApproved(1)->get();
بله میتوانید نام هر فیلد را تغییر دهید و آن را به عنوان suffix ( پسوند ) به 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'));
۸- مرتب کردن بر اساس رابطه
یک ترفند کمی پیچیدهتر. اگر مباحث تالار گفتگو دارید اما بخواهید آنها را با آخرین پست مرتب کنید چکار میکنید؟ یک مورد کاملا معمول در انجمنها با آخرین موضوعات به روز شده در بالا، درست است؟
ابتدا یک رابطه جداگانه برای آخرین پست آن موضوع تعریف کنید:
public function latestPost() { return $this->hasOne(\App\Post::class)->latest(); }
و سپس، در controller مان، میتوانیم این جادو را انجام دهیم:
$users = Topic::with('latestPost')->get()->sortByDesc('latestPost.created_at');
۹- استفاده از when() در مبحث Eloquent ، دیگر 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();
۱۰- BelongsTo پیشفرض مدلها
بیایید بگوییم که شما پستی دارید که متعلق به نویسنده است و سپس کد Blade آن :
{{ $post->author->name }}
اما اگر نویسنده حذف شود، یا به دلایلی تنظیم نشده باشد چه خواهد شد؟ شما خطایی دریافت خواهید کرد، مثل “property of non-object”.
البته، شما می توانید از این جلوگیری کنید ، مثل این:
{{ $post->author->name ?? '' }}
اما شما می توانید آن را در سطح Eloquent relationship انجام دهید:
public function author() { return $this->belongsTo('App\Author')->withDefault(); }
در این مثال، در صورتی که نویسنده ای به پست اختصاص نداشته باشد، ارتباط author() یک App\Author model خالی بر می گرداند.
به علاوه، میتوانیم مقدار property پیشفرض را به آن مدل پیش فرض اختصاص دهیم.
public function author() { return $this->belongsTo('App\Author')->withDefault([ 'name' => 'Guest Author' ]); }
۱۱- مرتب سازی به وسیله 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!
توجه کنید که نام فانکشن متفاوت است ، order By نشده ، sortBy شده است.
۱۲ – مرتب سازی پیش فرض در global scope
اگر بخواهید User::all() همیشه با فیلد name مرتب باشد چکار می کنید؟ می توانید یک global scope اختصاص دهید. بیایید به متد boot() که قبلاً اشاره کردیم، برگردیم.
protected static function boot() { parent::boot(); // Order by name ASC static::addGlobalScope('order', function (Builder $builder) { $builder->orderBy('name', 'asc'); }); }
اطلاعات بیشتر درمورد Query Scope ها را بخوانید.
۱۳ – متدهای کوئری خام ( Raw query )
بعضی اوقات ما نیاز به اضافه کردن نمایش داده های خام به Eloquent statement های خود داریم. خوشبختانه، فانکشن هایی برای آن وجود دارد.
// 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();
۱۴- تکرار: یک کپی از یک سطر ایجاد کنید
کوتاه و بدون توضیحات عمیق، بهترین روش تهیه کپی از ورود پایگاه داده در اینجا است:
$task = Tasks::find(1); $newTask = $task->replicate(); $newTask->save();
منبع laravel-news.com
نظرات کاربران