Tips Menggunakan Eloquent Laravel

Tips Menggunakan Eloquent Laravel

Pendahuluan

Eloquent adalah salah satu fitur yang menarik yang dimiliki oleh Laravel, dengannya kita dapat berinteraksi dan memanipulasi database sesuai yang diinginkan. Setiap model Eloquent yang telah dibuat adalah representasi table dari database yang ada.

Artikel ini dikhususkan buat kamu yang telah memahami bagaimana cara menggunakan Eloquent, setidaknya kamu telah bisa memanipulasi data (baca: delete, create, update, show). Sebab sepanjang artikel ini hanya akan membahas bagaimana tips memaksimalkan fitur dari Eloquent yang sebaiknya digunakan agar code kamu terlihan lebih menarik dilihat.

Baca Juga: Membuat Aplikasi POS (Point of Sales) Laravel 5.6 - Laporan

Eloquent Query Scope

Query Scope memungkian kamu untuk membuat sebuah fungsi query yang dapat digunakan kembali sepanjang aplikasi yang sedang kamu buat. Scope memiliki dua bagian, yakni, Global Scope dan Local Scope. Kedua hal ini tentu saja dapat membantu kamu dalam meminimalisir dalam menuliskan sesuatu yang sama secara berulang-ulang, sehingga kamu dapat lebih mudah me-maintan dan terlihat lebih rapi.

Lalu apa perbedaan dari keduanya? Sesuai namanya, jika Global Scope akan menjalankan fungsi yang telah didefinisikan setiap kali Model tersebut digunakan. Sedangkan Local scope hanya akan berjalan ketika nama fungsi yang telah didefinisikan tersebut dituliskan.

Mari kita buat pemisalan apa efektifnya menerapkan scope ini dalam model yang kita miliki. So, misalnya saja kamu akan me-load postingan dengan ketentuan statusnya active dan diurutkan berdasarkan data yang terakhir kali dibuat (baca: descending), maka yang akan kamu lakukan adalah:

$post = Post::where('status', 1)->orderBy('created_at', 'DESC')->get();

Lalu apa yang salah dari query diatas? Benar, tidak ada yang salah, namun bagaimana jadinya jika data post kamu load dengan ketentuan seperti diatas pada halaman yang berbeda-beda? Tentu saja kamu akan menuliskan code yang sama disetiap halaman yang kamu inginkan, betul?

Hindari kebiasaan tersebut, dan mari kita lakukan evolusi dengan menggunakan scope.

Local Scope

Buka model terkait yang diterapkan fungsi dari scope, dalam hal ini Post.php kemudian tambahkan method berikut:

public function scopeActiveDesc($query)
{
    return $query->where('status', 1)->orderBy('created_at', 'DESC');
}

Penjelasan: Perhatian, Local Scope diawali dengan kata scope kemudian diikuti dengan nama yang di-inginkan, dalam hal ini ActiveDesc . Parameter yang diterima adalah $query, dimana variable ini akan digunakan untuk membuat kondisi.

Sehingga evolusi dari query panjang yang telah dituliskan diawal, setelah menggunakan scope, penggunaannya akan menjadi:

$post = Post::activeDesc()->get();

Sederhana buka? So, ketika kamu membutuhkannya ditempat lain maka kamu cukup menambahkan activeDesc dalam rangkaian model yang terkait.

Dynamic Scope

Kondisi yang dapat diterapkan dalam scope tidak hanya dan harus bersifat statis, namun juga dapat bersifat dinamis tergantung parameter yang dikirimkan ketika scope tersebut digunakan. Untuk membuat scope yang dinamis, maka kamu dapat mendefinisikannya seperti berikut:

public function scopeActiveOrder($query, $order)
{
    return $query->where('status', 1)->orderBy('created_at', $order);
}

Penjelasan: Contoh code diatas menunjukkan dimana salah satu kondisi dalam mengurutkan data bersifat dinamis tergantung nilai dari parameter yang diterima.

Sedangkan untuk cara menggunakannya dapat kamu tuliskan menjadi:

$post = Post::activeOrder('DESC')->get();
​
//atau
$post = Post::activeOrder('ASC')->get();

