Langsung ke konten

06. Menghapus Chirp

Terkadang, sebanyak apa pun pengeditan dilakukan tidak dapat memperbaiki sebuah pesan, jadi mari kita beri pengguna kemampuan untuk menghapus Chirp mereka.

Semoga Anda sudah mulai terbiasa sekarang. Kami rasa Anda akan terkesan betapa cepatnya kita dapat menambahkan fitur ini.

Perutean (Routing)

Kita akan mulai lagi dengan memperbarui rute kita untuk mengaktifkan rute chirps.destroy:

routes/web.php
<?php
 ...
use App\Http\Controllers\ChirpController;
use App\Http\Controllers\ProfileController;
use Illuminate\Support\Facades\Route;
 
Route::get('/', function () {
return view('welcome');
});
 
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth'])->name('dashboard');
 
Route::middleware('auth')->group(function () {
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});
 
Route::resource('chirps', ChirpController::class)
- ->only(['index', 'store', 'edit', 'update'])
+ ->only(['index', 'store', 'edit', 'update', 'destroy'])
->middleware(['auth', 'verified']);
 ...
require __DIR__.'/auth.php';
 

Tabel rute untuk controller ini sekarang terlihat seperti berikut:

Verb URI Action Route Name
GET /chirps index chirps.index
POST /chirps store chirps.store
GET /chirps/{chirp}/edit edit chirps.edit
PUT/PATCH /chirps/{chirp} update chirps.update
DELETE /chirps/{chirp} destroy chirps.destroy

Memperbarui controller

Sekarang kita dapat memperbarui metode destroy pada kelas ChirpController untuk melakukan penghapusan dan kembali ke indeks Chirp:

app/Http/Controllers/ChirpController.php
<?php
 ...
namespace App\Http\Controllers;
 
use App\Models\Chirp;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Gate;
use Illuminate\View\View;
 
class ChirpController extends Controller
{
 ...
/**
* Menampilkan daftar resource.
*/
public function index(): View
{
return view('chirps.index', [
'chirps' => Chirp::with('user')->latest()->get(),
]);
}
 
/**
* Menampilkan formulir untuk membuat resource baru.
*/
public function create()
{
//
}
 
/**
* Menyimpan resource yang baru dibuat ke dalam penyimpanan.
*/
public function store(Request $request): RedirectResponse
{
$validated = $request->validate([
'message' => 'required|string|max:255',
]);
 
$request->user()->chirps()->create($validated);
 
return redirect(route('chirps.index'));
}
 
/**
* Menampilkan resource yang dipilih/spesifik.
*/
public function show(Chirp $chirp)
{
//
}
 
/**
* Menampilkan formulir untuk mengedit resource yang dipilih/spesifik.
*/
public function edit(Chirp $chirp): View
{
Gate::authorize('update', $chirp);
 
return view('chirps.edit', [
'chirp' => $chirp,
]);
}
 
/**
* Memperbarui resource yang dipilih/spesifik di dalam penyimpanan.
*/
public function update(Request $request, Chirp $chirp): RedirectResponse
{
Gate::authorize('update', $chirp);
 
$validated = $request->validate([
'message' => 'required|string|max:255',
]);
 
$chirp->update($validated);
 
return redirect(route('chirps.index'));
}
 
/**
* Menghapus resource yang dipilih/spesifik dari penyimpanan.
*/
- public function destroy(Chirp $chirp)
+ public function destroy(Chirp $chirp): RedirectResponse
{
- //
+ Gate::authorize('delete', $chirp);
+ 
+ $chirp->delete();
+ 
+ return redirect(route('chirps.index'));
}
}

Otorisasi

Sama seperti saat pengeditan, kita hanya ingin penulis Chirp yang dapat menghapus Chirp mereka, jadi mari perbarui metode delete di kelas ChirpPolicy kita:

app/Policies/ChirpPolicy.php
<?php
 ...
namespace App\Policies;
 
use App\Models\Chirp;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
 
