Βέλτιστες πρακτικές σχεδιασμού API στο Laravel

Κλεμμένο από εδώ.

Αυτή η ανάρτηση έχει μια ηχητική έκδοση χάρη στην εφαρμογή Blogcast του Miguel Piedrafita.

Δεν είμαι μόνο ένας μηχανικός DevOps, αλλά επίσης ξεκίνησα από το σημείο μηδέν με την PHP από τότε που ήμουν μικρό παιδί, πίσω στις μέρες που ήμουν στην 5η τάξη. Έκτοτε, βελτίωσα συνεχώς τον κώδικα μου και ανακάλυψα ότι οι άνθρωποι υιοθέτησαν κάποια πρότυπα για καθαρότερο κώδικα, καλύτερη απεικόνιση και δεδομένου ότι είναι πρότυπα, όλοι θα μπορούσαν να καταλάβουν καλύτερα τι έγραψε κάθε άλλος προγραμματιστής με τον ίδιο κωδικό.

Έχω πάντα αγάπη να κωδικοποιώ περισσότερο στο backend παρά στο front. Προσπάθησα να είμαι πλήρης στοίβα, αλλά δεν μου ταιριάζει. Έτσι έχω πέσει πίσω στο γράψιμο backend, ειδικά APIs. Αυτή τη φορά, δεν θα μιλήσω για πρότυπα κωδικοποίησης εν γένει, αλλά θα μιλήσω για τι λειτουργούν τα API και πώς να τα αναπτύξουμε ευκολότερα, από την ασφάλεια σε συμβουλές για το πώς να το κάνεις καλύτερα.

Βασικά, ένα API είναι μια διεπαφή που επιστρέφει τα δεδομένα σε ειδική μορφή που μπορεί να καταλάβει κάθε είδους εφαρμογή, είτε είναι μια εφαρμογή Android είτε μια εφαρμογή ιστού.

Το JSON χρησιμοποιείται ευρέως, αφού είναι σχεδόν παντού. Η άλλη επιλογή είναι να χρησιμοποιήσω XML, αλλά είχα πρόβλημα με κάποια API τρίτων μερών (ειδικά παρόχους πληρωμών στη χώρα μου) που χρησιμοποίησαν XML πάνω από το JSON και η ανάπτυξη ήταν ένα πλήρες χάλια. Συνιστώ την ανάπτυξη API JSON, όλη την ώρα, εκτός αν κάποιος ζητήσει ένα API XML.

Κατά την ανάπτυξη ενός API, θα πρέπει να λάβετε υπόψη σας μερικά πράγματα, με τη συγκεκριμένη σειρά:

  • η ασφάλεια - η εξασφάλιση της χρήσης του OAuth, ενός κλειδιού API ή του CORS είναι απαραίτητη. Προαιρετικά, θα πρέπει να χρησιμοποιείτε ένα throttler για να περιορίσετε τις αιτήσεις στην εφαρμογή σας.
  • κεφαλίδες - βεβαιωθείτε ότι οι εφαρμογές σας στέλνουν τον σωστό τύπο περιεχομένου. Μια κεφαλίδα τύπου περιεχομένου είναι ένα κομμάτι πληροφοριών που λέει στον πελάτη που λαμβάνει τα δεδομένα: "αυτό το πράγμα που σας στέλνω είναι JSON" ή "που εδώ είναι XML. αναλύστε το σωστά ", έτσι ώστε το πρόγραμμα περιήγησης ή ο πελάτης σας να γνωρίζει πώς να το αποκωδικοποιήσει σωστά.
  • πρότυπα κωδικοποίησης και ονομασία - αυτό είναι καθαρά backend. Βεβαιωθείτε ότι είστε συνεπείς στις απαντήσεις σας. Προσέχετε μόνο ένα είδος ονοματοδοσίας και σωστής μορφοποίησης.

Μου αρέσει να κωδικοποιώ APIs στο Laravel, δεδομένου ότι θέλετε να κλιμακώσετε περαιτέρω με το Event Broadcasting ή τις άλλες λείες δυνατότητες Lumen που το κάνουν φλεγόμενο-γρήγορο, μπορείτε να το κάνετε χωρίς να ξαναγράψετε ολόκληρο το έργο από το μηδέν. Σε περίπτωση που παραμείνετε στο ελάχιστο, μη διστάσετε να χρησιμοποιήσετε το Lumen.

Ασφάλεια