Global Scope

Ada dua cara penerapan Globa Scope, yakni dengan menggunakan membuat file bantuan untuk menuliskan logic yang akan diterapkan, dan yang kedua adalah dengan metode anonymous yaknik logic yang diinginkan langsung diterapkan pada model yang terkait.

Cara pertama, masih dengan kasus yang serupa, buat file ActiveScope.php yang diletakkan didalam folder app/Scopes, kemudian tambahkan code berikut:

<?php
​
namespace App\Scopes;
​
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
​
class ActiveScope implements Scope
{
    public function apply(Builder $builder, Model $model)
    {
        $builder->where('status', 1)->orderBy('created_at', 'DESC');
    }
}

Kemudian buka file model Post.php dan tambahkan method berikut:

protected static function boot()
{
    parent::boot();
​
    static::addGlobalScope(new ActiveScope);
}

Jangan lupa tambahkan use statement untuk me-load file ActiveScope

use App\Scopes\ActiveScope;

Fungsi yang diterapkan sama saja yang telah dilakukan pada Local Scope, hanya saja pada Global Scope, penggunaannya tidak perlu lagi menuliskan nama function yang telah didefinisikan karena secara otomatis akan berjalan ketika model tersebut digunakan. Sehingga penggunaannya cukup dengan:

$post = Post::get();

Kode diatas akan menjalankan Global Scope dimana telah diatur ketentuan dengan kondisi where status = 1 dan orderBy created_at, keren bukan? Lalu bagaimana jika kondisi tersebut tidak ingin saya jalankan pada bagian tertentu? Tenang saja, kita dapat skip Global Scope tersebut dengan code:

$post = Post::withoutGlobalScope(ActiveScope::class)->get();

Atau jika lebih dari satu Global Scope yang diterapkan pada model Post dan juga tidak ingin me-load-nya, kamu dapat menggunakan pendekatan berikut:

$post = Post::withoutGlobalScope([
    ActiveScope::class, OtherScope::class
])->get();

Atau kamu tidak ingin me-load semua scope yang telah didefinisikan? Caranya juga mudah dengan pendekatan berikut:

$post = Post::withoutGlobalScopes()->get();

Cara kedua dalam mendefinisikan Global Scope adalah dengan metode anonymous scope, yakni sebagaimana dijelaskan diawal bahwa logic-nya didefinisikan langsung pada model yang terakit, buka file Post.php kemudian tambahkan code berikut:

protected static function boot()
{
    parent::boot();
​
    static::addGlobalScope('activeDesc', function (Builder $builder) {
        $builder->where('status', 1)->orderBy('created_at', 'DESC');
    });
}

Nah, jika kamu ingin skip Global scope tersebut, dengan kata lain tidak ingin menggunakannya, kamu bisa melakukan pendekatan berikut:

$post = Post::withoutGlobalScope('activeDesc')->get();

Baca Juga: Membuat Aplikasi POS (Point of Sales) Laravel 5.6 - Transaksi (Bagian 2)

Increment & Decrement

Pernah tidak kamu membuat sebuah fitur, misalnya saja adalah untuk menghitung berapa kali artikel tersebut dilihat. Pastinya untuk mewujudkannya adalah dengan menggunakan logika sederhana, yakni mengambil total view yang terakhir kali disimpan kemudian ditambahkan nilai 1. Jika diwujudkan dalam code, maka akan tampak seperti ini:

$post = Post::find($id);
$post->update(['views' => $post->views+1]);

Atau dalam bentuk lainnya:

$post = Post::find($id);
$post->views++;
$post->save();

Tidak ada yang salah dari cara tersebut, dan sah sah saja jika kamu ingin menggunakan pendekatan seperti itu. Namun, tahu nggak sih? Eloquent memiliki fungsi dengan nama increment yang menyelesaikan case kamu, sehingga code diatas dapat kamu menggunakan pendekatan berikut:

$post = Post::find($id);
$post->increment('views');

Increment juga menerima parameter tambahan, misalnya saja kamu ingin menambahkan nilai yang tidak hanya +1 dalam sekali hit-nya. Kamu dapat menggunakan fungsi berikut:

