18 Cancellare un record
abbiamo visto che con il resource controller vengono creati i vari metodi per i vari scopi, fino ad ora abbiamo usato index() per mostrare le rotte.
Abbiamo accennato al metodo destroy() per l’eliminazione di un record, per protezione laravel imposta l’esecuzione di questo metodo tramite il metodo DELETE di una chiamata HTTP, quindi di default non è possibile utilizzare il metodo destroy() del nostro controller via GET.
Se aggiungessimo il comando per l’eliminazione di un record in destroy() laravel si aspetterebbe un token passato da un form per prevenire eventuali request forgery (CSRF Cross Site Request Forgery).
Mappiamo in web.php la rotta /albums utilizzando Route::resource invece che get()
Route::resource('/albums', AlbumsController::class );
Se lanciamo il comando route:list vedremo tutte le nostre rotte, ma prima nelle rotte web
php artisan route:list
Se analizziamo le rotte di albums e abbiamo creato il nostro controller con l’opzione resource, avremo che chiamando albums/{album} ovvero l’id dell’album col metodo HTTP DELETE verrà lanciato il metodo destroy() del controller. Questo significa che non possiamo chiamare il metodo destroy via GET,
GET|HEAD | albums/{album} | albums.show | App\Http\Controllers\AlbumsController@show | web | DELETE | albums/{album} | albums.destroy | App\Http\Controllers\AlbumsController@destroy | web |
infatti se chiamiamo
localhost:8000/albums/2
Verrà eseguito via GET il metodo show() come indicato nella lista delle rotte e non destroy(), come controprova restituiamo un messaggio nel metodo show()
public function show(Album $album) { return 'Visualizza'; }
L’unica maniera che abbiamo per lanciare la chiamata usando il metodo HTTP DELETE è tramite un form o utilizzare un software come postman che permette di fare le chiamate HTTP.
Usando postman si crea una new collection e poi sulla collezione si clicca su add Request, diamo un nome e cliccando poi sulla request inseriamo l’url http://localhost:8000/albums/1 e scegliamo il metodo GET. Noteremo che sarà restituito visualizza, mentre se scegliamo il metodo DELETE ci da errore, perchè comunque laravel per ulteriore sicurezza verifica che ci sia un token abbinato alla richiesta.
Per eseguire il test basta andare su app/Http/kernel e commentare la riga relativa alla verifica token.
// \App\Http\Middleware\VerifyCsrfToken::class,
aggiungiamo nel metodo destroy() del controller la restituzione di un una stringa
public function destroy(Album $album) { return 'Distrutto'; }
a questo punto possiamo eseguire il test della chiamato col metodo HTTP DELETE su postman e verrà visualizzata la nostra stringa chiamata dal metodo destroy() del controller.
A questo punto possiamo passare all’eliminazione del record vera e propria, come vediamo nel metodo destroy(Album $album) laravel inietta un’istanza di album come parametro, quindi basterebbe utilizzare il metodo delete() di $album
public function destroy(Album $album) { return $album->delete(); }
Visto che stavamo utilizzando la facade DB vediamo come farlo con essa. Ci prepariamo la query di cancellazione dove l’ID sarà uguale
$sql = 'DELETE FROM albums WHERE id=:id';
a questo punto a noi non interessa tutto l’oggetto Album restituito dal model, quindi sostituiamolo come parametro lasciando solo $album che conterrà solo l’id che convertiamo in intero
public function destroy(int $album)
restituiamo il metodo delete() della facade DB che riceverà la query memorizzata in $sql come parametro e come secondo il binding dell’ id in un array
public function destroy(int $album) { $sql = 'DELETE FROM albums WHERE id=:id'; return DB::delete($sql, ['id' => $album]); }
Qualora non volessimo utilizzare postman, possiamo creare un nuovo metodo nel controller, per esempio delete()
public function delete(int $album) { $sql = 'DELETE FROM albums WHERE id=:id'; return DB::delete($sql, ['id' => $album]); }
e poi mappare il metodo in una nuova rotta GET
Route::get('albums/{album}/del', [AlbumsController::class, 'delete']);
a questo punto abbiamo forzato la cancellazione via GET possiamo aprire l’url col browser
http://localhost:8000/albums/1/del