Betere API's en bibliotheken schrijven voor WordPress

Het voelt alsof alles wat we aanraken zorgvuldig is ontworpen: websites, telefoons, metrokaarten, enzovoort. Zelfs de dingen die we vroeger als vanzelfsprekend beschouwden: thermostaten, rookmelders en autodashboards krijgen nu een zorgvuldige gebruikerservaring.

Design gaat niet alleen over het uiterlijk en het gevoel: het gaat erom elke manier te overwegen waarop een gebruiker moet communiceren met ons apparaat / gereedschap / scherm / object. 

Dit geldt ook voor programmeren.

(On) ontworpen programmering

Programmeertalen zijn grote, gecompliceerde werelden. Zelfs PHP, dat veel programmeer snobs denkt, is te "gemakkelijk", is eigenlijk een vrij ingewikkelde mix van functies en klassen die zich op zeer inconsistente manieren gedragen. 

De syntaxis, methoden en naamgeving zijn in vele jaren geëvolueerd over miljoenen verschillende gebruikers en toepassingen. De meesten neigen om de onderliggende bouw van internals te wijzen - niet noodzakelijk hoe u het zou willen gebruiken.

Geweldige momenten in API-ontwerp: jQuery

Toen ik in 2006 of later begon met het schrijven van JavaScript, was het een zooitje. Hier is hoe ik een tag met een bepaalde klasse zou vinden en het toen rond de DOM zou kunnen verplaatsen:

var uls = getElementsByTagName ("ul"); var classToSearch = "voedingsmiddelen"; for (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;

Gedaan!

jQuery heeft JavaScript weer leuk gemaakt. Aan het eind van de jaren 2000 was het effect zo dramatisch dat ik me herinner dat mijn vader me vroeg naar 'een of ander ding' waarover hij in de Wall Street Journal las. Maar ondanks het grote effect heeft jQuery geen "nieuwe functies" aan JavaScript toegevoegd. Het kostte alleen de dingen die ontwikkelaars te doen hadden en brak het in echt duidelijke patronen.

In plaats van opnieuw uit te vinden hoe dingen op de pagina te vinden, gebruikten ze wat mensen al wisten: CSS selectors. Toen was het gewoon een kwestie van veel van de gemeenschappelijke acties verzamelen en ze in een paar dozijn functies organiseren. Laten we het vorige voorbeeld opnieuw proberen, nu met jQuery:

var $ li = $ ('
  • Biefstuk
  • '); $ ( "Ul.foods") toevoegen ($ li.);

    In 2006 kocht ik een 680 pagina's tellend boek over Ajax. Met de geweldige API van jQuery werd dat vrijwel vervangen door:

    $ .Post ();

    De WordPress API

    Hoewel API "third-party service" betekent, betekent dit gewoon dat de programmeerinterface met een systeem moet communiceren. Net zoals er een Twitter API of een Facebook API is, is er een WordPress API. U doet geen onbewerkte databasequery's om een ​​bericht te maken, toch? Je gebruikt wp_insert_post.

    Maar veel gaten in het ontwerp pesten de WordPress API. Je zou kunnen gebruiken get_the_title maar get_the_permalink genereert een fout die u gebruikt get_permalink. Hé, als je een decennia lang open-sourceproject hebt waarbij duizenden mensen code en miljoenen gebruikers betrokken zijn: je krijgt wat eigenaardigheden.

    Je kunt jezelf veel tijd besparen door deze eigenaardigheden te maskeren en te schrijven naar de gewoonten en het gedrag van de programmeur waar je voor schrijft (die mogelijk u). Hier kunt u de juiste interface ontwerpen om de plug-ins en thema's die u elke dag doet te programmeren.


    De oplossing

    Om ons werk te versnellen en repetitieve taken te beperken, heb ik bibliotheken gemaakt om de opdrachten en aanpassingen aan te kunnen die ik altijd nodig heb.

    1. Sneltoetsen voor algemene taken

    Neem bijvoorbeeld de bron van de miniatuur van een post. Blijkt dat er geen ingebouwde WordPress-functie is om een ​​miniatuur te bemachtigen op basis van de ID van een bericht (alleen de gehechtheid ID KAART). 

    Wat betekent dat ik mezelf vaak dit doe:

    $ thumb_id = get_post_thumbnail_id (get_the_ID ()); $ src = wp_get_attachment_thumb_url ($ thumb_id); echo '';

    Maar er moet een betere manier zijn!

    functie get_thumbnail_src ($ post) $ thumb_id = get_post_thumbnail_id ($ post); $ src = wp_get_attachment_thumb_url ($ thumb_id); return $ src;  echo '';

    2: onvoorspelbare ingangen, voorspelbare uitvoer

    Veel beter! In feite zul je merken dat je het de hele tijd gebruikt en dan deelt met andere ontwikkelaars in jouw bedrijf. 

    Je vriend heeft problemen hiermee, dus hij roept je op om te debuggen en je ziet:

    echo '';

    Dus het lijkt erop dat hij per ongeluk is gebruikt get_post in plaats van get_the_ID. Je schreeuwt tegen hem. Maar wacht even, waarom niet maak het meer accepterend? 

    Misschien kunnen we onze functie aanpassen zodat het een WP_Post object en geven de gebruiker nog steeds wat ze verwachten. Laten we teruggaan naar die functie:

    functie 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; 

    Dus als ze een sturen WP_Post voorwerp of een array, je functie helpt ze nog steeds om te krijgen wat ze nodig hebben. Dit is een groot deel van een succesvolle API: het verbergen van de rommelige lef. Je zou aparte functies kunnen maken voor get_thumbnail_src_by_post_id en get_thumbnail_src_by_wp_post_object. 

    Voor gecompliceerde transformaties kan het zelfs de voorkeur hebben, maar u kunt de interface vereenvoudigen door een enkele functieroute naar de juiste subroutine te maken. Ongeacht wat de gebruiker verzendt, de functie retourneert consistent een tekenreeks voor de afbeeldingsbron. 

    Laten we doorgaan: wat als ze sturen niets?

    3. Verstandige standaardwaarden

    function 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; 

    We zijn weer vereenvoudigd, zodat de gebruiker geen post hoeft te verzenden of zelfs een bericht-ID. In de loop is alles wat nodig is:

    echo '';

    Onze functie zal standaard de ID van het huidige bericht bevatten. Dit wordt een echt waardevolle functie. Om ervoor te zorgen dat dit goed zal spelen, laten we het in een klasse wikkelen zodat het de globale naamruimte niet vervuilt.

    / * Plugin Name: JaredTools Description: Mijn toolbox voor WordPress-thema's. Auteur: Jared Novack Versie: 0.1 Auteur URI: http://upstatement.com/ * / class JaredsTools public static function 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; 

    En alsjeblieft typ je klasse niet met WP. Ik maak dit een openbare statische functie omdat ik deze overal toegankelijk wil hebben, en deze verandert niet: de invoer of uitvoering verandert de functie of het object niet. 

    De laatste oproep voor deze functie is:

    echo '';

    Ontwerp eerst, later bouwen

    Laten we verder gaan met een meer gecompliceerde behoefte. Wanneer ik plug-ins schrijf, vind ik dat ik altijd verschillende soorten fouten moet genereren en / of berichten moet bijwerken. 

    Maar de op gebeurtenissen gebaseerde syntaxis heeft me altijd dwarsgezeten:

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

    Je ding is bijgewerkt

    ';

    Er zijn veel goede redenen waarom WordPress deze op gebeurtenissen gebaseerde architectuur volgt. Maar het is niet intuïtief, tenzij je wilt zitten en verschillende filters en acties onthouden. 

    Laten we ervoor zorgen dat deze overeenkomst de eenvoudigste use-case is: ik moet een beheerderskennisgeving weergeven. Ik ontwerp deze API graag eerst: waar vind ik de beste manier om naar de functie in mijn code te verwijzen. Ik zou het graag zo willen lezen:

    function thing_that_happens_in_my_plugin ($ post_id, $ value) $ updated = update_post_meta ($ post_id, $ value); if ($ updated) JaredsTools :: show_admin_notice ("Your thing is updated") else JaredsTools :: show_admin_notice ("Fout bij bijwerken van uw zaak", "fout"); 

    Zodra ik het eindpunt heb ontworpen, kan ik aan de ontwerpvereiste voldoen:

    class JaredsTools public static function show_admin_notice ($ message, $ class = 'updated') add_action ('admin_notices', function () gebruik ($ message, $ class) echo '

    '$ Boodschap.'

    '; );

    Veel beter! Nu hoef ik niet al deze extra functies te maken en geen gekke haaknamen te onthouden. Hier gebruik ik PHP anonieme functies (ook wel "sluitingen" genoemd) waarmee we een functie rechtstreeks aan een actie of filter kunnen koppelen. 

    Dit bespaart u een heleboel extra functies rond uw bestanden. De gebruik commando laat ons argumenten van de ouderfunctie doorgeven aan de kindersluiting.

    Wees intuïtief

    Nu roept een andere medewerker je over. Ze weet niet waarom haar admin-melding niet rood wordt:

    JaredsTools :: show_admin_notice ("Fout bij bijwerken van uw zaak", "rood");

    Het is omdat ze "rood" verzendt (wat ze zou verwachten zou de doos rood maken) terwijl ze in feite de naam van de klasse dat triggers rood. Maar waarom zou u het niet eenvoudiger maken??

    openbare statische functie show_notice ($ message, $ class = 'updated') $ class = trim (strtolower ($ class)); if ('geel' == $ class) $ class = 'updated';  if ('red' == $ class) $ class = 'error';  add_action ('admin_notices', function () gebruik ($ text, $ class) echo '

    '. $ tekst. '

    '; );

    We hebben nu geaccepteerd voor meer gebruikerstolerantie waardoor we het gemakkelijker kunnen delen en voor ons wanneer we terugkomen om het over maanden te gebruiken.


    Conclusie

    Na het bouwen van een aantal van deze, zijn hier enkele van de principes die ik heb geleerd om deze echt nuttig te maken voor mijn team en mij.

    1. Ontwerp eerst en laat de bouw van de functie overeenkomen met hoe mensen het willen gebruiken.
    2. Bewaar je toetsenbord! Maak snelkoppelingen voor algemene taken.
    3. Zorg voor verstandige standaardwaarden.
    4. Wees minimaal. Laat uw bibliotheek de verwerking afhandelen.
    5. Wees vergevingsgezind op input, maar nauwkeurig op output.
    6. Dat gezegd hebbende, gebruik zo min mogelijk functieargumenten, vier is een goede max. Daarna zou je er een array van opties van moeten maken.
    7. Organiseer uw bibliotheek in afzonderlijke klassen om verschillende gebieden te behandelen (admin, afbeeldingen, aangepaste berichten, enz.).
    8. Document met voorbeeldcode.

    Bij Upstatement maken onze bibliotheken voor Timber het gemakkelijker om thema's te maken en Jigsaw biedt tijdbesparende snelkoppelingen om elke installatie aan te passen.

    Dankzij de tijdsbesparingen die deze hulpprogramma's bieden, kunnen we meer tijd besteden aan het bouwen van de nieuwe en innovatieve delen van elke site of app. Door de commando's te nemen die anders esoterisch zijn (zoals het toevoegen van een kolom aan de admin-berichtentabellen) en het maken van eenvoudige interfaces: elke ontwerper of ontwikkelaar in ons bedrijf kan elke site volledig aanpassen met dezelfde kracht als een professionele WordPress-ontwikkelaar.