class ChirpPolicy
{
 ...
use HandlesAuthorization;
 
/**
* Menentukan apakah pengguna dapat melihat model apa saja.
*/
public function viewAny(User $user): bool
{
//
}
 
/**
* Menentukan apakah pengguna dapat melihat model yang ditentukan.
*/
public function view(User $user, Chirp $chirp): bool
{
//
}
 
/**
* Menentukan apakah pengguna dapat membuat model.
*/
public function create(User $user): bool
{
//
}
 
/**
* Menentukan apakah pengguna dapat memperbarui model.
*/
public function update(User $user, Chirp $chirp): bool
{
return $chirp->user()->is($user);
}
 
/**
* Menentukan apakah pengguna dapat menghapus model.
*/
public function delete(User $user, Chirp $chirp): bool
{
- //
+ return $this->update($user, $chirp);
}
 ...
/**
* Menentukan apakah pengguna dapat merestorasi model.
*/
public function restore(User $user, Chirp $chirp): bool
{
//
}
 
/**
* Menentukan apakah pengguna dapat menghapus model secara permanen.
*/
public function forceDelete(User $user, Chirp $chirp): bool
{
//
}
 
}

Alih-alih mengulang logika dari metode update, kita dapat mendefinisikan logika yang sama dengan memanggil metode update dari metode delete kita. Siapa pun yang berwenang untuk memperbarui Chirp sekarang juga akan berwenang untuk menghapusnya.

Memperbarui view

Terakhir, kita dapat menambahkan tombol hapus ke menu dropdown yang kita buat sebelumnya di view chirps.index:

resources/views/chirps/index.blade.php
<x-app-layout>
<div class="max-w-2xl mx-auto p-4 sm:p-6 lg:p-8">
<form method="POST" action="{{ route('chirps.store') }}">
@csrf
<textarea
name="message"
placeholder="{{ __('What\'s on your mind?') }}"
class="block w-full border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm"
>{{ old('message') }}</textarea>
<x-input-error :messages="$errors->get('message')" class="mt-2" />
<x-primary-button class="mt-4">{{ __('Chirp') }}</x-primary-button>
</form>
 
<div class="mt-6 bg-white shadow-sm rounded-lg divide-y">
@foreach ($chirps as $chirp)
<div class="p-6 flex space-x-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-gray-600 -scale-x-100" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
<div class="flex-1">
<div class="flex justify-between items-center">
<div>
<span class="text-gray-800">{{ $chirp->user->name }}</span>
<small class="ml-2 text-sm text-gray-600">{{ $chirp->created_at->format('j M Y, g:i a') }}</small>
@unless ($chirp->created_at->eq($chirp->updated_at))
<small class="text-sm text-gray-600"> &middot; {{ __('edited') }}</small>
@endunless
</div>
@if ($chirp->user->is(auth()->user()))
<x-dropdown>
<x-slot name="trigger">
<button>
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-gray-400" viewBox="0 0 20 20" fill="currentColor">
<path d="M6 10a2 2 0 11-4 0 2 2 0 014 0zM12 10a2 2 0 11-4 0 2 2 0 014 0zM16 12a2 2 0 100-4 2 2 0 000 4z" />
</svg>
</button>
</x-slot>
<x-slot name="content">
<x-dropdown-link :href="route('chirps.edit', $chirp)">
{{ __('Edit') }}
</x-dropdown-link>
+ <form method="POST" action="{{ route('chirps.destroy', $chirp) }}">
+ @csrf
+ @method('delete')
+ <x-dropdown-link :href="route('chirps.destroy', $chirp)" onclick="event.preventDefault(); this.closest('form').submit();">
+ {{ __('Delete') }}
+ </x-dropdown-link>
+ </form>
</x-slot>
</x-dropdown>
@endif
</div>
<p class="mt-4 text-lg text-gray-900">{{ $chirp->message }}</p>
</div>
</div>
@endforeach
</div>
</div>
</x-app-layout>

Coba sekarang

Jika Anda pernah membuat Chirp yang tidak memuaskan, cobalah menghapusnya!

Menghapus chirp

Lanjutkan ke notifikasi & event...