$post->increment('views', 10); //yang berarti +10

Sedangkan untuk decrement hanya mengganti nama method-nya saja, untuk cara penggunaannya sama saja.

$post->decrement('views') // -1
$post->decrement('views', 10) // -10

Handle Event Dengan OBServer

Event memungkin kamu untuk menjalankan sesuatu setelah kejadian tertentu terjadi. Misalnya saja, kamu ingin mengirim email notifikasi setelah proses registrasi berhasil dilakukan, maka logika sederhananya adalah kamu menyimpan data user ke dalam table yang terkait, kemudian setelah itu kamu menjalankan fungsi untuk mengirimkan email. Jika diterjemahkan kedalam coding akan tampak seperti berikut:

public function register(Request $request)
{
    $user = User::create([
        'name' => 'Daengweb',
        'email' => '[email protected]'
   ]);
    
    Mail::to($user->email)
            ->send(new PostMail($user));
}

Sekali lagi tidak ada yang salah dengan cara diatas untuk menyelesaikan case yang telah disebutkan sebelumnya. Namun terdapat cara yang lebih baik untuk meng-handle hal tersebut dengan menggunakan event. OBServers dapat digunakan untuk meng-handle event yang merepresentasikan pada model terkait.

Jalankan command berikut untuk membuat file Observer nya:

php artisan make:observer UserObServer --model=User

Penjelasan: Command diatas berarti akan men-generate file dengan nama UserObServer.php yang akan meng-handle event dari model User.php.

Buka file app/Observers/UserObServer.php, secara default terdapat 5 method yang mewakili kelima event yang tersedia yang dapat di-handle oleh ObServers. Jika dikaitkan dengan contoh diatas, maka method yang akan digunakan adalah created, karena fungsi email dijalankan setelah data berhasil disimpan. Pindahkan fungsi untuk mengirim email kedalam method created():

public function created(User $user)
{
    Mail::to($user->email)->send(new PostMail($user));
}

Agar ObServer yang dibuat dapat berjalan sebagaimana mestinya, maka register terlebih dahulu kedalam file AppServiceProvider.php, pada method boot() tambahkan code berikut:

public function boot()
{
    User::observe(UserObServer::class);
}

Where Multiple Parameter

Hal lainnya yang kadang kita temukan adalah lebih dari satu kondisi yang harus diterapkan dalam query. Misalnya saja kita ingin menampilkan data artikel yang statusnya true (1) dan artikel tersebut adalah kepemilikan dari user yang sedang login, tentu saja secara sederhana kita dapat melakukan hal berikut:

$post = Post::where('status', 1)->where('user_id', auth()->user()->id)->get();

Cara tersebut benar akan tetapi dapat kita sederhanakan menjadi:

$post = Post::where([
    'status' => 1, 
    'user_id' => auth()->user()->id
])->get();

Lebih rapi bukan?

Magic Of Artisan Make Model

Artisan adalah senjata pamungkas yang dimiliki oleh Laravel, sebab dengannya kita dapat men-generate file secara otomatis beserta kerangka code dari masing-masing file yang telah di-generate. Misalnya saja kamu ingin men-generate Controller, Migration dan Model untuk table posts, maka yang akan kamu lakukan adalah:

php artisan make:model Post
php artisan make:controller PostController
php artisan make:migration create_posts_table

Padahal dapat kamu sederhanakan menjadi:

php artisan make:model Post -m
php artisan make:controller PostController

Note: Line pertama akan men-generate model beserta migration-nya.

Atau bisa juga kamu sederhanakan menjadi:

php artisan make:model Post -mcr

Note: Command diatas akan men-generate Model, Controller dan Migration sekaligus.

Kesimpulan

Eloquent menyediakan berbagai method yang powerful untuk menunjukkan pesonanya. Aturan aturan yang dimilikinya dapat menuntun kamu untuk menghasilkan code yang lebih baik, sehingga kamu dapat lebih mudah dalam mengelolanya baik saat code tersebut pertama kali dituliskan, maupun dikemudian hari. Sehingga tidak ada lagi code yang hanya kamu dan Tuhan yang tahu maksudnya.

Category:
Share:

Comments