{"id":230629,"date":"2022-12-15T11:23:00","date_gmt":"2022-12-15T08:23:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230629"},"modified":"2022-12-17T14:49:40","modified_gmt":"2022-12-17T11:49:40","slug":"wordpress-widgets-refactoring-del-4","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/sv\/wordpress-widgets-refactoring-del-4\/","title":{"rendered":"WordPress-widgets: Refactoring, del 4"},"content":{"rendered":"\n<p>Vi har implementerat en betydande m\u00e4ngd \u00e4ndringar i WordPress Widget Boilerplate. Om du inte har f\u00f6ljt med rekommenderar jag att b\u00f6rja i b\u00f6rjan av serien och komma ikapp.<\/p>\n<p>Om du d\u00e4remot har f\u00f6ljt med och du ocks\u00e5 k\u00f6r n\u00e5gra av kodkvalitetsverktygen som unders\u00f6ker projektets tillst\u00e5nd, kommer du att m\u00e4rka en handfull fel i konsolen.<\/p>\n<p>Normalt \u00e4r det h\u00e4r punkten d\u00e4r jag rekommenderar att du \u00e4r uppm\u00e4rksam p\u00e5 vad den delar och sedan fixar vad den rapporterar, men vi \u00e4r inte d\u00e4r \u00e4n.<\/p>\n<p>Till exempel \u00e4r n\u00e5gra av de fel som v\u00e5ra verktyg visar just nu baserade p\u00e5 att vi har oanv\u00e4nda variabler. Naturligtvis \u00e4r det dock s\u00e5, eftersom vi inte har b\u00f6rjat bygga en widget.<\/p>\n<p>Men det finns fortfarande n\u00e5gra konkreta klasser vi beh\u00f6ver implementera.<\/p>\n<h2>WordPress Widget Boilerplate: Refactoring, del 4<\/h2>\n<p>Ett av problemen som fortfarande finns i koden som den ser ut just nu \u00e4r att widgetens konstruktor registrerar funktioner och det \u00e4r inte bra.<\/p>\n<p>Syftet med en konstruktor \u00e4r att st\u00e4lla in v\u00e4rdena f\u00f6r klassens egenskaper, inte att implementera n\u00e5gon typ av logik. Detta \u00e4r av n\u00e5gra anledningar:<\/p>\n<ul>\n<li>det skapar stark koppling eller beroenden mellan klasser i projektet n\u00e4rhelst en given klass instansieras,<\/li>\n<li>det introducerar aff\u00e4rslogik i en funktion som inte \u00e4r avsedd att inneh\u00e5lla n\u00e4mnda funktionalitet,<\/li>\n<li>det g\u00f6r det sv\u00e5rt att testa en klass isolerat.<\/li>\n<\/ul>\n<p>S\u00e4ttet att hantera detta \u00e4r tv\u00e5delat:<\/p>\n<ol>\n<li>l\u00e4gg till ett register som vi kan anv\u00e4nda f\u00f6r att registrera klasser i applikationen (och skicka dem runt med s\u00e5 f\u00e5 beroenden som m\u00f6jligt, vilket jag ska f\u00f6rklara senare),<\/li>\n<li>skapa abonnenter som kan hantera aff\u00e4rslogiken p\u00e5 en krokspecifik basis.<\/li>\n<\/ol>\n<p>Under de kommande tre inl\u00e4ggen:<\/p>\n<ol>\n<li>vi ska titta p\u00e5 att skapa ett register,<\/li>\n<li>hur vi kan introducera det i bootstrap-filen,<\/li>\n<li>och titta sedan p\u00e5 att skapa prenumeranter f\u00f6r var och en av v\u00e5ra funktioner (vilket inte borde vara alltf\u00f6r sv\u00e5rt med tanke p\u00e5 vad vi gjorde i f\u00f6rra inl\u00e4gget och vad vi g\u00f6r i det h\u00e4r inl\u00e4gget).<\/li>\n<\/ol>\n<h3>Skapa registret<\/h3>\n<p>Innan du skriver koden f\u00f6r registret \u00e4r det viktigt att notera vad dess prim\u00e4ra syfte \u00e4r. Enkelt uttryckt \u00e4r klassen menad att inneh\u00e5lla en referens till vilken klass som helst som \u00e4r, ahem, registrerad med den.<\/p>\n<p>Detta g\u00f6rs genom att skicka en referens till ett givet objekt till en funktion och \u00e4ven binda det till en nyckel s\u00e5 att vi enkelt kan h\u00e4mta det senare.<\/p>\n<h4>Inledande \u00f6verv\u00e4ganden<\/h4>\n<p>Men det finns n\u00e5gra saker att t\u00e4nka p\u00e5. Till exempel:<\/p>\n<p>om ett objekt redan finns i registret f\u00f6r en given nyckel, d\u00e5 m\u00e5ste vi kasta ett undantag &#8211; om en anv\u00e4ndare f\u00f6rs\u00f6ker ta ett objekt fr\u00e5n registret med en given nyckel, s\u00e5 b\u00f6r den kasta ett undantag<\/p>\n<p>Naturligtvis beh\u00f6ver det inte n\u00f6dv\u00e4ndigtvis ge undantag. Ist\u00e4llet kan den ocks\u00e5 visa felmeddelanden, returnera null eller tomma v\u00e4rden, eller vad du \u00e4n v\u00e4ljer.<\/p>\n<p>F\u00f6r det andra m\u00e5ste registret kunna returnera en lista \u00f6ver alla prenumeranter som finns i det s\u00e5 att de kan registreras med WordPress (vilket \u00e4r vad vi kommer att se i n\u00e4sta inl\u00e4gg).<\/p>\n<p>F\u00f6r att g\u00f6ra detta m\u00e5ste vi dock se till att det st\u00f6der alla prenumeranter och det \u00e4r h\u00e4r begreppet abstrakt prenumerant fr\u00e5n <a href=\"https:\/\/wordpress.mediadoma.com\/sv\/wordpress-widgets-refactoring-del-3\/\" title=\"det tidigare inl\u00e4gget\">det tidigare inl\u00e4gget<\/a> kommer in i bilden. Det vill s\u00e4ga, s\u00e5 l\u00e4nge en klass \u00e4r en barnklass i den klassen, s\u00e5 \u00e4r vi okej.<\/p>\n<h4>Skapar registret<\/h4>\n<p>Med det sagt, l\u00e5t oss planera f\u00f6ljande:<\/p>\n<ul>\n<li>Vi skapar en Registry-klass och placerar den i ett Utilities-namnomr\u00e5de (och d\u00e4rmed katalog) om den inte redan finns i ditt arbete.<\/li>\n<li>Vi kommer att l\u00e5ta registret uppr\u00e4tth\u00e5lla en referens till alla dess objekt i en associativ array.<\/li>\n<li>Vi beh\u00f6ver metoder f\u00f6r att <strong>l\u00e4gga<\/strong> till och <strong>f\u00e5<\/strong> en enskild prenumerant och sedan en f\u00f6r att h\u00e4mta listan \u00f6ver hela prenumeranter.<\/li>\n<\/ul>\n<p>Stubben f\u00f6r klassen kommer att se ut ungef\u00e4r <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-00-registry-stub-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">s\u00e5 h\u00e4r:<\/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>D\u00e4refter kan <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-01-registry-constructor-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">vi definiera den grundl\u00e4ggande egenskapen<\/a>, en array, och initiera den i konstruktorn:<\/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>Efter det kan <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-02-registry-add-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">vi skapa add-metoden<\/a>. Kom ih\u00e5g att i min implementering v\u00e4ljer jag att g\u00f6ra ett undantag om en nyckel redan \u00e4r definierad, men du beh\u00f6ver inte g\u00f6ra det.<\/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>P\u00e5 samma s\u00e4tt kommer <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-03-registry-get-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">get-metoden<\/a> att returnera en referens till instansen av ett objekt som identifieras med den nyckeln. Om nyckeln inte \u00e4r inst\u00e4lld kommer det att skapa ett undantag. Om det \u00e4r inst\u00e4llt, men inget objekt existerar, returnerar vi 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>Slutligen beh\u00f6ver vi en metod f\u00f6r att returnera alla registrerade prenumeranter. I ett framtida inl\u00e4gg kommer anv\u00e4ndningen av detta att bli mycket mer uppenbar, men f\u00f6r nu, notera att vi kommer att skapa en array av alla klasser som \u00e4r en instans av klassen <strong>AbstractSubscriber<\/strong> och <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-04-registry-get-subscribers-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">sedan returnerar vi den filtrerade arrayen.<\/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>Vid det h\u00e4r laget har <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-05-registry-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">vi hela klassen<\/a> (komplett med dokumentation):<\/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>Nu m\u00e5ste vi l\u00e4gga till det i bootstrap f\u00f6r v\u00e5rt plugin.<\/p>\n<h2>F\u00f6re Bootstrap, dock<\/h2>\n<p>Som n\u00e4mnts tidigare i inl\u00e4gget m\u00e5ste vi l\u00e4gga till detta till pluginets bootstrap. F\u00f6r att g\u00f6ra detta m\u00e5ste vi dock definiera v\u00e5rt eget filter s\u00e5 att vi enkelt kan skicka registret runt resten av pluginet (n\u00e4r det \u00e4r dags att g\u00f6ra det).<\/p>\n<p>Innan vi g\u00f6r det \u00e4r det dock viktigt att se till att du har ett bra grepp om registret vi just har skapat, att det passar in i pluginet och att du sp\u00e5rar med <a href=\"https:\/\/github.com\/tommcfarlin\/WordPress-Widget-Boilerplate\/tree\/develop\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">utvecklingsgrenen<\/a> som vi har hittills.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Inspelningsk\u00e4lla:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ett problem som fortfarande finns i koden som den ser ut just nu \u00e4r att WordPress-widgetens konstruktor registrerar funktioner och detta \u00e4r inte bra.<\/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":[901,724,868],"tags":[1173],"class_list":["post-230629","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-koda","category-utvecklaren","category-wordpress-9","tag-affiai-sv"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/posts\/230629","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/comments?post=230629"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/posts\/230629\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/media\/223984"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/media?parent=230629"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/categories?post=230629"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/sv\/wp-json\/wp\/v2\/tags?post=230629"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}