CRUD Manajemen Artikel - Menambahkan Artikel
6 Maret 2025
Β·
11 menit Β·

Pada artikel sebelumnya, kita sudah menampilkan artikel berdasarkan data dummy yang diperoleh melalui seeder. Sekarang, kita akan melangkah lebih jauh dengan menambahkan fitur untuk menambah artikel baru.
Untuk memberikan pengalaman user yang lebih baik, kita tambahkan notifikasi setiap kali artikel berhasil disimpan. Kita juga akan menampilkan pesan error apabila terdapat kesalahan input. Dengan begitu, user bisa langsung tahu apakah proses berhasil dilakukan atau perlu diperbaiki.
Sebagai pengingat, kita sudah membuat route berikut:
- GET /articles/create β mengarah ke method
create()
untuk menampilkan form pembuatan artikel baru. - POST /articles β mengarah ke method
store()
untuk menyimpan artikel ke database.
Yuk, kita mulai dari langkah pertama.
Menyesuaikan Controller untuk Menampilkan Form Pembuatan Artikel Baru
Seperti yang kita bahas sebelumnya, untuk menampilkan form pembuatan artikel baru, kita perlu menyesuaikan method create()
.
Buka file ArticleController.php dan sesuaikan kode menjadi sebagai berikut:
π app/Http/Controllers/ArticleController.php
|
|
- Kita memanfaatkan konstanta
STATUS_LIST
(sudah kita buat sebelumnya pada saat membuat model untuk tabel artikel) untuk menampilkan daftar status artikel. Konstanta ini akan digunakan untuk mengisi opsi pada dropdown status publikasi artikel.
Membuat View untuk Menampilkan Form Pembuatan Artikel Baru
Setelah menyiapkan route dan controller, sekarang saatnya membuat form input untuk artikel.
Form ini dibagi menjadi dua kolom:
- bagian kiri berupa input utama seperti judul, slug, dan konten;
- bagian kanan berupa input metadata tambahan seperti gambar pilihan, status publikasi, dan tanggal terbit.
Untuk mendukung pembuatan form, kita akan memanfaatkan beberapa package/library berikut:
- Laravel HTML β membantu kita membuat elemen-elemen HTML menggunakan sintaks PHP yang lebih ringkas, rapi, dan konsisten. Dengan Laravel HTML, kita bisa membuat elemen form seperti
input
,select
, dantextarea
langsung dari PHP, tanpa menulis tag HTML secara manual. Package ini mendukung berbagai fitur seperti binding data dari model, integrasi CSRF token otomatis, pengelolaan atribut, dan sebagainya. - Froala Editor β sebuah rich text editor berbasis JavaScript yang akan kita gunakan untuk memberikan pengalaman WYSIWYG (What You See Is What You Get) saat menulis konten artikel.
Instalasi dan Konfigurasi Laravel HTML
Install Laravel HTML menggunakan Composer dengan perintah berikut:
sail composer require spatie/laravel-html
Sesuaikan file pada bootstrap/providers.php menjadi sebagai berikut:
π bootstrap/providers.php
1 2 3 4 5 6
<?php return [ App\Providers\AppServiceProvider::class, Spatie\Html\HtmlServiceProvider::class, ];
Instalasi dan Konfigurasi Froala Editor
Untuk mempermudah proses instalasi, kita akan memanfaatkan CDN. Versi yang kita gunakan adalah v4.5.1.
Penggunaan versi spesifik penting agar dokumentasi dan perilaku editor sesuai dengan yang kita bahas pada artikel ini.
Buka file styles.blade.php dan tambahkan kode berikut:
π resources/views/layouts/styles.blade.php
1 2 3 4 5 6 7 8 9
<style> /** ... **/ </style> @vite(['resources/css/app.css']) <link href='https://cdn.jsdelivr.net/npm/[email protected]/css/froala_editor.pkgd.min.css' rel='stylesheet' type='text/css' /> @stack('styles')
Buka file scripts.blade.php dan tambahkan kode berikut:
π resources/views/layouts/scripts.blade.php
1 2 3 4 5
@vite(['resources/js/app.js']) <script type='text/javascript' src='https://cdn.jsdelivr.net/npm/[email protected]/js/froala_editor.pkgd.min.js'></script> @stack('scripts')
Membuat View
Sekarang semua dependensi yang dibutuhkan sudah siap, saatnya kita membangun form input artikel.
Buat file resources/views/pages/articles/create.blade.php dan tambahkan kode berikut:
π resources/views/pages/articles/create.blade.php
|
|
- Form akan mengirim data ke endpoint POST /articles, yang ditangani oleh method
store()
pada controller. - Method
acceptsFiles()
menambahkan atributenctype="multipart/form-data"
ke tag<form>
agar form bisa mengirimkan file (gambar). - Fungsi
html()->form()
,html()->text()
, dan lainnya yang diawali denganhtml()
adalah bagian dari package Laravel HTML, yang menggantikan penulisan elemen form menggunakan tag HTML manual seperti<input type="text" ...>
.- Laravel HTML juga otomatis menangani binding nilai lama (
old()
) saat form gagal validasi.
- Laravel HTML juga otomatis menangani binding nilai lama (
- Fungsi
$errors->has()
dan directive@error()
β memeriksa apakah terdapat error pada field yang ditentukan.
- Pada baris 107, atribut
type=module
ditujukan agar script menggunakan skema ES Module, yang kompatibel dengan Vite. - Pada baris 108 - 110, nilai pada field
slug
otomatis diisi apabila terdapat pengubahan pada fieldtitle
dengan ketentuan sebagai berikut:- Spasi diubah menjadi tanda hubung.
- Karakter selain
a-z
,0-9
, dan-
(tanda hubung) dihapus. - Semuanya diubah menjadi huruf kecil.
- Para baris 112 s.d. 114, Froala Editor diinisialisasi untuk field
content
dengan menghilangkan tag<div>
.
Kita sudah berhasil membuat form pembuatan artikel baru. Keren!

Menyesuaikan Controller untuk Menyimpan Artikel
Sebelum benar-benar menyimpan artikel ke database, kita perlu memastikan bahwa data yang dikirimkan melalui form sudah valid. Untuk itu, kita akan melakukan proses validasi terlebih dahulu.
Agar kode tetap rapi dan terstruktur, kita akan menggunakan Form Request β sebuah fitur dari Laravel yang memungkinkan kita memisahkan logika validasi ke dalam kelas tersendiri.
Membuat Form Request
Jalankan perintah berikut untuk membuat file ArticleRequest.php:
sail artisan make:request ArticleRequest
- Perintah ini akan membuat file baru bernama ArticleRequest.php pada direktori app/Http/Requests.
- Pada kasus ini, kita akan menggunakan form request yang sama untuk proses menambahkan (
store
) dan mengubah (update
) artikel.- Apabila validasi untuk masing-masing proses sangat berbeda atau lebih kompleks, kita bisa memisahkan form request untuk setiap proses. Misalnya:
StoreArticleRequest
untuk proses menambahkan artikel danUpdateArticleRequest
untuk proses mengubah artikel.
- Apabila validasi untuk masing-masing proses sangat berbeda atau lebih kompleks, kita bisa memisahkan form request untuk setiap proses. Misalnya:
Buka file ArticleRequest.php dan sesuaikan kode menjadi sebagai berikut:
π app/Http/Requests/ArticleRequest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
<?php namespace App\Http\Requests; use App\Models\Article; use Illuminate\Foundation\Http\FormRequest; class ArticleRequest extends FormRequest { /** * Determine if the user is authorized to make this request. */ public function authorize(): bool { return true; } /** * Get the validation rules that apply to the request. * * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string> */ public function rules(): array { return [ 'title' => 'required|string|max:255', 'slug' => 'required|string|max:255|regex:/^[a-z0-9-]+$/u|unique:articles,slug'.($this->article?->id ? ", {$this->article->id}" : ''), 'feature_image_url' => 'nullable|file|mimes:jpeg,jpg,png,gif', 'content' => 'required|string', 'status' => 'required|in:'.implode(',', array_keys(Article::STATUS_LIST)), 'published_at' => 'required|date', ]; } }
- Method
authorize()
β mengatur apakah user memiliki hak untuk membuat request ini. Untuk kasus ini, kita cukup mengembalikan nilaitrue
. - Method
rules()
β mendefinisikan aturan validasi untuk setiap input. Penjelasan masing-masing field:Field Keterangan title
Wajib diisi, berupa string, maksimal 255 karakter. slug
- Wajib diisi, berupa string, maksimal 255 karakter.
- Hanya boleh terdiri dari huruf kecil, angka, dan tanda hubung (-).
- Harus unik di tabel `articles` pada kolom `slug`. Namun, pada proses `update`, slug artikel yang sedang diedit akan dikecualikan.
feature_image_url
Opsional. Jika diisi, harus berupa file dengan tipe gambar: jpeg, jpg, png, atau gif. content
Wajib diisi, berupa string. status
Wajib diisi. Nilai harus salah satu dari daftar yang tersedia di Article::STATUS_LIST
. Kita menggunakan fungsiimplode()
untuk menyusun daftar nilai valid yang dipisahkan koma.published_at
Wajib diisi dan harus berupa tanggal yang valid.
- Untuk mempelajari validation rule lainnya, silakan merujuk pada dokumentasi Laravel: Available Validation Rules.
- Untuk mempelajari form request validation, silakan merujuk pada dokumentasi Laravel: Form Request Validation.
- Method
Instalasi dan Konfigurasi PHPFlasher
Untuk memberikan umpan balik yang jelas kepada user setelah menyimpan artikel, kita akan menggunakan PHPFlasher β sebuah package yang memungkinkan kita menampilkan notifikasi yang elegan hanya dengan satu baris kode.
Untuk melakukan instalasi, cukup jalankan perintah berikut di Teminal:
sail composer require php-flasher/flasher-laravel
Setelah proses instalasi selesai, jalankan perintah berikut untuk setup asset yang dibutuhkan:
sail artisan flasher:install
Saat ini, kita menggunakan layout dengan Navbar dari Bootstrap. Agar tampilan Flasher tidak tertimpa dengan Navbar, kita bisa menyesuaikan nilai z-index
pada class fl-wrapper
sebagai berikut:
π resources/views/partials/styles.blade.php
|
|
PHPFlasher sudah siap digunakan!
Mengenal Laravel File Storage
Ketika user mengunggah gambar untuk artikel, kita perlu menyimpannya ke sistem file dengan aman dan terstruktur. Laravel menyediakan fitur File Storage yang memudahkan proses penyimpanan file ke berbagai media seperti local disk, Amazon S3, dan lainnya.
Secara default, Laravel sudah menyediakan beberapa konfigurasi disk penyimpanan yang bisa kita temukan di file config/filesystems.php, yaitu local
, public
, dan s3
. Untuk menyimpan gambar artikel, kita akan menggunakan disk public
karena file gambar perlu diakses secara publik (misalnya saat menampilkan thumbnail artikel).
Disk ini menyimpan file di direktori storage/app/public, bukan langsung di folder public. Agar file bisa diakses melalui browser, kita harus membuat symbolic link dari direktori storage/app/public ke direktori public/storage.
Jalankan perintah berikut di Terminal:
sail artisan storage:link
Setelah menjalankan perintah di atas, semua file yang disimpan di direktori storage/app/public akan dapat diakses melalui URL http://localhost/storage/.
Menyesuaikan Controller
Selanjutnya, kita akan mengubah tipe parameter $request
di method store()
menjadi ArticleRequest
. Dengan begitu, Laravel akan otomatis menjalankan validasi berdasarkan aturan yang telah kita definisikan sebelumnya.
Berikut adalah implementasi method store()
di ArticleController
yang sudah disesuaikan:
π app/Http/Controllers/ArticleController.php
|
|
- Baris 12
Data dari form sudah otomatis divalidasi olehArticleRequest
. Methodvalidated()
akan mengembalikan data yang valid dan aman untuk disimpan ke database. - Baris 17-23
Jika user mengunggah gambar pilihan, kita simpan di direktori penyimpanan lokal. Nama dari file ditambahkan timestamp di depan agar unik, lalu nama file disimpan ke dalam database melalui fieldfeature_image_url
. - Baris 25
Data artikel langsung disimpan menggunakan Eloquent. - Baris 27
Jika proses berhasil, tampilkan notifikasi flash message dengan status sukses. - Baris 29-30
Sebaliknya, jika terjadi kegagalan, kita tangkap exception-nya dan tampilkan notifikasi flash message dengan status error.
Fungsireport($e)
akan mengirimkan exception ke sistem log Laravel. - Baris 32
Apapun hasilnyaβberhasil atau gagalβuser akan diarahkan kembali ke halaman daftar artikel.
Berikut adalah tampilan form apabila terdapat kesalahan validasi:

Berikut adalah tampilan form apabila seluruh form sudah diisi dengan benar:

Menambahkan Link pada Halaman Menampilkan Daftar Artikel
Agar user bisa membuka form pembuatan artikel baru tanpa harus mengetik link http://localhost/articles/create, kita perlu menambahkan link pada halaman menampilan daftar artikel.
Buka file resources/views/pages/articles/index.blade.php, lalu sesuaikan kode berikut:
π resources/views/pages/articles/index.blade.php
|
|
Hasil dari pengubahan di atas adalah sebagai berikut:

Dengan ini, kita telah berhasil membuat fitur untuk menambahkan artikel baru, lengkap dengan form input, validasi yang rapi menggunakan Form Request, serta notifikasi menggunakan PHPFlasher untuk memberikan umpan balik kepada user.
Pada artikel berikutnya, kita akan melanjutkan dengan fitur untuk mengedit artikel yang sudah ada.
Sampai jumpa di pembahasan selanjutnya! π