Tampilkan data dengan default properti yang Anda inginkan, tidak hanya itu. Scope juga bisa membantu kita dalam membuat kode kita lebih readable.
Tampilkan data dengan default properti yang Anda inginkan, tidak hanya itu. Scope juga bisa membantu kita dalam membuat kode kita lebih readable.
Sebelum kita memulainya, pertama saya akan menunjukkan perbedaan dari sebelum dan sesudah.
// Before
Article::where('user_id', $request->user())->where('status', ArticleStatus::PUBLISHED)->get();
// After
Article::query()->wherePublishedAndBelongsToMe()->get();
Karena di sini saya mencontohkan dengan artikel, maka kita akan menganggap bahwa ada status pada artikel tersebut. Seperti misalnya unpublished
dan published
. Sehingga jika Anda melihat contoh di atas, itu hanya menggunakan enum dari PHP. Kurang lebih enum nya seperti ini.
enum ArticleStatus: int
{
case UNPUBLISHED = 0;
case PREVIEW = 1;
case PUBLISHED = 2;
}
Nah pada sekarang, buka model artikel dan tambahkan 3 metode di dalamnya dengan prefix scopeNameOfFunction
seperti:
use App\Enums\ArticleStatus;
use Illuminate\Contracts\Database\Query\Builder;
class Article extends Model
{
//...
public function scopeWherePublished(Builder $builder)
{
return $builder->where('status', ArticleStatus::PUBLISHED);
}
public function scopeWhereBelongsToMe(Builder $builder)
{
return $builder->whereBelongsTo(auth()?->user());
}
public function scopeWherePublishedAndBelongsToMe(Builder $builder)
{
return $builder->wherePublished()->whereBelongsToMe();
}
}
Setelah itu, maka kalian sudah bisa menggukan seperti contoh di atas, hanya saja untuk metode scopeWhereBelongsToMe
ada sedikit pengecualian. Pastikan jika Anda ingin memakainya itu tepat di halaman yang sudah di proteksi middleware auth
. Itu hanya contoh, pastinya Anda bisa membuat apapun yang diinginkan.
Baik untuk cara penggunaan nya itu sangat mudah sekali, jika kita butuh yang hanya bersatus published
, maka kita bisa melakukan nya seperti:
Article::query()->wherePublished()->get();
Dan jika kalian ingin menampilkan semua yang bersangkutan dengan user yang sedang login dan tidak peduli dengan statusnya bisa seperti:
Article::query()->whereBelongsToMe()->get();
Dan pastinya, jika kalian ingin kedua-dua nya itu bisa seperti:
Article::query()->whereBelongsToMe()->wherePublished()->get();
Atau disatukan dengan prefix and
seperti:
Article::query()->wherePublishedAndBelongsToMe()->get();
Kurang lebih untuk penggunaan scope
seperti itu. Namun scope yang kita lakukan di atas masih disebut dengan scope secara local. Mengapa seperti itu ? Karena sebenarnya ada cara untuk scope secara global. Jadi scope nya itu diterapkan by default.
Sekarang kita akan mencontohkannya langsung. Buka terminal Anda dan jalankan perintah artisan untuk membuat scope seperti:
php artisan make:scope PublishedScope
Setelah itu, maka dia akan membuatkan kita 1 folder Scopes
yang di dalam nya ada file ArticleScope.php
. Lihat file nya tepat di dalam direktori app/Models/Scopes/ArticleScope.php
. Ingat, bahwa class ini hanya mengandung 1 metode yaitu apply
, jadi jika Anda mencoba untuk membuat 1 lagi metode dibawahnya maka itu akan error. Karena class ini sendiri di implementasikan dengan interface Scope
yang di dalamnya hanya ada 1 metode seperti:
public function apply(Builder $builder, Model $model);
Nah, sekarang Anda bisa masukkan query yang ingin dibuat tepat pada metode apply
itu seperti:
class PublishedScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
return $builder->where('status', ArticleStatus::PUBLISHED)->latest();
}
}
Selanjutnya Anda bisa mendaftarkan scope itu secara global tepat pada model yang membutuhkan nya.
class Article extends Model
{
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::addGlobalScope(new PublishedScope);
}
}
Jika seandainya model user juga membutuhkan scope itu, maka Anda bisa juga meletekkan nya di sana seperti:
class User extends Model
{
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::addGlobalScope(new PublishedScope);
}
}
Jika kalian tidak ingin membuatnya di luar dari dari model itu, bisa dengan menggunakan anonymous global scope seperti:
class User extends Model
{
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::addGlobalScope('published', function (Builder $builder) {
$builder->where('status', Article::PUBLISHED);
});
}
}
Terkadang kita tidak ingin menggunakan scope ini, misalnya kita ingin menampiklan semua artikel tanpa memperhatikan statusnya. Maka itu bisa dicegah dengan menambahkan metode withoutGlobalScope
seperti:
Article::withoutGlobalScope(PublishedScope::class)->get();
Atau jika Anda menggunakan anonymous global scope bisa dengan langsung memasukkan namanya seperti:
Article::withoutGlobalScope('published')->get();
Semoga artikel ini bermanfaat. Until next time 👋🏻
Let's start living like no one can help us in any event, so that when we are helped in certain times, it becomes a plus in itself.