Creare un’API GraphQL con Laravel? Ci pensa Lighthouse! – Parte 2

0
1926

Direi che è arrivato il momento di concludere il nostro piccolo viaggio introduttivo alla scoperta di come creare un’API GraphQL con Laravel. Nell’articolo precedente, pubblicato un paio di settimane, fa, avevo spiegato le basi di Lighthouse e di come usarlo per creare, facilmente, un’API GraphQL usando il nostro framework preferito.

L’ultima volta ci siamo lasciati dopo aver visto, un po’ più da vicino, le prime query sulla nostra entità Movie.

Oggi vedremo più da vicino come funzionano le mutation, come vengono gestite le relazioni tra entità e, infine, qualche esempio su altri tool che Lighthouse ci mette a disposizione per facilitarci il lavoro. Pronti? Partiamo dalle…

Mutation!

Come già spiegato nell’articolo precedente, nel mondo di GraphQL una Query è un’operazione di lettura, mentre una Mutation riguarda, appunto, una “mutazione” dei nostri dati. Può essere un inserimento, una modifica ma anche una cancellazione.

Per avere a disposizione queste operazioni nella nostra API, per fortuna, non dobbiamo fare molto. Andiamo a modificare il nostro file dello schema, aggiungendo

Come si può intuire, abbiamo definito tre mutation, una per ogni operazione da effettuare.

  • addMovieche si occupa dell’aggiunta di un nuovo film all’API;
  • updateMovie, che ci consente di modificare un film già esistente;
  • deleteMovienecessario a cancellare un film esistente;

La sintassi è abbastanza lineare:

  • definisco il nome della mutation;
  • i parametri sono quelli di cui avrò bisogno nel momento in cui userò la mutation corrispondente (titolo ed anno in fase di creazione, con aggiunta dell’id in fase di modifica; per concludere, solo l’id in fase di cancellazione);
  • in ogni caso, mi verrà ritornata l’entità Movie corrispondente;
  • le direttive finali@create, @update e @delete spiegano a Lighthouse quale operazione stiamo chiedendo. Sotto il cofano, il package si occuperà del resto, permettendoci di implementare le tre operazioni senza scrivere codice aggiuntivo;

Facciamo una prova? Apriamo il playground visto nell’articolo precedente (dovrebbe essere raggiungibile su localhost/graphql-playground, ed eseguiamo una mutation come

Se vediamo qualcosa del genere, tutto è andato a buon fine. Come esercizio, provate ad eseguire le altre due mutation! 😉

Relazioni tra entità

Abbiamo visto le operazioni più basilari con una singola entità. Come gestire, però, le relazioni tra diverse entità? Proviamo ad immaginarci una nuova entità: il director, il regista. Un’entità di cui intendo salvare tre informazioni:

  • nome;
  • cognome;
  • link alla pagina wikipedia;

Ovviamente, non scordiamoci la chiave esterna per la relazione di cui avremo bisogno, nella tabella movies. Ecco la migration:

Non dimentichiamoci, ovviamente, di creare il model e definire la relazione in esso.

Fatto questo, andiamo ad aggiungere un po’ di cose nel nostro schema:

Come probabilmente avete intuito, le due direttive @belongsTo e @hasMany descrivono i due “lati” della relazione tra film e regista. Esattamente come abbiamo fatto nel model Eloquent.

Come visto per le mutation di base, poco fa, queste due direttive sono specifiche di Lighthouse e ci permettono di usare le relazioni tra i nostri model senza dover scrivere altro codice. Ancora una volta, stesso approccio di prima: si usa quasi esclusivamente il file di schema, con l’aiuto delle direttive, per ottenere il risultato di cui abbiamo bisogno.

Torniamo al playground ed aggiungiamo un primo director con cui fare qualche prova.

Fatto questo, abbiamo dei dati su cui poter effettuare una query.

Perché non provare ad effettuare la query per ottenere un film specifico, ma stavolta chiedendo anche le informazioni sul regista? Così:

Con una singola query, stiamo chiedendo:

  • i dettagli del film;
  • i dettagli del regista;

La risposta, stavolta, sarà…

Nota: ho preparato questa query usando tutti i campi delle entità, ma nulla mi vieta di escludere uno o più campi (sia in Movie che in Director) per adattare la query al mio caso d’uso. Fate una prova voi stessi: eliminate dalla query qualche campo del Movie e del Director, e guardate cosa ne esce fuori!

L’aspetto più interessante di questa caratterestica di GraphQL è l’assoluta flessibilità di ogni query, una volta che questa viene ben costruita. Lavorando in questo modo, diventa molto più semplice coprire casi d’uso diversi senza dover andare a scrivere altro (e magari replicare parti di) codice.

Altre pillole di Lighthouse

Lighthouse, ovviamente, non si ferma alle sole operazioni di base. Coprirlo tutto in poche pagine sarebbe impossibile, ma prima di lasciarci volevo farvi dare un’occhiata a qualche altra direttiva che ho trovato degna di nota.

Validazione dei dati

So bene cosa avete pensato prima, mentre scrivevo i metodi di creazione/modifica di film e registi.

“E la validazione? Possiamo mai mandare i dati così, a caso?”

Ovviamente no. Come spiegato molto bene nell’apposita pagina della documentazione, tramite un  comando è possibile creare una classe “validator” apposita per il caso d’uso che vogliamo coprire. A quel punto, una volta specificate le regole nel formato che già conosciamo, non serve altro che definire il validatore usando la direttiva @validator

Ah, per i casi più semplici comunque esiste anche la direttiva @rules… 😉

Throttling

Le API sono una soluzione meravigliosa, anche e soprattutto quando si ha a che fare con partner/utenti esterni che possono consumarle per il loro business. Tuttavia, bisogna sempre tenere sotto controllo tutto quello che riguarda la sicurezza e l’eventuale abuso di un’API.

Lighthouse ci mette a disposizione la direttiva @throttle come prima difesa verso gli “utilizzatori compulsivi” della nostra API.

Molto interessante la possibilità di definire facilmente un numero di tentativi in un certo lasso di tempo, e la durata di tale lasso di tempo.

Ordinamento

Abbiamo visto la semplicità con cui è possibile implementare, per le nostre query, la paginazione. La cosa che serve sempre, subito dopo la paginazione, è l’ordinamento crescente/decrescente partendo da un campo specifico.

Anche qui, indovinate? C’è una direttiva: l’utilissima @orderBy che ci consente di definire per quali campi sarà possibile ordinare i risultati. Sarà possibile, quindi, creare una query come questa:

Et voilà!

Concludendo

Anche oggi ho sforato il buon proposito di tenermi “breve”. Fa niente: l’importante è che l’articolo vi sia stato, in qualche modo, utile a capirne qualcosa di più. GraphQL non è qualcosa che si adatta a tutti i progetti, ma per determinati casi d’uso può essere davvero di grande aiuto e fare la differenza.

Voi ci avete mai messo le mani? Fatemi sapere… sono curioso!

Se volete tenervi aggiornati su quello che scrivo, iscrivetevi alla newsletter! Trovate qui il form di iscrizione, oppure potete dare un’occhiata qui a lato. Alla prossima!