
Setelah sebelumnya kita berhasil menambahkan fitur untuk membuat artikel baru, kini saatnya kita melanjutkan dengan fitur mengubah artikel. Fitur ini memungkinkan user untuk memperbarui data artikel yang sudah ada, seperti judul, isi, atau lainnya.
Route untuk fitur ini sudah kita buat sebelumnya. Tugas kita selanjutnya adalah menyesuaikan controller, khususnya method edit()
dan update()
.
Sudah siap? Yuk, kita mulai.
Untuk menampilkan form edit artikel, kita perlu menyesuaikan method edit()
.
Buka file ArticleController.php dan sesuaikan kode menjadi sebagai berikut:
๐ app/Http/Controllers/ArticleController.php
1
2
3
4
5
6
7
8
9
10
11
12
13
| /** ... **/
/**
* Show the form for editing the specified resource.
*/
public function edit(Article $article): View
{
$statusList = Article::STATUS_LIST;
return view('pages.articles.edit', compact('article', 'statusList'));
}
/** ... **/
|
Form edit ini hampir sama seperti form tambah artikel. Untuk saat ini, kita akan tulis ulang terlebih dahulu. Tenang saja, di artikel selanjutnya kita akan refaktor agar lebih DRY (Don’t Repeat Yourself).
Buat file resources/views/pages/articles/edit.blade.php dan tambahkan kode berikut:
๐ resources/views/pages/articles/edit.blade.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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
| @extends('layouts.app')
@section('title', 'Edit Artikel')
@section('content')
<div id="content" class="container">
{{ html()->form('PUT', route('articles.update', $article->id))->acceptsFiles()->autocomplete(false)->open() }}
@php html()->model($article); @endphp
<div class="row">
<div class="col-lg-8">
<div class="mb-3">
@php
$name = 'title';
$placeholder = 'Judul';
@endphp
{{ html()->text($name)->class('form-control fs-3' . ($errors->has($name) ? ' is-invalid' : ''))->placeholder($placeholder) }}
@error($name)
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
@php
$name = 'slug';
$placeholder = 'Slug';
@endphp
<div class="input-group">
<div class="input-group-prepend">
<div class="input-group-text">{{ route('articles.index') }}/</div>
</div>
{{ html()->text($name)->class('form-control' . ($errors->has($name) ? ' is-invalid' : ''))->placeholder($placeholder) }}
@error($name)
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
<div class="mb-3">
@php $name = 'content'; @endphp
{{ html()->textarea($name)->class('form-control' . ($errors->has($name) ? ' is-invalid' : '')) }}
@error($name)
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
<div class="col-lg-4">
<div class="card mb-3">
@php
$name = 'feature_image_url';
$placeholder = 'Gambar Pilihan';
@endphp
<div class="card-header">{{ $placeholder }}</div>
<div class="card-body">
{{ html()->file($name)->class('form-control' . ($errors->has($name) ? ' is-invalid' : '')) }}
@error($name)
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
<div class="card mb-3">
<div class="card-body">
<div class="mb-2">
@php
$name = 'status';
$placeholder = 'Status';
@endphp
{{ html()->select($name, $statusList, $article->getRawOriginal($name))->class('form-select' . ($errors->has($name) ? ' is-invalid' : ''))->placeholder($placeholder) }}
@error($name)
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-2">
@php $name = 'published_at'; @endphp
{{ html()->datetime($name, \Carbon\Carbon::parse($article->{$name})->format('Y-m-d\TH:i'))->class('form-control' . ($errors->has($name) ? ' is-invalid' : '')) }}
@error($name)
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
</div>
{{ html()->submit('Update')->class('btn btn-primary') }}
</div>
</div>
{{ html()->form()->close() }}
</div>
@endsection
@push('scripts')
<script type="module">
$('[name=title]').on('input', function() {
$('[name=slug]').val($(this).val().replace(/\s+/g, '-').replace(/[^a-z0-9-]/gi, '').toLowerCase());
});
new FroalaEditor('textarea[name=content]', {
htmlRemoveTags: ['div'],
});
</script>
@endpush
|
Berikut adalah beberapa perbedaan dengan form pembuatan artikel:
- Judul halaman diubah menjadi ‘Edit Artikel’.
- Form akan mengirim data ke endpoint PUT /articles/{article}, yang ditangani oleh method
update()
pada controller. - Kita memanfaatkan model binding dari Laravel HTML untuk mengisi nilai pada setiap field.
- Field
status
dimodifikasi oleh accessor. Untuk itu, kita menggunakan fungsi getRawOriginal()
untuk memperoleh nilai sebelum diubah. - Field
published_at
menggunakan format Y-m-d\TH:i
dengan bantuan helper Carbon
.
- Button Simpan diganti menjadi Update.
Tampilan form mengubah artikel sudah tampil sebagai berikut:

