Fermer

mai 11, 2022

Conception d’API flexible : créez des crochets pour votre pipeline d’API PHP

Conception d’API flexible : créez des crochets pour votre pipeline d’API PHP


La conception d’interfaces de programmation d’applications (API) peut être une tâche difficile. Les bonnes API ont des interfaces simples, simples et faciles à utiliser. Derrière cette interface simple, il peut y avoir de nombreuses interactions système complexes, et ces interactions peuvent vraiment brouiller les pistes d’une tâche de point de terminaison autrement clairement définie. Au fil du temps, les développeurs peuvent être invités à « ajouter » une logique métier supplémentaire pour les points de terminaison existants. Puis, avant que vous ne vous en rendiez compte, un seul appel d’API effectue des interactions avec plus d’une douzaine de systèmes dans le cadre de son flux principal.

Ne serait-il pas agréable de pouvoir développer un pipeline simple mais avec la possibilité d’ajouter des tâches supplémentaires ultérieurement sans obscurcir le flux principal ? Cet article vous montrera comment vous pouvez adapter une idée de WordPress, et la programmation en général, pour donner à vos API la possibilité de faire des interactions plus puissantes.

Que sont les crochets/actions ?

UN crochet (alias actions/filtres) est le nom donné aux événements et à leurs rappels associés par la communauté WordPress. Si vous avez de l’expérience en programmation, vous connaissez peut-être les rappels et les modèle éditeur-abonné. Pendant le traitement, un système peut déclencher un événement qui appelle zéro à de nombreuses fonctions abonnées à cet événement. Par exemple, en réponse au chargement d’une page, WordPress appelle des fonctions pour charger l’en-tête, charger un titre, répertorier les publications ou rechercher le bon modèle. Ces tâches sont exécutées sans encombrer le processus principal de génération d’une page.

L’idée derrière les crochets n’est pas nouvelle et n’a pas été inventée par WordPress. Cependant, WordPress a fait un excellent travail en les implémentant au cours de leur cycle de vie de traitement des pages côté serveur. Cette utilisation de crochets, à mon avis, est probablement la plus grande caractéristique de la plate-forme. Avec ces crochets, les utilisateurs peuvent écrire leurs propres fonctionnalités – qu’il s’agisse de plugins ou de thèmes – qui se lient à WordPress et exécutent le code que vous voulez au moment où vous en avez besoin. Avez-vous besoin de modifier un en-tête envoyé à l’utilisateur ? Pas de problème : accrochez-vous au wp_headers événement et vous pouvez modifier les en-têtes comme bon vous semble.

Pourquoi utiliser des hooks dans une API ?

Les crochets sont bons pour beaucoup de choses, y compris déclencher certaines tâches secondaires, appeler un autre système via une commande PHP cURL, créer un objet et le mettre dans une file d’attente de tâches pour qu’il soit récupéré par un autre système plus tard, envoyer un e-mail, etc. Tout cela peut être fait sans avoir besoin de brouiller le flux principal d’un point de terminaison donné (et éventuellement de forcer une nouvelle version d’API dans le processus).

Si le point de terminaison est destiné à créer un utilisateur, nous pouvons nous concentrer sur la création de cet enregistrement d’utilisateur dans la base de données et, en cours de route, appeler simplement la personne qui écoute pendant ce processus. Peut-être qu’après avoir créé l’enregistrement de l’utilisateur, nous envoyons un événement qui dit « quiconque écoute ceci, je viens de créer un utilisateur et voici ses informations ». Peut-être que certaines fonctions de rappel se sont abonnées à l’événement et écoutent ou peut-être qu’aucune ne l’est. L’événement n’a pas vraiment d’importance.

Avec ce système, nos API peuvent appeler du code qui peut être écrit ultérieurement. Nous pouvons le faire sans avoir à toucher au code du point de terminaison de l’API lui-même. Pour montrer comment cela pourrait fonctionner, changeons de vitesse et montrons le mécanisme de base permettant de démarrer cela dans une API PHP. Gardez à l’esprit que, pendant que nous utilisons PHP ici, nous pouvons en fait implémenter une logique similaire dans des applications Web utilisant d’autres langages.

