Adakalanya saat kita mengembangkan web, setelah kita perhatikan dan kita review kembali ternyata logika kita menumpuk di satu tempat, misalnya di controller class. Dan boleh jadi untuk satu logika bisnis ini menghabiskan banyak baris kode di satu method. Misalkan pada saat membuat blog (yang sering dijadikan studi kasus di sini) untuk proses insert data saja, kadang terdapat beberapa proses, di mulai dari validasi form, create data post baru, upload image untuk header post, ada proses kirim notifikasi ke subscriber dan lain-lain. Banyak proses dalam satu method. Biasanya kita ingin memisahkan logika ini ke tempat lain supaya codingan kita tidak terlalu banyak. Cara ini biasanya disebut refactor.
Mengutip tulisan om Martin Fowler, Refactor adalah teknik restrukturisasi kode program komputer yang ada tanpa mengubah perilaku eksternalnya. Sebagai contoh studi kasusnya, kita akan coba merefactor kode dari seri belajar laravel 8 sebelumnya tentang crud. Pada fitur crud tentu ada fitur menambahkan data dan update data dan di dalamnya terdapat proses validasi form. Bagian validasi form ini akan kita coba ubah dan pisahkan dari method untuk menambahkan data dan update data dengan menggunakan solusi yang terdapat pada framework laravel, yaitu Form Request Validation. Selain itu, kita juga akan coba menggunakan phpunit
untuk proses testing supaya setelah proses refactoring tidak mengubah fungsionalitas dari method yang sudah kita refactor nantinya. Nah, sekarang kita coba mulai belajar refactor controller.
Project yang akan kita gunakan dalam percobaan refactor kali ini adalah project hasil dari tutorial Testing Feature CRUD. Kenapa kita pakai project hasil dari tutorial tersebut? Karena kita perlu fitur CRUD yang sudah jadi dan yang akan kita coba refactor. Dan yang kedua kita juga perlu feature testing yang sudah kita coding di tutorial tersebut. Feature testing ini kita gunakan untuk memastikan tidak ada perubahan atau error ketika kita mengimplementasikan form request validation class. Jadi untuk mengikuti percobaan refactor kali ini, pastikan teman-teman sudah mengikuti tutorial testing feature crud, dari seri belajar laravel 8 sebelumnya.
Setelah sample project yang akan kita refactor siap, sebelum kita mulai refactor, kita run dulu phpunit. Buka terminal lalu kita run command berikut ini.
vendor/bin/phpunit
Output di terminal tampil hasil testing kurang lebih seperti di bawah ini.
PHPUnit 9.5.20 #StandWithUkraine
...... 6 / 6 (100%)
Time: 00:00.255, Memory: 32.00 MB
OK (6 tests, 26 assertions)
Karena belum ada perubahan jadi hasilnya masih sama seperti hasil seri belajar laravel 8 sebelumnya.
Sekarang kita cek kembali PostController.php
. Di dalam class PostController
terdapat dua method yang menggunakan proses validasi, yaitu store()
dan update()
.
<?php
// .. baris kode lainnya
class PostController extends Controller
{
// .. baris kode lainnya
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|string|max:155',
'content' => 'required',
'status' => 'required'
]);
$post = Post::create([
'title' => $request->title,
'content' => $request->content,
'status' => $request->status,
'slug' => Str::slug($request->title)
]);
if ($post) {
return redirect()
->route('post.index')
->with([
'success' => 'New post has been created successfully'
]);
} else {
return redirect()
->back()
->withInput()
->with([
'error' => 'Some problem occurred, please try again'
]);
}
}
// ...
public function update(Request $request, $id)
{
$this->validate($request, [
'title' => 'required|string|max:155',
'content' => 'required',
'status' => 'required'
]);
$post = Post::findOrFail($id);
$post->update([
'title' => $request->title,
'content' => $request->content,
'status' => $request->status,
'slug' => Str::slug($request->title)
]);
if ($post) {
return redirect()
->route('post.index')
->with([
'success' => 'Post has been updated successfully'
]);
} else {
return redirect()
->back()
->withInput()
->with([
'error' => 'Some problem has occured, please try again'
]);
}
}
// baris kode lainnya
}
Bagian yang akan kita refactor ini adalah bagian validasi untuk store()
dan update()
, jadi sekarang kita akan buat dua class Form Request Validation menggunakan artisan
command. Buka kembali terminal, lalu kita run command di bawah ini.
php artisan make:request StorePostRequest
php artisan make:request UpdatePostRequest
Setelah kita run dua command di atas, kita bisa lihat ada dua file baru hasil generate di direktori app/Http/Requests
, yaitu file StorePostRequest.php
dan UpdatePostRequest.php
.
Sekarang kita buka file StorePostRequest.php
.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StorePostRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}
Di dalamnya terdapat dua method, yaitu authorize()
dan rules()
.
Sekarang kita ubah isi kedua method tersebut.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StorePostRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'title' => 'required|string|max:155',
'content' => 'required',
'status' => 'required'
];
}
}
Method authorize()
kita jadikan true
, sedangkan rules()
kita ambil dari rule validasi dari method store()
di PostController
.
Selanjutnya kita modifikasi juga isi dari app/Http/Requests/UpdatePostRequest.php
.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdatePostRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'title' => 'required|string|max:155',
'content' => 'required',
'status' => 'required'
];
}
}
Ya, isinya tidak jauh berbeda dari class StorePostRequest
. Kita ubah isi dari authorize()
menjadi true dan juga rules()
kita sesuaikan dengan aturan validasi dari method update()
di PostController
.
Langkah selanjutnya adalah refactor PostController
dan sebelum kita mulai, kita run kembali phpunit.
$ vendor/bin/phpunit
PHPUnit 9.5.20 #StandWithUkraine
...... 6 / 6 (100%)
Time: 00:00.258, Memory: 32.00 MB
OK (6 tests, 26 assertions)
Pertama kita coba refactor dulu method store()
. Kita buka kembali Http/Controllers/PostController.php
di text editor. Awalnya method store()
seperti di bawah ini.
<?php
// ... baris kode lainnya
class PostController extends Controller
{
// ... baris kode lainnya
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|string|max:155',
'content' => 'required',
'status' => 'required'
]);
$post = Post::create([
'title' => $request->title,
'content' => $request->content,
'status' => $request->status,
'slug' => Str::slug($request->title)
]);
if ($post) {
return redirect()
->route('post.index')
->with([
'success' => 'New post has been created successfully'
]);
} else {
return redirect()
->back()
->withInput()
->with([
'error' => 'Some problem occurred, please try again'
]);
}
}
// ... baris kode lainnya
}
Kita refactor menjadi seperti baris kode berikut ini.
<?php
namespace App\Http\Controllers;
// ... baris kode lainnya
use App\Http\Requests\StorePostRequest; // tambahkan ini
class PostController extends Controller
{
// ... baris kode lainnya
public function store(StorePostRequest $request) // ubah parameter
{
$post = Post::create($request->validated() + ['slug' => Str::slug($request->title)]);
if ($post) {
return redirect()
->route('post.index')
->with([
'success' => 'New post has been created successfully'
]);
} else {
return redirect()
->back()
->withInput()
->with([
'error' => 'Some problem occurred, please try again'
]);
}
}
// ... baris kode lainnya
}
Bisa kita perhatikan baris kode di atas. Awalnya typehint untuk $request
merujuk ke Illuminate\Http\Request
, sekarang kita gunakan form request validation class yang sebelumnya sudah kita buat, yaitu App\Http\Requests\StorePostRequest
. Karena validasi sudah ditangani class App\Http\Requests\StorePostRequest
, jadi kita bisa menghapus code validasi di method store()
dan kita juga bisa menggunakan $request->validated()
untuk insert data yang berisi array dari input yang sudah tervalidasi.
Setelah kita refactor method store()
, sekarang kita test kembali menggunakan phpunit
. Buka kembali terminal, lalu run phpunit.
$ vendor/bin/phpunit
PHPUnit 9.5.20 #StandWithUkraine
...... 6 / 6 (100%)
Time: 00:00.181, Memory: 32.00 MB
OK (6 tests, 26 assertions)
Ya, tidak ada error.
Baik kita lanjutkan.
Sekarang kita coba refactor method update()
. Sebelum refactor, method update()
berisi baris kode berikut ini.
<?php
// ... baris kode lainnya
class PostController extends Controller
{
// ... baris kode lainnya
public function update(Request $request, $id)
{
$this->validate($request, [
'title' => 'required|string|max:155',
'content' => 'required',
'status' => 'required'
]);
$post = Post::findOrFail($id);
$post->update([
'title' => $request->title,
'content' => $request->content,
'status' => $request->status,
'slug' => Str::slug($request->title)
]);
if ($post) {
return redirect()
->route('post.index')
->with([
'success' => 'Post has been updated successfully'
]);
} else {
return redirect()
->back()
->withInput()
->with([
'error' => 'Some problem has occured, please try again'
]);
}
}
// ... baris kode lainnya
}
Sekarang kita implementasikan UpdatePostRequest
dan refactor method update()
.
<?php
namespace App\Http\Controllers;
// ... baris kode lainnya
use App\Http\Requests\UpdatePostRequest; // tambahkan ini
class PostController extends Controller
{
// ... baris kode lainnya
public function update(UpdatePostRequest $request, $id)
{
$post = Post::findOrFail($id);
$post->update($request->validated() + ['slug' => Str::slug($request->title)]);
if ($post) {
return redirect()
->route('post.index')
->with([
'success' => 'Post has been updated successfully'
]);
} else {
return redirect()
->back()
->withInput()
->with([
'error' => 'Some problem has occured, please try again'
]);
}
}
// ... baris kode lainnya
}
Sama seperti method store()
, pada method update()
kita ubah typehint $request
dari Illuminate\Http\Request
menjadi App\Http\Requests\UpdatePostRequest
class. Selain itu pada proses update data, kita gunakan data yang sudah divalidasi untuk diupdate ke table menggunakan $request->validated()
.
Sekarang kita coba test kembali, apakah berhasil atau ada error? Buka kembali terminal lalu kita run phpunit
.
vendor/bin/phpunit
Outputnya:
vendor/bin/phpunit
PHPUnit 9.5.20 #StandWithUkraine
...... 6 / 6 (100%)
Time: 00:00.262, Memory: 32.00 MB
OK (6 tests, 26 assertions)
Ya, Refactor kita berhasil dan tidak ada error.
Pada percobaan kali ini kita sudah belajar bagaimana cara refactor controller dengan memisahkan logika validasi ke class terpisah, yaitu class Form Request Validation class. Selain itu, supaya tidak ada perubahan behaviour setelah refactor, kita juga gunakan phpunit
untuk proses testing. Setelah mencoba untuk memisahkan logika validasi, kita bisa lihat hasilnya logika di controller, terutama di method store()
dan update()
menjadi lebih ringkas, dengan fungsionalitas masih sama. Perbedaannya terdapat class PHP yang lebih banyak sebelumnya. Apakah ini lebih bermanfaat atau malah lebih ribet? Bagaimana menurutmu?
© 2024 qadrLabs . All rights reserved. 000515268