Το μεγαλύτερο πρόβλημα που πρέπει να αντιμετωπίσετε είναι η ασφάλεια. Είναι εύκολο να το ασφαλίσετε, αλλά αν δεν το κάνετε σωστά, μπορεί να έχετε ανεπιθύμητη πρόσβαση. Στο Laravel, ίσως να θέλετε να χρησιμοποιήσετε το Laravel Passport - ανήκει στο οικοσύστημα Laravel, υποστηρίζει την πιστοποίηση μέσω αυτού του App ID - App Secrety προκειμένου να αποκτήσει ένα αναγνωριστικό πρόσβασης, είτε για να μιμηθεί κάποιον ή για έναν διακομιστή, είτε είναι backend ή front end. Βασικά, θα υποβάλλετε ένα αίτημα με το αναγνωριστικό εφαρμογής σας και το μυστικό εφαρμογής σε ένα τελικό σημείο του OAuth για να λάβετε ένα κουπόνι, το οποίο μπορεί είτε να δημιουργηθεί από ένα διακομιστή (π.χ. πρόσβαση σε ένα API από μια εντολή που τρέχει σε ένα cronjob κάθε μέρα) χρήστη που έχει συνδεθεί στην εφαρμογή σας.

Εναλλακτικά, ίσως θελήσετε να χρησιμοποιήσετε έναν έλεγχο ταυτότητας JWT Token, ο οποίος λειτουργεί σχεδόν το ίδιο, αλλά ίσως είναι ευκολότερο να κατανοηθεί. Επιλέξτε την επιλογή σας και δείτε τι ταιριάζει καλύτερα για εσάς, τόσο στην εφαρμογή όσο και στις ανάγκες σας.

Κεφαλίδες

Οι αιτήσεις ιστού είναι απλώς συνηθισμένες συνομιλίες μεταξύ ενός πελάτη και ενός διακομιστή ή μεταξύ δύο εξυπηρετητών. Βασίζονται σε ένα αίτημα και μια απάντηση, εκτός και αν είναι ένα είδος αίτησης websocket, αλλά αυτό είναι απλώς μια άλλη ιστορία. Όταν ζητάτε ή στέλνετε τα πράγματα πίσω, υπάρχουν κάποιες πληροφορίες που ονομάζονται Κεφαλίδες που πρέπει να ληφθούν μέριμνα - μερικοί εξηγούν στον διακομιστή πώς να επεξεργάζονται τις πληροφορίες που έχουν λάβει ή πώς ο πελάτης θα ήθελε να λάβει την απάντηση.

Είναι σαν να σας λέει η μητέρα σας: "Πηγαίνετε να αγοράσετε λίγο γάλα από το κατάστημα αλλά αγοράστε μόνο από το γάλα με επώνυμα X". Ξέρεις τι πρέπει να κάνεις, αλλά πρέπει να το πάρεις μόνο ένα είδος γάλακτος. Είναι το ίδιο με τα αιτήματα: "θέλω να βρω τον κατάλογο των χρηστών, αλλά να τους δώσω σε JSON" ή "θέλω να πάρω όλους τους χρήστες, αλλά να με στείλετε σε κομμάτια των 20" (σε περίπτωση που καθορίσετε μια παράμετρο GET ). Για αυτό, υπάρχει μια κεφαλίδα που ονομάζεται Αποδοχές, η οποία μπορεί να είναι application / json σε περίπτωση που θέλετε την απάντηση ως JSON. Δεν είναι απαραίτητο, αλλά για ορισμένες εφαρμογές όπως το AJAX, αν εντοπίσει αυτήν την κεφαλίδα, αυτόματα αποκωδικοποιεί την απάντηση για τον πελάτη, χωρίς να χρειάζεται να κάνει κάτι τέτοιο:

τα δεδομένα var = JSON.parse (response.data);

Μια άλλη κεφαλίδα που πρέπει να γνωρίζετε είναι ο τύπος περιεχομένου, που είναι λίγο συγκεχυμένος, αλλά είναι απέναντι από την Αποδοχή: ενημερώνει το διακομιστή σχετικά με το πώς να χειριστεί το περιεχόμενο που παίρνει. Για παράδειγμα, εάν θέλετε να στείλετε δεδομένα RAW, όπως μια συμβολοσειρά JSON, μπορείτε να ορίσετε τον Τύπο περιεχομένου σε εφαρμογή / json, αλλά αν θέλετε να λάβετε το περιεχόμενο μέσω της μεταβλητής $ _POST, θα πρέπει να το ορίσετε σε x-www -form-urlencoded. Αυτό θα σας βοηθήσει όχι μόνο με την ανάλυση του περιεχομένου απευθείας μέσω $ _POST, αλλά θα πρέπει να χρησιμοποιείται σε φόρμες HTML, επειδή είναι εύκολα προσβάσιμο. Εάν στέλνετε δεδομένα όπως δυαδικό, μέσω αρχείων εισόδου, για παράδειγμα, βεβαιωθείτε ότι έχετε στείλει το περιεχόμενο multipart / form-data.