Construire les mécanismes de base

Pour commencer, nous devrons pouvoir ajouter un crochet/action (que j’appellerai désormais « crochet »). Nous aurons également besoin de la possibilité de supprimer un crochet et enfin de déclencher un crochet. Une fois que nous avons défini ces mécanismes, nous devons simplement nous assurer qu’ils sont inclus dans l’API, puis localiser les endroits dans notre API où nous pourrions vouloir appeler ces crochets. Vous trouverez ci-dessous une façon de configurer cela.

Voici hooks.php:




$hooks = [];



function add_hook($event_name, $callback) {
    global $hooks;

    if ($callback !== null) {
        if ($callback) {
          
            $hooks[$event_name][] = $callback;
        }
    }
}


function remove_hook($event_name) {
    global $hooks;

    unset($hooks[$event_name]);
}



function do_hook($event_name, ...$params) {
    global $hooks;

    if (isset($hooks[$event_name])) {
      
      
        foreach ($hooks[$event_name] as $function) {
            if (function_exists($function)) {
                call_user_func($function, ...$params);
            }
        }
    }
}

Maintenant que nous avons notre hooks.php fichier créé, il suffit de l’inclure dans notre API pour que ces fonctions soient visibles. Une fois cela fait, il suffit d’insérer les crochets dans notre API en utilisant do_hook.

Comme exemple simple, supposons que nous ayons une API pour enregistrer un nouvel utilisateur avec notre système. Nous pouvons avoir un point de terminaison API REST appelé /addUser. Au nom de la simplicité, supposons également que le but ici est simplement d’insérer le nom et l’âge d’un nouvel utilisateur dans notre base de données. users table. Assez simple, non?


public function addUser($name, $age) {
  if ($this->request->method === 'post') {
    try {
      $this->db->insert('users', ['name' => $name, 'age' => $age]);
      return new Response(200, 'User created successfully!');
    } catch (Exception $e) {
      
      
    }
  }

  
  return new Response(400, 'Bad request');
}

Le code ci-dessus est une vue trop simpliste et généralisée de la façon dont nous pourrions ajouter un nouvel utilisateur. L’idée est que, si quelqu’un appelait nos API /addUser point de terminaison, ils arriveraient éventuellement à cette fonction où le nom et l’âge de l’utilisateur sont extraits des données publiées. Nous vérifions d’abord qu’ils publient (comme le dictent les règles REST appropriées), puis essayons d’insérer l’utilisateur dans le users table.

Ensuite, si l’utilisateur a été inséré avec succès, nous voulons appeler un crochet pour laisser tout code écouter qu’un utilisateur a été créé (ceci est similaire à déclencher un événement dans d’autres langages).

Que faire lorsque les exigences changent

Quelques mois plus tard, notre service marketing insiste pour que, lorsqu’un nouvel utilisateur est créé, un e-mail soit envoyé avec les détails de l’utilisateur. Nous pourrions être enclins à écrire une fonction d’assistance dans l’API, puis à l’appeler à partir de ce code de point de terminaison. Génial… si c’est tout ce qui était demandé. Mais que se passe-t-il si l’équipe d’assistance vous contacte plus tard et souhaite que vous ajoutiez également l’utilisateur à son système Zendesk. Donc, vous écrivez une autre fonction et pointez cet appel dans ce point de terminaison également.

Ensuite, ce point de terminaison n’ajoute pas seulement un utilisateur à la base de données de notre site Web, mais appelle également des fonctions d’envoi d’e-mails, ajoute des utilisateurs à Zendesk, Jira et au cloud Microsoft, puis traite leurs résultats de réussite/échec. Toutes ces choses supplémentaires enlèvent vraiment le point clair d’ajouter l’utilisateur à notre base de données. Nous aimerions appeler un événement et demander à un autre code d’écouter lorsqu’un utilisateur est créé et de faire ses propres choses – sans que nous ayons besoin de modifier ce point de terminaison. Peut-être qu’aucun autre service ne se soucie d’ajouter un nouvel utilisateur, donc personne n’est appelé à faire quoi que ce soit. Le point final n’a pas à s’en soucier. Assez génial, non?

