Écrire de meilleures API et bibliothèques pour WordPress

On a l'impression que tout ce que nous touchons est soigneusement conçu: sites Web, téléphones, plans de métro, etc. Même les choses que nous tenions pour acquis: les thermostats, les détecteurs de fumée et les tableaux de bord des voitures bénéficient désormais d'une expérience utilisateur minutieuse..

Le design ne se limite pas à l'aspect et à la convivialité: il s'agit de prendre en compte tous les moyens dont un utilisateur a besoin pour interagir avec notre périphérique / outil / écran / objet. 

Cela vaut aussi pour la programmation.

Programmation (non) conçue

Les langages de programmation sont de grands mondes compliqués. Même PHP, que beaucoup de snobs de programmation jugent trop "facile", est en réalité un mélange assez compliqué de fonctions et de classes qui se comportent de manière très incohérente.. 

La syntaxe, les méthodes et les noms ont évolué au fil des ans pour des millions d'utilisateurs et d'applications différents. La plupart ont tendance à refléter la construction sous-jacente des internes - pas nécessairement comment vous voudriez l'utiliser.

Grands moments dans la conception de l'API: jQuery

Quand j'ai commencé à écrire JavaScript en 2006 ou à peu près, c'était le bordel. Voici comment trouver une balise avec une certaine classe et la déplacer dans le DOM à l'époque:

var uls = getElementsByTagName ("ul"); var classToSearch = "aliments"; pour (var i = 0; i < uls.length; i++)  var classes = uls[i].getClasses(); for (var j = 0; j < classes.length; j++) if (classes[j] == classToSearch) myUL = uls[i];    var $li = document.createElement('li'); $li.innerHTML = 'Steak'; myUL.innerHTML += $li;

Terminé!

jQuery a rendu JavaScript encore plus amusant. À la fin des années 2000, l’effet était si dramatique que je me souviens que mon père m’avait posé des questions sur «quelque chose de superficiel» dont il avait parlé dans le Wall Street Journal. Mais malgré son grand effet, jQuery n'a ajouté aucune "nouvelle fonctionnalité" à JavaScript. Il a simplement fallu ce que les développeurs devaient faire et le décomposer en modèles très clairs.

Plutôt que de réinventer la recherche d'éléments sur la page, ils ont exploité ce que les gens savaient déjà: les sélecteurs CSS. Ensuite, il s’agissait simplement de rassembler un grand nombre d’actions communes et de les organiser en quelques dizaines de fonctions. Essayons à nouveau l'exemple précédent, maintenant avec jQuery:

var $ li = $ ('
  • Steak
  • '); $ ("ul.foods"). append ($ li);

    En 2006, j'ai acheté un livre de 680 pages sur Ajax. Avec la superbe API de jQuery, cela a été remplacé par ceci:

    $ .post ();

    L'API WordPress

    Bien que l’API soit devenue synonyme de "service tiers", elle désigne simplement l’interface de programmation permettant de communiquer avec un système. Tout comme il existe une API Twitter ou Facebook, il existe une API WordPress. Vous ne faites pas de requêtes de base de données brutes pour créer une publication, n'est-ce pas? Tu utilises wp_insert_post.

    Mais de nombreux trous de conception affectent l’API WordPress. Vous pourriez utiliser get_the_title mais get_the_permalink génère une erreur, vous utilisez get_permalink. Hé, quand vous avez un projet open source qui dure depuis des décennies et qui implique du code de milliers de personnes et des millions d’utilisateurs: vous allez avoir des bizarreries.

    Vous pouvez gagner beaucoup de temps en masquant ces bizarreries et en écrivant sur les habitudes et les comportements du programmeur pour lequel vous écrivez (ce qui vous). C’est là que vous pouvez concevoir la bonne interface pour programmer les plugins et les thèmes que vous faites tous les jours..


    La solution

    Pour accélérer notre travail et réduire le nombre de tâches répétitives, j'ai créé des bibliothèques pour gérer les commandes et les personnalisations dont j'ai besoin à tout moment..

    1. Raccourcis pour les tâches courantes

    Prenez, par exemple, la source de la vignette d'un message. Il s'avère qu’il n’existe pas de fonction WordPress intégrée permettant de saisir une vignette en fonction de l’ID du message (uniquement le attachement ID). 

    Ce qui signifie que je me retrouve souvent à faire ceci:

    $ thumb_id = get_post_thumbnail_id (get_the_ID ()); $ src = wp_get_attachment_thumb_url ($ thumb_id); écho '';

    Mais il doit y avoir un meilleur moyen!

    fonction get_thumbnail_src ($ post) $ thumb_id = get_post_thumbnail_id ($ post); $ src = wp_get_attachment_thumb_url ($ thumb_id); return $ src;  écho '';

    2: Entrées imprévisibles, sortie prévisible

    Beaucoup mieux! En fait, vous vous retrouvez à l’utiliser tout le temps, puis à le partager avec d’autres développeurs de votre entreprise.. 

    Votre ami a des problèmes, alors il vous appelle pour déboguer et vous voyez:

    écho '';

    Donc, il semble qu'il a utilisé accidentellement get_post au lieu de get_the_ID. Tu lui cries dessus. Mais attendez une seconde, pourquoi pas le rendre plus tolérant? 

    Peut-être que nous pouvons ajuster notre fonction afin qu’elle puisse prendre WP_Post objet et toujours donner à l'utilisateur ce qu'ils attendent. Revenons à cette fonction:

    fonction get_thumbnail_src ($ post) if (is_object ($ post) && isset ($ post-> ID)) $ post = $ post-> ID;  else if (is_array ($ post) && isset ($ post ['ID'])) $ post = $ post ['ID']];  $ thumb_id = get_post_thumbnail_id ($ post); $ src = wp_get_attachment_thumb_url ($ thumb_id); return $ src; 

    Donc, s'ils envoient un WP_Post objet ou un tableau, votre fonction les aidera quand même à obtenir ce dont ils ont besoin. C'est une partie importante d'une API réussie: cacher les tripes en désordre. Vous pouvez créer des fonctions séparées pour get_thumbnail_src_by_post_id et get_thumbnail_src_by_wp_post_object. 

    En fait, pour des transformations plus complexes, cela peut être préférable, mais vous pouvez simplifier l'interface en ayant un seul chemin de fonction vers le sous-programme approprié. Peu importe ce que l'utilisateur envoie, la fonction renvoie systématiquement une chaîne pour la source de l'image.. 

    Continuons: et s'ils envoyaient rien?

    3. Valeurs par défaut sensibles

    fonction get_thumbnail_src ($ post = false) if (false === $ post) $ post = get_the_ID ();  else if (is_object ($ post) && isset ($ post-> ID)) $ post = $ post-> ID;  else if (is_array ($ post) && isset ($ post ['ID'])) $ post = $ post ['ID']];  $ thumb_id = get_post_thumbnail_id ($ post); $ src = wp_get_attachment_thumb_url ($ thumb_id); return $ src; 

    Nous avons simplifié encore une fois pour que l'utilisateur n'ait pas à envoyer de message ou même une identification de poste. Une fois dans la boucle, tout ce dont vous avez besoin est:

    écho '';

    Notre fonction utilisera par défaut l'ID de l'article en cours. Cela devient une fonction vraiment précieuse. Pour que cela fonctionne correctement, enveloppons-le dans une classe pour ne pas polluer l'espace de noms global..

    / * Nom du plugin: JaredTools Description: Ma boite à outils pour les thèmes WordPress. Auteur: Jared Novack Version: 0.1 URI de l'auteur: http://upstatement.com/ * / class JaredsTools fonction statique publique get_thumbnail_src ($ post = false) if (false === $ post) $ post = get_the_ID () ;  else if (is_object ($ post) && isset ($ post-> ID)) $ post = $ post-> ID;  else if (is_array ($ post) && isset ($ post ['ID'])) $ post = $ post ['ID']];  $ thumb_id = get_post_thumbnail_id ($ post); $ src = wp_get_attachment_thumb_url ($ thumb_id); return $ src; 

    Et S'il vous plaît ne préfixez pas votre classe avec WP. Je fais de cette fonction une fonction statique publique parce que je la veux accessible partout, et cela ne change pas: l'entrée ou l'exécution ne change pas la fonction ou l'objet. 

    Le dernier appel à cette fonction est:

    écho '';

    Concevez d’abord, construisez plus tard

    Passons à un besoin plus compliqué. Quand j'écris des plugins, j'ai toujours besoin de générer différents types d'erreur et / ou de messages de mise à jour.. 

    Mais la syntaxe basée sur les événements m'a toujours causé des problèmes:

    add_action ('admin_notices', 'show_my_notice'); functon show_my_notice () echo '

    Votre truc a été mis à jour

    ';

    Il existe de nombreuses bonnes raisons pour que WordPress respecte cette architecture basée sur des événements. Mais ce n'est pas intuitif, à moins que vous ne souhaitiez vous asseoir et mémoriser différents filtres et actions. 

    Faisons de cette correspondance le cas d'utilisation le plus simple: je dois afficher une notification de l'administrateur. J'aime concevoir cette API en premier lieu, où je trouve le meilleur moyen de faire référence à la fonction dans mon code. Je voudrais qu'il se lise comme ceci:

    fonction thing_that_happens_in_my_plugin ($ post_id, $ value) $ updated = update_post_meta ($ post_id, $ value); if ($ updated) JaredsTools :: show_admin_notice ("Votre objet a été mis à jour") else JaredsTools :: show_admin_notice ("Erreur lors de la mise à jour de votre objet", "erreur"); 

    Une fois que le point final est conçu, je peux répondre à l'exigence de conception:

    class JaredsTools fonction statique publique show_admin_notice ($ message, $ class = 'updated') add_action ('admin_notices', function () use ($ message, $ class) echo '

    ". $ message."

    '; );

    Beaucoup mieux! Maintenant, je n'ai plus besoin de créer toutes ces fonctions supplémentaires ni de me souvenir de noms de hooks insensés. Ici, j'utilise des fonctions anonymes PHP (également appelées "fermetures") qui nous permettent de lier une fonction directement à une action ou à un filtre.. 

    Cela vous évite d'avoir un tas de fonctions supplémentaires flottant autour de vos fichiers. le utilisation commande nous permet de passer des arguments de la fonction parent dans la fermeture de l'enfant.

    Être intuitif

    Maintenant, un autre collègue vous appelle. Elle ne sait pas pourquoi son avis administratif ne devient pas rouge:

    JaredsTools :: show_admin_notice ("Erreur lors de la mise à jour de votre objet", "rouge");

    C’est parce qu’elle envoie «rouge» (ce qui, selon elle, ferait virer la boîte au rouge) alors qu’elle devrait en fait envoyer le nom du classe cette déclencheurs rouge. Mais pourquoi ne pas le rendre plus facile?

    fonction statique publique show_notice ($ message, $ class = 'updated') $ class = trim (strtolower ($ class)); if ('yellow' == $ class) $ class = 'mis à jour';  if ('red' == $ class) $ class = 'error';  add_action ('admin_notices', function () use ($ text, $ class) echo '

    '. $ text. '

    '; );

    Nous avons maintenant accepté une plus grande tolérance de la part des utilisateurs, ce qui facilitera le partage et, pour nous, lorsque nous reviendrons à l'utiliser dans des mois..


    Conclusion

    Après en avoir construit un certain nombre, voici quelques-uns des principes que j'ai appris à les rendre vraiment utiles à mon équipe et à moi-même..

    1. Concevez d’abord et laissez la construction de la fonction correspondre à la manière dont les utilisateurs veulent l’utiliser..
    2. Enregistrez votre clavier! Faire des raccourcis pour les tâches courantes.
    3. Fournir des valeurs par défaut raisonnables.
    4. Soyez minimal. Laissez votre bibliothèque gérer le traitement.
    5. Soyez indulgent à l'entrée, mais précisez à la sortie.
    6. Cela dit, utilisez le moins d'arguments de fonction possible, quatre est un bon max. Après cela, vous devriez en faire un tableau d’options.
    7. Organisez votre bibliothèque en classes séparées pour couvrir différents domaines (admin, images, publications personnalisées, etc.).
    8. Document avec exemple de code.

    Chez Upstatement, nos bibliothèques pour Timber facilitent la création de thèmes et Jigsaw fournit des raccourcis permettant de gagner du temps pour personnaliser chaque installation..

    Les gains de temps fournis par ces outils nous permettent de consacrer plus de temps à la construction des nouvelles parties innovantes de chaque site ou application. En prenant les commandes qui sont autrement ésotériques (comme ajouter une colonne aux tables des postes de l'administrateur) et en faisant des interfaces simples: tout concepteur ou développeur de notre société peut personnaliser chaque site avec la même puissance qu'un développeur WordPress professionnel..