Στο Laravel, αυτό δεν θα αποτελέσει πρόβλημα, δεδομένου ότι μπορείτε να έχετε απευθείας πρόσβαση στα δεδομένα.

Για την εφαρμογή / json:

δείκτης λειτουργίας (αίτημα αίτησης $)
{
   $ var = $ request-> μεταβλητή;
}}

Ωστόσο, στην εφαρμογή / json δεν μπορείτε να δείτε τη μέθοδο -> all () το περιεχόμενο JSON:

δείκτης λειτουργίας (αίτημα αίτησης $)
{
   $ data = $ request-> all (); // αυτό είναι κενός πίνακας, ακόμα και έχουμε δεδομένα.
}}

Αν έχει οριστεί σε x-www-form-urlencoded ή multipart / form-data, μπορείτε να δείτε όλες τις μεταβλητές χρησιμοποιώντας -> all ().

Όταν απαντάτε στο Laravel, μπορείτε να χρησιμοποιήσετε την ενσωματωμένη απάντηση JSON Ή μπορείτε να το επεξεργαστείτε καλύτερα και να χρησιμοποιήσετε ένα πακέτο όπως το Laravel Fractal ή το Laravel Responder. Από τη δική μου εμπειρία, ο Laravel Responder έκανε την δουλειά του καλύτερα, με πιο σημασιολογικό τρόπο. Επιτρέψτε μου να σας δείξω:

getUsers (ζητήστε αίτημα $)
{
   return responder () -> επιτυχία (User :: all ()) -> response ();
}}

Αυτό θα επιστρέψει όλους τους χρήστες με κατάσταση OK 200 και μορφοποιημένο ως JSON. Καλά, σωστά; Για σφάλματα, πρέπει να κάνετε κάτι τέτοιο, το οποίο σας επιτρέπει να στείλετε έναν κωδικό και ένα μήνυμα:

getUsers (ζητήστε αίτημα $)
{
   $ users = Χρήστης :: all ();

   αν ($ χρήστες-> count () === 0) {
      () -> λάθος ('no_users', 'Δεν υπάρχουν χρήστες.') -> απάντηση ();
   }}
   () -> επιτυχία ($ χρήστες) -> απάντηση ();
}}

Αυτό το πακέτο υποστηρίζει πολύ περισσότερα, επομένως κατευθυνθείτε στα docs επειδή μπορεί εύκολα να ενσωματωθεί με μετασχηματιστές και προσαρμοσμένα δεδομένα που αποστέλλονται.

Πρότυπα κωδικοποίησης

Αυτό που μου αρέσει να βλέπω είναι οι άνθρωποι να κολλάνε με κάποια πρότυπα που τους ταιριάζουν ή είναι καθαρά. Ακολουθούν ορισμένες συμβουλές που θα μπορούσαν να σας βοηθήσουν να δημιουργήσετε πιο καθαρό κώδικα και να διαρθρώσετε καλύτερα τις διαδρομές API σας.

Χρησιμοποιήστε τα αρχεία διαδρομών / api.php για διαδρομές API

Το Laravel έρχεται με ξεχωριστές διαδρομές / api.phpfile που απομακρύνεται από τα συνηθισμένα δρομολόγια / αρχείο web.php που χρησιμοποιείται για τη δρομολόγηση ιστού. Το αρχείο api.php δημιουργείται για να αποθηκεύσει τις διαδρομές σας API. Έχει ενσωματωμένο ενδιάμεσο λογισμικό (που μπορεί να δει στο app / Http / Kernel.php, στη μεταβλητή $ middlewareGroups, στο api) και στο πρόθεμα / api, έτσι ώστε όλες οι οδούς που ορίζονται είναι ήδη διαθέσιμες στο / api

Χρησιμοποιήστε τα ονόματα διαδρομών

Αυτό που θέλω να κάνω είναι να θέσω μια ρύθμιση ως το σύνολο του API, οπότε μπορώ να αποκτήσω πρόσβαση στις διαδρομές με το όνομά τους, με api. πρόθεμα.