Continuons notre exemple en donnant un nom à notre crochet. C’est le nom que tout code de rappel devra utiliser pour écouter. Encore une fois, d’autres langues font référence à cette configuration en tant qu' »événements », alors assurez-vous de la rechercher dans votre langue pour en savoir plus.

Nous appellerons notre crochet added_user. Simple et droit au but, vous ne pensez pas ? Une fois que nous avons un nom, nous pouvons décider où nous voulons appeler ce crochet. Je pense que juste après une insertion réussie serait une bonne idée :

public function addUser($name, $age) {
  if ($this->request->method === 'post') {
    try {
      $this->db->insert('users', ['name' => $name,  'age' => $age]);
      
      do_hook('added_user', $name, $age);
      return new Response(200, 'User created successfully!');
    } catch (Exception $e) {
      
      
    }
  }

  return new Response(400, 'Bad request');
}

Maintenant, nous pouvons avoir des dizaines de fonctions de rappel écoutant le added_user crochet ou pas du tout. Peut-être avons-nous un rappel chargé d’insérer l’utilisateur dans Zendesk et un autre qui prendra le nom et l’âge et générera un e-mail au marketing. Ce code « abonné » peut vivre ailleurs dans la base de code, tant qu’il peut voir le hooks.php code à l’intérieur du projet API. Je place généralement ma fonction de rappel dans un fichier séparé et j’inclus également ce fichier dans l’API. Vous trouverez ci-dessous un exemple de rappel qui peut désormais tirer parti de ce nouveau crochet que nous avons créé :

function sendContactToMarketing($name, $age) {
  
}

add_hook('added_user', 'sendContactToMarketing');

Où pouvons-nous placer ces crochets ?

Dans le code ci-dessus, nous démontrons l’utilisation d’un crochet dans un seul point de terminaison. Ce crochet n’est déclenché que lorsque le /addUser endpoint est appelé, et seulement après la réussite de l’insertion. Mais ce n’est pas le seul endroit où vous pouvez utiliser ces crochets. Vous avez peut-être un code de routage dans votre classe API qui vérifie si une clé API est valide ou que vous avez même reçu un certain type de demande.

Vous pouvez placer un crochet au niveau global dans l’API afin que chaque requête le déclenche. Puis, plus tard, quelqu’un pourrait écrire un enregistreur, le joindre au api_init hook que vous avez créé et commencez soudainement à consigner toutes les requêtes adressées à l’API – encore une fois, sans toucher au code de classe de l’API principale. Ce même crochet peut également avoir un rappel supplémentaire attaché qui vérifierait les abus d’API et le signalerait à votre service informatique s’il commence à voir quelqu’un claquer votre API avec des demandes.

L’image ci-dessous est un schéma de l’architecture de tout cela.

Diagramme des crochets dans l'API

Étant donné que vous pouvez utiliser ce mécanisme à plusieurs endroits, vous pouvez même avoir des crochets appelés au début, au milieu et à la fin d’un point de terminaison d’API. Vous pouvez également avoir des crochets à différents points du cycle de vie complet de l’API de traitement d’une demande. C’est vraiment à votre conception de l’endroit où vous les insérez do_hook appels.

Les meilleures pratiques

Voyons maintenant quelques bonnes pratiques à suivre pour vous et vos développeurs.

Astuce 1 : Gardez vos hameçons maigres et méchants

Une chose à garder à l’esprit est que ces crochets appellent toujours du code qui s’exécutera dans le thread unique. À moins que vous ne déclenchiez quelque chose dans votre rappel qui envoie la tâche à un processus d’arrière-plan ou à un autre service, l’API exécutera toujours ce code supplémentaire (lorsque le hook est déclenché). Cela signifie que nous devons faire de notre mieux pour que tout code de rappel reste léger et méchant. Un code de rappel de longue durée va ralentir les points de terminaison ou l’API dans son ensemble.

Astuce 2 : faites en sorte que chaque rappel soit isolé et simple à déboguer

