API RESTful e risorse nidificate

3

Avendo costruito un'API RESTful (usando Laravel) per un progetto al lavoro, ho seguito quello che sembrava (da molte letture) essere la maggioranza in termini del mio approccio alle risorse annidate - definendole nel percorso:

https://myapi.com/clients/{clientId}/tasks

anziché:

https://myapi.com/tasks?client={clientId}

Il filtraggio dei risultati oltre questo, oltre all'ordinazione, è stato fatto usando i parametri di query:

https://myapi.com/clients/{clientId}/tasks?orderby=title

Sebbene all'inizio questo sembrasse un buon approccio, diventava più difficile da mantenere in termini di controllori e percorsi. Ad esempio, per quanto sopra, ho creato un ClientsController, un TasksController AND un ClientsTasksController.

TasksController

public function store() {}
public function updated() {}
public function destroy() {}

TasksClientsController

public function index($client_id) {}

E i percorsi :

Route::resource('tasks', 'TasksController', ['except' => [
    'edit', 'index'
]]);
Route::resource('clients.tasks', 'ClientsTasksController', ['only' => [
    'index'
]]);

Questa applicazione non aveva bisogno di molte altre risorse annidate come questa, era relativamente semplice. Tuttavia, ora sto cercando di creare un'API per l'applicazione esistente che ha molte relazioni più complesse. È un'app per la gestione del campionato, schema EER di seguito:

Perquantomiriguarda,hobisognodiinterrogarelerisorseconmoltidatidiversi,adesempio:

  1. teamperdivisione,stagioneeroundspecifici
  2. statistichesiaperIDdellasquadracheperIDdellastagioneepossibilmenteperarrotondareanche
  3. partiteperstagione,roundedivisione

ecombinazionidiquantosopra.

Quindimisembrapiùsensatoavereuncontrollereuninstradamentoperognirisorsafinale,mausareiparametridiquerypiuttostochelevariabilidipercorso.

Adesempio:

https://myapi.com/matches?team_id={teamId}&season_id={seasonId}&roundId={roundId}

anziché:

https://myapi.com/seasons/{seasonId}/teams/{teamId}/matches

eivaricontrolleraggiuntivichequestocreerebbe.

Tuttavia,ritengochequestopotrebbeandareincontrotendenzainterminidiciòchelamaggiorpartedellepersonesembrasuggerire:vedi qui per esempio. Anche il secondo URL mi sembra più carino.

Qualsiasi aiuto / raccomandazione sarebbe molto apprezzato.

    
posta C Ivemy 10.01.2017 - 12:08
fonte

1 risposta

3

Se stai progettando l'API di maturità L3 (HATEOAS) [1], i client non creano o ricordano gli URL. L'approccio migliore in questo caso consiste nell'avere più mapping per supportare entrambi gli scenari: recupero tramite navigazione e query per popolazione di parametri modello URI (RFC 6570 [2]).

Quando si recupera tramite la navigazione verso il collegamento fornito, la scelta della struttura del percorso dovrebbe essere basata sulla relazione tra le entità sia l'aggregazione o la composizione, vale a dire se un'entità possiede un'altra o semplicemente la fa riferimento. Ad esempio, un giocatore è un'entità di primo livello, perché il ciclo di vita di un giocatore non rientra nei limiti del ciclo di vita di una squadra. I giocatori possono cambiare squadra, quindi è naturale avere la seguente serie di percorsi:

  • rel=players elenco di riferimenti dei giocatori su /players
  • rel=self per giocatore è players/{playerId}
  • rel=teams riferimenti elenco di squadre a /teams
  • rel=self per team è teams/{teamId}
  • rel=seasons riferimenti elenco di stagioni a /seasons
  • rel=self per la stagione è /seasons/{seasonId}

Tutti gli endpoint di raccolta possono accettare parametri di query per impaginare e filtrare la risposta.

Esempi di aggregazione

È possibile conoscere tutte le squadre del giocatore e viceversa, ma i link di raccolta includono i parametri del modello URI solo se questi valori dei parametri sono rilevabili dal client nelle navigazioni precedenti.

Ad esempio, ogni client inizia con la radice dell'API per recuperare l'elenco delle risorse. In questo momento, scopre rel=teams , ma il collegamento non può avere parametri di query da filtrare per i giocatori, perché il cliente non sa ancora quali sono i valori di ID giocatore da sostituire. Il link può guardare in questo momento solo come segue: /teams{?team_name} Lo stesso con il link rel=players in questo momento: può contenere solo filtri per nome giocatore, ma non per squadra. Può sembrare come segue: /players{?first_name} .

Tuttavia, quando navighiamo a /teams , scopriamo il collegamento rel=players in /teams , che ora contiene il parametro team_id , perché i suoi possibili valori sono già rilevati dal client. Può sembrare come segue: /players{?team_id,first_name,last_name} .

In alternativa, possiamo utilizzare i seguenti percorsi scoperti nelle risposte di rel=self richieste per giocatori e squadre:

  • rel=player_teams può elencare tutti i team per i quali il giocatore ha mai eseguito: /players/{playerId}/teams . Ogni squadra ha rel=self come definito sopra.
  • rel=team_players nell'elenco dei riferimenti di risorse del team dei giocatori della squadra tramite /teams/{teamId}/players . Ogni giocatore ha rel=self come definito sopra.

Esempio di composizione

Se una divisione è definita per ogni stagione separatamente, allora ha lo stesso ciclo di vita e c'è una relazione di composizione. Lo stesso vale per le partite in una stagione. Ciò significa che è naturale creare il percorso da abbinare come segue:

/seasons/{seasonId}/matches/{matchId}

E vai alle partite all'interno di una divisione seguendo il seguente percorso:

/seasons/{seasonId}/divisions/{divisionId}/matches

o per ricerca:

/seasons/{seasonId}/matches?division_id={divisionId}

Gli ultimi due possono essere gestiti dallo stesso controller se la tecnologia API REST supporta più mapping. Tutti i sottotracciati in questo esempio sono anche richieste valide e devono restituire le rispettive informazioni. Inoltre, questo esempio può essere esteso con ulteriori rotte aggregate come:

  • /seasons/{seasonId}/divisions/{divisionId}/teams - elenco delle squadre in divisione, in cui ogni risorsa del team ha il link rel=self come definito sopra.
  • /seasons/{seasonId}/statistics/players - elenco delle statistiche dei giocatori nella stagione

Riferimenti

  1. link
  2. link
risposta data 11.01.2017 - 00:33
fonte

Leggi altre domande sui tag