20 Aggiornare un record

dopo aver visualizzato ed eliminato gli album tramite lo la facade DB e il suo statement delete(), vediamo come aggiornare un album attraverso un pulsante e una nuova view.

Raggruppiamo le views riferita agli album in un’apposita cartella resources/views/albums, spostiamoci albums.template.php e aggiorniamo la rotta nella funzione index() del controller

return view('albums.albums', ['albums' => DB::select($sql, $where)]);

aggiungiamo il pulsante nella view e come href lo indirizziamo ad una pagina edit

<div>
 <a href="/albums/{{$album->id}}/edit" class="btn btn-primary">AGGIORNA</a>
 <a href="/albums/{{$album->id}}" class="btn btn-danger">DELETE</a>
</div>

definiamo ora il metodo edit nel controller che restituirò una apposita view

public function edit(Album $album)
{
 return view('albums.edit');
}

andiamo a creare resources/views/album/edit.blade.php e come prima cosa estendiamo il template di base che ho rinominato in resources/views/templates/default.blade.php

@extends('templates.default')
@section('content')
 <h1>Modifica album</h1>
@stop

Usiamo @stop per indicare la fine della sessione.

Ora dobbiamo creare un form che riceva i dati dell’album

<form>
 <div class="form-group">
  <label for="">Name</label>
  <input type="text" name="name" id="name" class="form-control" placeholder="Album name">
 </div>
 <div class="form-group">
  <label for="">Descrizione</label>
  <input type="text" name="description" id="description" class="form-control" placeholder="Album description">
 </div>
 <button type="submit" class="btn btn-primary">Aggiorna</button>
</form>

ora per popolare i dati aggiungiamo nell'<input> il campo value che riceve il dato

value="{{$album->album_name}}"

aggiungiamo la query nel metodo edit()

$sql = 'select album_name, description, id from albums where id =:id';

lanciamo la DB::select, $id viene preso come argomento nel metodo edit(int $id), ricevuto dalla rotta

$album = DB::select($sql, ['id' => $id]);

restituiamo la view editalbum e visto che l’array $album ha un solo un solo valore restituiamo l’indice 0 e usiamo withAlbum

return view('albums.editalbum')->withAlbum($album[0]);

Inviare i dati per salvarli sul db

Se inviamo il form per modificarlo, i dati vengono inviati via GET come parametri url, cosa che non vogliamo, mentre noi vogliamo inviarli via POST alla risorsa URL ( es: /albums/5 ).

Siccome i form HTML possono inviare i dati solo via GET o POST, mentre a noi servirebbe simulare il metodo HRML PATCH che serve ad aggiornare i dati, vediamo come simularlo.

Prima di tutto nel form reperiamo il csrf_field() per soddisfare il middleware web che bloccherebbe la richiesta via url

{{csrf_field()}}

adesso specifichiamo l’ action del form che sarà albums/id dell’album

<form action="/albums/{{$album->id}}" method="POST">

ora simuliamo il metodo PATCH con un campo <hidden> che avrà come name _method value PATCH

<input type="hidden" name="_method" value="PATCH">

Per verificare che i dati vengano inviati con il verbo PATCH, andiamo ad inserire una rotta che utilizzerà un nuovo metodo store()

Route::patch('/albums/{id}', 'AlbumsController@store');

andiamo a creare il metodo store() facendo un dd della richiesta sfruttando la funzione helper request()->all() per verificare i dati che stiamo mandando

public function store(Request $req)
{
  dd(request()->all());
}

aprendo l’url /albums/10 per esempio vedremo restituito il token il metodo che sarà PATCH e i dati dell’album, quindi anche se abbiamo inviato i dati via POST, laravel ridireziona tramite la rotta di tipo PATCH alla funzione store() del controller. In questo modo possiamo utilizzare un form con il metodo HTML PATCH ! cosa che era possibile con AJAX specificando l’attributo method. Questo sistema di utilizzare un altro metodo in un form HTML che non sia sia GET o POST, di norma unicamente possibili, vale anche per gli altri metodi HTML DI RICHIESTE (DELETE, PUT…).

Nel nostro esempio la rotta passa il nostro /albums/{id} tramite PATCH request al metodo store() del nostro controller, quindi possiamo catturarlo aggiungendo una variabile $id come argomento del metodo store() e catturiamo i dati della request che ci interessano tramite la funzione helper request()->only()

public function update($id Request $request)
{
 $data = $request->only(['name','description']);

facciamo una verifica con un dd)$data). Aggiungiamo l’id che viene passato direttamente dal metodo

$data = $request->only(['name','description']);
$data['id'] = $id;

è il momento di preparare la query UPDATE usando i relativi segnaposti

$sql = 'UPDATE albums set album_name=:name, description=:description where id=:id';

a questo punto usiamo il metodo update() della facade DB che riceve come primo argomento la query $sql e come secondo l’array contenente i dati da aggiornare

$res = DB::update($sql, $data);
dd($res);

Verifichiamo che funzioni ed in caso positivo restituiamo un return $res.

Restituire un messaggio e redirezionare

Se vogliamo restituire un messaggio creiamo una variabile $messaggio e una condizione if

$messaggio = $res ? 'Album con id = ' . $id . ' aggiornato' : 'Album ' .$id . ' non aggiornato';

adesso utilizziamo la funzione helper flash() che ci permette di aggiungere una variabile in sessione tramite session() quando la pagina si carica, mentre verrà distrutta se la si effettua un refresh della pagina

session()->flash('messaggio', $messaggio);

a questo punto per ritornare all’elenco degli album utilizziamo l’helper redirect(), restituendolo, che ci da accesso alla facade Route che contiene il metodo route() che riceve il nome della rotta

return redirect()->route('albums');

Vediamo come dare un nome ad una rotta tramite il metodo ->name(), questa funzione è utile perchè se un domani cambiassimo il percorso, non dobbiamo cambiare i riferimenti che puntano a questa rotta.

Route::resource('/albums', 'AlbumsController@index')->name('albums');

andiamo ora a restituire il messaggio nella view resources/views/albums/albums.blade.php con una condizione @if e il meodo has()

@if(session()->has('message'))
<div>{{ session()->get('message') }}</div>
@endif

aggiungiamo in fondo al template una funzione jQuery che ci fa scomparire il messaggio dopo 5 secondi

<script>
 $('document').ready(function () {
  $('.alert').fadeOut(5000);

Sfruttiamo i componenti di blade per creare un mini template riutilizzabile, quindi creiamo il file /resources/views/components/alert-info.blade.php

<div class="alert alert-info" role="alert">
 <strong>{{$slot}}</strong>
</div>

Utilizziamo il componente nel nostro template albums

@if(session()->has('message'))
 <x-alert-info>{{ session()->get('message') }}</x-alert-info>
@endif