Menyesuaikan Controller untuk Mengubah Artikel #
Berhubung kita menggunakan form request yang sama dengan proses menambahkan (store
) artikel, kita bisa langsung menyesuaikan method update()
pada controller.
Buka kembali file ArticleController.php dan sesuaikan menjadi sebagai berikut:
๐ app/Http/Controllers/ArticleController.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
35
36
37
38
39
40
41
42
43
| /** ... **/
use Illuminate\Support\Facades\Storage;
/** ... **/
/**
* Update the specified resource in storage.
*/
public function update(ArticleRequest $request, Article $article): RedirectResponse
{
try {
$input = $request->validated();
$storagePath = Article::IMAGE_STORAGE_PATH;
if ($request->hasFile('feature_image_url')) {
if ($article->feature_image_url) {
$oldFilePath = "$storagePath/$article->feature_image_url";
if (Storage::disk('public')->exists($oldFilePath)) {
Storage::disk('public')->delete($oldFilePath);
}
}
$file = $request->file('feature_image_url');
$fileName = time().'_'.$file->getClientOriginalName();
$file->storeAs($storagePath, $fileName, 'public');
$input['feature_image_url'] = $fileName;
}
$article->update($input);
flash()->success('Data berhasil di-update!');
} catch (\Exception $e) {
report($e);
flash()->error('Data tidak berhasil di-update!');
} finally {
return redirect(route('articles.index'));
}
}
/** ... **/
|
Perbedaan utama dengan method store()
adalah sebagai berikut:
- Jika user mengunggah gambar baru, gambar lama akan dihapus terlebih dahulu.
- Menggunakan Eloquent method
update()
untuk menyimpan perubahan. - Pesan notifikasi disesuaikan dengan konteks update.
Berikut adalah tampilan form apabila terdapat kesalahan validasi:

Menambahkan Link pada Daftar Artikel #
Agar user bisa mengakses halaman edit, kita akan menambahkan tombol Edit pada kolom action di DataTables.
Buka file ArticleDataTable.php dan sesuaikan method dataTable()
menjadi sebagai berikut:
๐ app/DataTables/ArticleDataTable.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| /** ... **/
public function dataTable(QueryBuilder $query): EloquentDataTable
{
return (new EloquentDataTable($query))
->addColumn('action', function (Article $article) {
$action = [
"<a href='".route('articles.show', $article)."' class='btn btn-sm btn-primary'><i class='bi bi-eye-fill'></i></a>",
"<a href='".route('articles.edit', $article)."' class='btn btn-sm btn-success'><i class='bi bi-pencil-fill'></i></a>",
];
return implode(' ', $action);
})
->rawColumns(['status', 'action'])
->setRowId('id');
}
/** ... **/
|
Hasil dari pengubahan di atas adalah sebagai berikut:

Fitur mengubah artikel yang kita tambahkan kali ini melengkapi proses pengelolaan konten di aplikasi blog kita. Dengan memanfaatkan form yang sudah ada, kita bisa menjaga konsistensi tampilan dan pengalaman user.
Nah, kalau kita perhatikan lebih dalam, ternyata masih ada beberapa bagian kode yang bisa kita sederhanakan. Di artikel berikutnya, kita akan mulai refaktor agar struktur proyek kita jadi lebih bersih, efisien, dan siap untuk dikembangkan lebih lanjut.
Sampai jumpa dan terus semangat ngoding, ya! ๐ป๐