{"id":231229,"date":"2022-12-15T11:14:00","date_gmt":"2022-12-15T08:14:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=231229"},"modified":"2022-12-17T14:59:20","modified_gmt":"2022-12-17T11:59:20","slug":"wordpress-widgetit-refaktorointi-osa-4","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/fi\/wordpress-widgetit-refaktorointi-osa-4\/","title":{"rendered":"WordPress-widgetit: Refaktorointi, osa 4"},"content":{"rendered":"\n<p>Olemme tehneet huomattavan m\u00e4\u00e4r\u00e4n muutoksia WordPress Widget Boilerplateen. Jos et ole seurannut, suosittelen aloittamaan sarjan alusta ja kuromaan kiinni.<\/p>\n<p>Jos olet kuitenkin seurannut mukana ja k\u00e4yt\u00e4t my\u00f6s joitain koodinlaatuty\u00f6kaluja, jotka tutkivat projektin tilaa, huomaat konsolissa kourallisen virheit\u00e4.<\/p>\n<p>Normaalisti t\u00e4m\u00e4 on kohta, jossa suosittelen kiinnitt\u00e4m\u00e4\u00e4n huomiota siihen, mit\u00e4 se jakaa, ja korjaamaan sitten sen ilmoittaman, mutta emme ole viel\u00e4 siell\u00e4.<\/p>\n<p>Esimerkiksi jotkut ty\u00f6kalumme t\u00e4ll\u00e4 hetkell\u00e4 n\u00e4ytt\u00e4mist\u00e4 virheist\u00e4 perustuvat siihen, ett\u00e4 meill\u00e4 on k\u00e4ytt\u00e4m\u00e4tt\u00f6mi\u00e4 muuttujia. Tietysti n\u00e4in on kuitenkin, koska emme ole aloittaneet widgetin rakentamista.<\/p>\n<p>Mutta meid\u00e4n on viel\u00e4 toteutettava muutamia konkreettisia luokkia.<\/p>\n<h2>WordPress Widget Boilerplate: Refactoring, osa 4<\/h2>\n<p>Yksi ongelmista, jotka ovat edelleen olemassa koodissa sellaisena kuin se t\u00e4ll\u00e4 hetkell\u00e4 on, on se, ett\u00e4 widgetin rakentaja rekister\u00f6i toimintoja, mik\u00e4 ei ole hyv\u00e4 asia.<\/p>\n<p>Konstruktorin tarkoitus on asettaa luokan ominaisuuksien arvot, ei toteuttaa mink\u00e4\u00e4nlaista logiikkaa. T\u00e4m\u00e4 johtuu muutamista syist\u00e4:<\/p>\n<ul>\n<li>se luo vahvaa kytkent\u00e4\u00e4 tai riippuvuuksia luokkien v\u00e4lille projektissa aina, kun tietty luokka instantoidaan,<\/li>\n<li>se tuo liiketoimintalogiikkaa toimintoon, jonka ei ole tarkoitus sis\u00e4lt\u00e4\u00e4 mainittua toimintoa,<\/li>\n<li>se vaikeuttaa luokan testaamista erikseen.<\/li>\n<\/ul>\n<p>Tapa k\u00e4sitell\u00e4 t\u00e4m\u00e4 on kaksitahoinen:<\/p>\n<ol>\n<li>lis\u00e4\u00e4 rekisteri, jonka avulla voimme rekister\u00f6id\u00e4 luokkia sovelluksessa (ja v\u00e4litt\u00e4\u00e4 ne mahdollisimman v\u00e4hill\u00e4 riippuvuuksilla, jotka selit\u00e4n my\u00f6hemmin),<\/li>\n<li>luoda tilaajia, jotka voivat k\u00e4sitell\u00e4 liiketoimintalogiikkaa koukkukohtaisesti.<\/li>\n<\/ol>\n<p>Kolmen seuraavan postauksen aikana:<\/p>\n<ol>\n<li>harkitsemme rekisterin luomista,<\/li>\n<li>kuinka voimme lis\u00e4t\u00e4 sen bootstrap-tiedostoon,<\/li>\n<li>ja katso sitten tilaajien luomista jokaiselle toiminnollemme (sen ei pit\u00e4isi olla liian vaikeaa ottaen huomioon, mit\u00e4 teimme edellisess\u00e4 viestiss\u00e4 ja mit\u00e4 teemme t\u00e4ss\u00e4 viestiss\u00e4).<\/li>\n<\/ol>\n<h3>Luo rekisteri<\/h3>\n<p>Ennen kuin kirjoitat rekisterin koodin, on t\u00e4rke\u00e4\u00e4 huomata, mik\u00e4 sen ensisijainen tarkoitus on. Yksinkertaisesti sanottuna luokan on tarkoitus sis\u00e4lt\u00e4\u00e4 viittaus mihin tahansa luokkaan, joka on rekister\u00f6ity siihen.<\/p>\n<p>T\u00e4m\u00e4 tehd\u00e4\u00e4n v\u00e4litt\u00e4m\u00e4ll\u00e4 viittaus annettuun objektiin funktiolle ja sitomalla se my\u00f6s avaimeen, jotta voimme helposti hakea sen my\u00f6hemmin.<\/p>\n<h4>Alustavia huomioita<\/h4>\n<p>Mutta joitain asioita on otettava huomioon. Esimerkiksi:<\/p>\n<p>jos objekti on jo olemassa rekisteriss\u00e4 tietylle avaimelle, meid\u00e4n on teht\u00e4v\u00e4 poikkeus &#8211; jos k\u00e4ytt\u00e4j\u00e4 yritt\u00e4\u00e4 napata objektin rekisterist\u00e4 annetulla avaimella, sen pit\u00e4isi heitt\u00e4\u00e4 poikkeus<\/p>\n<p>Poikkeuksia ei tietenk\u00e4\u00e4n v\u00e4ltt\u00e4m\u00e4tt\u00e4 tarvitse tehd\u00e4. Sen sijaan se voi my\u00f6s n\u00e4ytt\u00e4\u00e4 virheilmoituksia, palauttaa nolla- tai tyhji\u00e4 arvoja tai mit\u00e4 tahansa valitsemasi.<\/p>\n<p>Toiseksi rekisterin on voitava palauttaa luettelo kaikista sen sis\u00e4lt\u00e4mist\u00e4 tilaajista, jotta heid\u00e4t voidaan rekister\u00f6id\u00e4 WordPressiin (jonka tulemme n\u00e4kem\u00e4\u00e4n seuraavassa viestiss\u00e4).<\/p>\n<p>T\u00e4t\u00e4 varten meid\u00e4n on kuitenkin varmistettava, ett\u00e4 se tukee kaikkia tilaajia, ja t\u00e4ss\u00e4 tulee <a href=\"https:\/\/wordpress.mediadoma.com\/fi\/wordpress-widgetit-refaktorointi-osa-3\/\" title=\"esiin edellisen viestin\">esiin edellisen viestin<\/a> k\u00e4site AbstractSubscriber. Eli niin kauan kuin luokka on tuon luokan lapsiluokka, olemme kunnossa.<\/p>\n<h4>Rekisterin luominen<\/h4>\n<p>T\u00e4m\u00e4n j\u00e4lkeen suunnitellaan seuraavaa:<\/p>\n<ul>\n<li>Luomme rekisteriluokan ja sijoitamme sen Utilities-nimiavaruuteen (ja siten hakemistoon), jos sit\u00e4 ei viel\u00e4 ole ty\u00f6ss\u00e4si.<\/li>\n<li>Rekisterin pit\u00e4\u00e4 yll\u00e4pit\u00e4\u00e4 viittausta kaikkiin assosiatiivisessa taulukossa oleviin objekteihinsa.<\/li>\n<li>Tarvitsemme menetelmi\u00e4 yksitt\u00e4isen tilaajan <strong>lis\u00e4\u00e4miseksi<\/strong> ja <strong>hankkimiseksi ja sitten yhden kokonaisten tilaajien luettelon hakemiseksi.<\/strong><\/li>\n<\/ul>\n<p>Luokan tynk\u00e4 n\u00e4ytt\u00e4\u00e4 suunnilleen <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-00-registry-stub-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">t\u00e4lt\u00e4:<\/a><\/p>\n<pre><code>&lt;?php\n\nclass Registry extends AbstractSubscriber\n{\n    public function __construct()\n    {\n    }\n\n    public function add($id, $obj)\n    {\n    }\n\n    public function get($id)\n    {\n    }\n\n    public function getRegisteredSubscribers()\n    {\n    }\n}\n<\/code><\/pre>\n<p>Seuraavaksi <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-01-registry-constructor-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">voimme m\u00e4\u00e4ritt\u00e4\u00e4 perusominaisuuden<\/a>, taulukon ja alustaa sen konstruktorissa:<\/p>\n<pre><code>&lt;?php\n\nclass Registry\n{\n    private $registry;\n\n    public function __construct()\n    {\n        $this-&gt;registry = [];\n    }\n\n    \/\/ ...\n\n}<\/code><\/pre>\n<p>T\u00e4m\u00e4n j\u00e4lkeen <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-02-registry-add-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">voimme luoda lis\u00e4ysmenetelm\u00e4n<\/a>. Muista, ett\u00e4 toteutuksessani valitsen poikkeuksen, jos avain on jo m\u00e4\u00e4ritetty, mutta sinun ei tarvitse tehd\u00e4 sit\u00e4.<\/p>\n<pre><code>&lt;?php\n\npublic function add($id, $obj)\n{\n    if (isset($this-&gt;registry[$id])) {\n        throw new Exception('An object already exists for this given key.');\n    }\n    $this-&gt;registry[$id] = $obj;\n}<\/code><\/pre>\n<p>Vastaavasti <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-03-registry-get-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">get-menetelm\u00e4<\/a> palauttaa viittauksen kyseisell\u00e4 avaimella tunnistetun objektin esiintym\u00e4\u00e4n. Jos avainta ei ole asetettu, se tekee poikkeuksen. Jos se on asetettu, mutta objektia ei ole, palautetaan null.<\/p>\n<pre><code>&lt;?php\n\npublic function get($id)\n{\n    if (!isset($this-&gt;registry[$id])) {\n        throw new Exception('No object exists for the specified key.');\n    }\n\n    return $this-&gt;registry[$id] ?? null;\n}<\/code><\/pre>\n<p>Lopuksi tarvitsemme menetelm\u00e4n kaikkien rekister\u00f6ityjen tilaajien palauttamiseksi. Tulevassa viestiss\u00e4 t\u00e4m\u00e4n k\u00e4ytt\u00f6 tulee paljon ilmeisemm\u00e4ksi, mutta toistaiseksi huomaa, ett\u00e4 luomme taulukon mist\u00e4 tahansa luokasta, joka on <strong>AbstractSubscriber<\/strong> &#8211; luokan esiintym\u00e4, ja <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-04-registry-get-subscribers-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">sitten palautamme suodatetun taulukon.<\/a><\/p>\n<pre><code>&lt;?php\n\npublic function getRegisteredSubscribers()\n{\n    $subscribers = [];\n    foreach ($this-&gt;registry as $object) {\n        if ($object instanceof AbstractSubscriber) {\n            $subscribers[] = $object;\n        }\n    }\n\n    return array_filter($subscribers);\n}<\/code><\/pre>\n<p>T\u00e4ss\u00e4 vaiheessa <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-05-registry-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">meill\u00e4 on koko luokka<\/a> (dokumentaatioineen):<\/p>\n<pre><code>&lt;?php\n\n\/*\n * This file is part of the WordPress Widget Boilerplate\n *\n * (c) Tom McFarlin &lt;tom@tommcfarlin.com&gt;\n *\n * This source file is subject to the GPL license that is bundled\n * with this source code in the file LICENSE.\n *\/\n\nnamespace WordPressWidgetBoilerplateUtilities;\n\nuse Exception;\nuse WordPressWidgetBoilerplateSubscriberAbstractSubscriber;\n\n\/**\n * This class services as a simple container that can be used to pass objects\n * around the plugin.\n *\n * To use this class you'd make a call to the registry by saying Registry-&gt;get(),\n * then making a class to `register()` and `retrieve()` on an instance of the object.\n *\/\nclass Registry\n{\n    \/**\n     * @var array an array used to maintain the objects registered with the plugin\n     *\/\n    private $registry;\n\n    \/**\n     * Initializes the class by setting up the registry.\n     *\/\n    public function __construct()\n    {\n        $this-&gt;registry = [];\n    }\n\n    \/**\n     * Registers an object with the registry with the specified ID; however, will throw an\n     * exception if the ID is already referencing an object.\n     *\n     * @param string $id  an ID by which the specified object will be referenced\n     * @param mixed  $obj an instance of an object to store in the registry\n     *\n     * @throws Exception if an object already exists for the specified key\n     *\/\n    public function add($id, $obj)\n    {\n        if (isset($this-&gt;registry[$id])) {\n            throw new Exception('An object already exists for this given key.');\n        }\n        $this-&gt;registry[$id] = $obj;\n    }\n\n    \/**\n     * @param string $id the ID for the object that we wish to retrieve\n     *\n     * @throws Exception if no object exists for the specified key\n     *\n     * @return mixed a reference to the object or null\n     *\/\n    public function get($id)\n    {\n        if (!isset($this-&gt;registry[$id])) {\n            throw new Exception('No object exists for the specified key.');\n        }\n\n        return $this-&gt;registry[$id] ?? null;\n    }\n\n    \/**\n     * @return array all of the the Subscribers that should be registered with WordPress\n     *\/\n    public function getRegisteredSubscribers()\n    {\n        $subscribers = [];\n        foreach ($this-&gt;registry as $object) {\n            if ($object instanceof AbstractSubscriber) {\n                $subscribers[] = $object;\n            }\n        }\n\n        return array_filter($subscribers);\n    }\n}\n<\/code><\/pre>\n<p>Nyt meid\u00e4n on lis\u00e4tt\u00e4v\u00e4 se laajennuksen bootstrapiin.<\/p>\n<h2>Kuitenkin ennen The Bootstrapia<\/h2>\n<p>Kuten aiemmin viestiss\u00e4 mainittiin, meid\u00e4n on lis\u00e4tt\u00e4v\u00e4 t\u00e4m\u00e4 laajennuksen k\u00e4ynnistyspalkkiin. T\u00e4t\u00e4 varten meid\u00e4n on kuitenkin m\u00e4\u00e4ritett\u00e4v\u00e4 oma suodattimemme, jotta voimme helposti siirt\u00e4\u00e4 rekisterin muun laajennuksen ymp\u00e4rille (kun sen aika tulee).<\/p>\n<p>Ennen kuin teemme sen, on kuitenkin t\u00e4rke\u00e4\u00e4 varmistaa, ett\u00e4 sinulla on hyv\u00e4 k\u00e4sitys juuri luomastamme rekisterist\u00e4, ett\u00e4 se sopii laajennukseen ja ett\u00e4 seuraat <a href=\"https:\/\/github.com\/tommcfarlin\/WordPress-Widget-Boilerplate\/tree\/develop\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">kehityshaaraa<\/a>, joka meill\u00e4 on t\u00e4h\u00e4n menness\u00e4.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Yksi ongelma, joka on edelleen olemassa koodissa sellaisena kuin se on t\u00e4ll\u00e4 hetkell\u00e4, on se, ett\u00e4 WordPress-widgetin rakentaja rekister\u00f6i toimintoja, mik\u00e4 ei ole hyv\u00e4 asia.<\/p>\n","protected":false},"author":1,"featured_media":223984,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[719,895,864],"tags":[1166],"class_list":["post-231229","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kehittaejae","category-koodi","category-wordpress-5","tag-affiai-fi"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/posts\/231229","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/comments?post=231229"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/posts\/231229\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/media\/223984"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/media?parent=231229"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/categories?post=231229"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fi\/wp-json\/wp\/v2\/tags?post=231229"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}