Cependant, avec la façon dont cette structure est conçue, ajouter et supprimer des fonctions de rappel pour vos crochets est facile à faire et le débogage est tout aussi simple. Trouvez quel rappel est le coupable (peut-être que chaque rappel enregistre des données) et découvrez où il se bloque. Ensuite, ne le faites tout simplement pas s’abonner au crochet jusqu’à ce que le bogue soit corrigé ou travaillez sur le code de rappel, encore une fois sans rien toucher dans le code du point de terminaison/API et n’empêchant pas votre code API de s’exécuter en production.

Astuce 3 : pensez aux performances et n’abusez pas d’un crochet

Il est également important de garder à l’esprit le nombre de rappels que vous attachez à vos crochets. Une poignée de rappels rapides, c’est bien, mais 100 rappels sur un seul crochet, chacun prenant une seconde pour s’exécuter, peuvent vraiment être un frein à votre API. Nous voulons des appels d’API rapides, et chaque rappel peut facilement allonger les temps de réponse. Encore une fois, si vous trouvez un rappel lent, envoyez la tâche à un processus d’arrière-plan ou à un système de file d’attente pour qu’elle soit récupérée par un autre service ultérieurement. J’utilise souvent des emplois dans des systèmes comme Laravel pour gérer de telles tâches. Peut-être ajouter la tâche utilisateur à un File d’attente des tâches Laravel et continuez avec le traitement de l’API.

Enfin, assurez-vous de rester en contact avec vos développeurs susceptibles d’utiliser ces crochets. Il est courant que les développeurs utilisant vos crochets et écrivant des rappels ne soient pas les mêmes personnes qui ont créé le crochet dans l’API pour commencer. Au fur et à mesure que votre API mûrit, vous pourriez commencer à voir des demandes pour ajouter plus de crochets à différents endroits et avec une granularité plus fine. Ils peuvent demander des crochets avant/après qui peuvent être utilisés pour déclencher des actions avant qu’un utilisateur ne soit inséré ainsi qu’après. Ils peuvent également demander que des informations supplémentaires soient transmises à leurs rappels (non seulement leur nom et leur âge, mais également le nouvel identifiant de l’utilisateur inséré, par exemple). Considérez ces demandes comme un bon signe que vos développeurs trouvent le mécanisme utile et voient le potentiel d’étendre l’impact de votre API dans les systèmes connexes. C’est vraiment agréable d’avoir un système qui est si facile à « accrocher » et à exécuter un petit morceau de code pour avoir un impact important.

Avec cette approche, le ciel est la limite de ce que vous pouvez faire faire à votre API. Tout cela peut être réalisé tout en gardant le flux principal de votre point de terminaison clair et exempt de bruit lorsqu’il traite avec d’autres systèmes.

Conclusion

Dans cet article, nous avons discuté de ce que sont les crochets/actions et comment ils pourraient être utilisés. Nous avons donné quelques exemples de code PHP que vous pouvez utiliser dans votre API PHP pour implémenter le « hooking » et comment un rappel pourrait être utilisé pour se lier à ce hook. Nous avons également discuté de l’ajout de crochets au niveau général de l’API (plus globalement pour toutes les requêtes) ainsi que dans les points de terminaison. En plus de cela, nous avons également parlé un peu de certains des inconvénients de ce système et du fait que c’est une bonne idée de garder vos rappels légers et méchants. Mais si vous avez un rappel de longue durée, nous avons mentionné quelques stratégies pour gérer ces processus afin d’éviter qu’ils n’affectent votre pipeline d’API.

Si vous implémentez ce système, vous pouvez également bénéficier de certaines des meilleures fonctionnalités dont la communauté WordPress (et les programmeurs en général) bénéficient depuis des années. Vous vous épargnerez également beaucoup de temps et de maux de tête en ayant à modifier directement votre code API, et vous pourrez vous concentrer sur un petit code de rappel à la place. Vous pouvez également ajouter et supprimer des rappels qui peuvent être des intégrations complètes avec d’autres systèmes. Toutes ces fonctionnalités — et pas une seule fois avoir à republier votre code de pipeline d’API ! C’est une très bonne affaire, non ? Avec ce système, j’ai réussi à faire quelques intégrations simples en une journée, et maintenant vous pouvez le faire aussi.

Merci d’avoir lu!




Source link