Διαδρομή :: get ('/ users', 'API \ UserController @ getUsers') -> όνομα ('get.users');

Η διεύθυνση URL αυτής της διαδρομής μπορεί να πάρει τη διαδρομή ('get.users'), αλλά ενδέχεται να έρθει σε σύγκρουση με το web.php.

Διαδρομή :: ομάδα (['as' => 'api.'], Λειτουργία () {
   Διαδρομή :: get ('/ users', 'API \ UserController @ getUsers') -> όνομα ('get.users');
});

Με αυτόν τον τρόπο, θα το έχετε στη διαδρομή ('api.get.users').

Εάν χρησιμοποιείτε τις ονομασίες διαδρομής, εάν οι δοκιμές εγγραφής σας δεν χρειάζεται να αντικαταστήσετε τη διεύθυνση URL παντού, αν σκοπεύετε να αλλάξετε τη θέση URL και να διατηρήσετε το όνομα της διαδρομής.

Περιγραφικά, αλλά απλά δρομολόγια

Μια καλή πρακτική είναι να ομαδοποιήσετε τις διαδρομές σε τμήματα, όπως χρήστες, θέσεις κ.λπ. και να χρησιμοποιήσετε τα πιο απλά πράγματα που μπορείτε να σκεφτείτε:

Διαδρομή :: ομάδα (['as' => 'api.'], Λειτουργία () {
   Route :: group (['as' => 'account', 'prefix' => '/ account'],
         Διαδρομή :: get ('/ users', 'API \ UserController @ getUsers') -> όνομα ('get.users');
         Διαδρομή :: get ('/ user / {id}', 'API \ UserController @ getUser') -> όνομα ('get.user');
         Route :: post ('/ user', 'API \ UserController @ createUser') -> όνομα ('create.user');
         // και τα λοιπά.
   });
});

Χρησιμοποιήστε :: get () για τη λήψη δεδομένων, :: post () για τη δημιουργία, :: patch () ή :: put () για επεξεργασία και :: delete () για τη διαγραφή δεδομένων. Έτσι, καταλήγετε στο ίδιο τελικό σημείο, αλλά με τα διαφορετικά είδη αιτημάτων, θα μπορείτε να ενεργοποιήσετε άλλες ενέργειες.

Μέσα στον ελεγκτή σας, θα πρέπει να χρησιμοποιείτε απλή κωδικοποίηση και να κάνετε χρήση των κλάσεων αιτήσεων, όπως εξήγησα στο Pushing Laravel περαιτέρω - καλύτερες συμβουλές και καλές πρακτικές για το Laravel 5.7

getUsers (ζητήστε αίτημα $)
{
   $ users = Χρήστης :: all ();
   () -> επιτυχία ($ χρήστες) -> απάντηση ();
}}
λειτουργία getUser ($ id, αίτημα αίτησης $)
{
   $ user = Χρήστης :: findOrFail ($ id);
   () -> επιτυχία ($ user) -> απάντηση ();
}}
συνάρτηση createUser (CreateUserRequest $ request)
{
    $ user = Χρήστης :: δημιουργία ($ request-> all ());
    () -> επιτυχία ($ user) -> απάντηση ();
}}
// και τα λοιπά.

Επίσης, βεβαιωθείτε ότι έχετε κολλήσει με τα ίδια ονόματα για όλες τις ενέργειες, έτσι θα τα βρείτε πιο γρήγορα και ο καθένας μπορεί να έρθει στον κώδικα και να διευκολύνει τη διατήρηση ή τη δημιουργία περιεχομένου. Μην δεσμεύετε κλειδιά API ή ευαίσθητα δεδομένα στο repo, γράφετε καθαρό κώδικα και είστε πρόθυμοι να μάθετε από τους άλλους.

Πάρα πολύ δύσκολο να καταλάβεις; Φτάσε με!

Εάν έχετε περισσότερες ερωτήσεις σχετικά με το Laravel, αν χρειάζεστε βοήθεια με οποιαδήποτε πληροφορία που σχετίζεται με DevOps ή απλά θέλετε να πείτε ένα Ευχαριστώ !, μπορείτε να με βρείτε στο Twitter @rennokki!

Γίνετε μέλος της κοινότητας μας Χαλαρώστε και διαβάστε τα εβδομαδιαία θέματα Faun ⬇

Εάν αυτή η ανάρτηση ήταν χρήσιμη, κάντε κλικ στο πλήκτρο below κάτω από μερικές φορές για να δείξετε την υποστήριξή σας στον συντάκτη! ⬇