{"id":230644,"date":"2022-12-17T14:58:00","date_gmt":"2022-12-17T11:58:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230644"},"modified":"2022-12-17T14:59:29","modified_gmt":"2022-12-17T11:59:29","slug":"widzety-wordpress-refaktoryzacja-czesc-3","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pl\/widzety-wordpress-refaktoryzacja-czesc-3\/","title":{"rendered":"Wid\u017cety WordPress: Refaktoryzacja, cz\u0119\u015b\u0107 3"},"content":{"rendered":"\n<p>Je\u015bli chodzi o aktualizacj\u0119 WordPress Widget Boilerplate (wszystko to jest \u015bledzone w <a href=\"https:\/\/github.com\/tommcfarlin\/WordPress-Widget-Boilerplate\/tree\/develop\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">ga\u0142\u0119zi<\/a> deweloperskiej), przeszli\u015bmy d\u0142ug\u0105 drog\u0119, je\u015bli chodzi o refaktoryzacj\u0119 tego, jak jest zorganizowany.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-161272-61e71e5eea22f.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-161272-61e71e5eea22f.png\" alt=\"Wid\u017cety WordPress: Refaktoryzacja, cz\u0119\u015b\u0107 3\"><\/a><\/p>\n<p>Do tej pory mamy:<\/p>\n<ul>\n<li>przyjrza\u0142 si\u0119, jak <a href=\"https:\/\/wordpress.mediadoma.com\/pl\/widzety-wordpress-podejscie-obiektowe\/\" title=\"WordPress Widget API stanowi przyk\u0142ad\">WordPress Widget API stanowi przyk\u0142ad<\/a> programowania obiektowego,<\/li>\n<li>jak mo\u017cemy wykorzysta\u0107 to API <a href=\"https:\/\/wordpress.mediadoma.com\/pl\/widzety-wordpress-wykrywanie-programowania-obiektowego\/\" title=\"do okre\u015blenia programowania obiektowego\">do okre\u015blenia programowania obiektowego<\/a> w innych obszarach WordPressa,<\/li>\n<li>zainstalowane <a href=\"https:\/\/wordpress.mediadoma.com\/pl\/widzety-wordpress-zaczynajac-od-standardow\/\" title=\"narz\u0119dzia, kt\u00f3re pomog\u0105 nam oceni\u0107 jako\u015b\u0107\">narz\u0119dzia, kt\u00f3re pomog\u0105 nam oceni\u0107 jako\u015b\u0107<\/a> kodu,<\/li>\n<li><a href=\"https:\/\/wordpress.mediadoma.com\/pl\/widzety-wordpress-refaktoryzacja-czesc-1\/\" title=\"znalaz\u0142em b\u0142\u0119dy, kt\u00f3re obecnie istniej\u0105 w kodzie\">znalaz\u0142em b\u0142\u0119dy, kt\u00f3re obecnie istniej\u0105 w kodzie<\/a> pod k\u0105tem wsp\u00f3\u0142czesnych standard\u00f3w programowania,<\/li>\n<li>i rozpocz\u0119li\u015bmy reorganizacj\u0119 bazy kodu tak, aby pasowa\u0142a do <a href=\"https:\/\/wordpress.mediadoma.com\/pl\/widzety-wordpress-refaktoryzacja-czesc-2\/\" title=\"bardziej nowoczesnych praktyk\">bardziej nowoczesnych praktyk<\/a>.<\/li>\n<\/ul>\n<p>Teraz jeste\u015bmy gotowi do rozpocz\u0119cia refaktoryzacji tego kodu w znacznie bardziej zorientowany obiektowo spos\u00f3b.<\/p>\n<p>Wi\u0119c je\u015bli jeszcze nie nadrobi\u0142e\u015b poprzednich post\u00f3w (naprawd\u0119 kt\u00f3rykolwiek z nich), polecam to zrobi\u0107, poniewa\u017c uaktualnienie tego zajmie troch\u0119 czasu. Jest du\u017co kodu do napisania wyja\u015bnienia.<\/p>\n<p>Zacznijmy.<\/p>\n<h2>WordPress Widget Boilerplate: Refaktoryzacja, cz\u0119\u015b\u0107 3<\/h2>\n<p>Prawdopodobnie najwi\u0119kszym problemem zwi\u0105zanym z Boilerplate jest to, \u017ce wszystko jest zamkni\u0119te w jednej klasie.<\/p>\n<p>Jasne, jest kilka fajnych rzeczy, takich jak oddzielanie naszych pogl\u0105d\u00f3w od logiki po stronie serwera, ale to wszystko.<\/p>\n<p>Inne problemy, kt\u00f3re pojawiaj\u0105 si\u0119 tylko z samego patrzenia na kod, to:<\/p>\n<ul>\n<li>dodawanie akcji i filtr\u00f3w w konstruktorze,<\/li>\n<li>posiadanie metod robi\u0105cych wi\u0119cej ni\u017c jedn\u0105 rzecz,<\/li>\n<li>brak klas odpowiedzialnych za implementacj\u0119 takich rzeczy jak rejestracja zale\u017cno\u015bci,<\/li>\n<li>i tak dalej.<\/li>\n<\/ul>\n<p>W tym po\u015bcie zamierzamy rozpocz\u0105\u0107 proces tworzenia abstrakcji, kt\u00f3re ostatecznie zaimplementujemy, aby prze\u0142ama\u0107 bosk\u0105 natur\u0119 Boilerplate w obecnej formie.<\/p>\n<p>Zostanie to podzielone na kilka post\u00f3w, abym m\u00f3g\u0142 przedstawi\u0107 solidne wyja\u015bnienie, dlaczego robimy pewne rzeczy, kt\u00f3re robimy, a tak\u017ce wyja\u015bni\u0107 przyk\u0142ady, kt\u00f3re za tym stoj\u0105.<\/p>\n<p>Je\u015bli zrobi\u0119 to w inny spos\u00f3b, seria pomija zbyt wiele cennych informacji, kt\u00f3re mo\u017cna zastosowa\u0107 w innych praktykach programowania obiektowego.<\/p>\n<h3>Kim jest subskrybent?<\/h3>\n<p>System podpi\u0119\u0107 WordPressa \u2013 czyli dost\u0119pne akcje i filtry \u2013 opiera si\u0119 na wzorcu projektowym opartym na zdarzeniach. Oznacza to, \u017ce za ka\u017cdym razem, gdy co\u015b si\u0119 wydarzy, wydarzenie, WordPress uruchomi dowolny inny kod, kt\u00f3ry zasubskrybowa\u0142 to wydarzenie.<\/p>\n<p>Wi\u0119c kiedy rejestrujemy funkcj\u0119 z hakiem<strong>,<\/strong> <strong>subskrybujemy<\/strong> zdarzenie. W tym celu jestem fanem tworzenia subskrybent\u00f3w dla dowolnego haka, kt\u00f3rego b\u0119dziemy potrzebowa\u0107.<\/p>\n<p>Co wi\u0119cej, abonenci zazwyczaj stosuj\u0105 sp\u00f3jny format. Oznacza to, \u017ce naprawd\u0119 \u0142atwo jest utworzy\u0107 klas\u0119 abstrakcyjn\u0105, kt\u00f3ra implementuje cz\u0119\u015b\u0107 sp\u00f3jnych funkcji, a nast\u0119pnie pozwala klasie implementuj\u0105cej klas\u0119 abstrakcyjn\u0105 skupi\u0107 si\u0119 wy\u0142\u0105cznie na logice biznesowej.<\/p>\n<p>Jednym z naj\u0142atwiejszych sposob\u00f3w, aby to zademonstrowa\u0107, jest subskrybowanie plik\u00f3w CSS i plik\u00f3w JavaScript, poniewa\u017c s\u0105 to dwie najcz\u0119stsze rzeczy, kt\u00f3rych u\u017cywamy podczas tworzenia wtyczek.<\/p>\n<h3>Tworzenie klasy abstrakcyjnej<\/h3>\n<p>Zanim zaimplementujemy klas\u0119 abstrakcyjn\u0105, przedstawmy dok\u0142adnie, co zamierzamy zrobi\u0107, aby to stworzy\u0107.<\/p>\n<ol>\n<li>Potrzebujemy w\u0142a\u015bciwo\u015bci, kt\u00f3ra reprezentuje wydarzenie, kt\u00f3re subskrybujemy.<\/li>\n<li>Potrzebujemy funkcji uruchamiaj\u0105cej si\u0119 za ka\u017cdym razem, gdy podpi\u0119cie jest uruchamiane przez WordPress. Innym sposobem my\u015blenia o tym jest to, \u017ce potrzebujemy funkcji do zaimplementowania za ka\u017cdym razem, gdy dana akcja lub filtr jest uruchamiany przez WordPress.<\/li>\n<li>Potrzebujemy klas, aby zaimplementowa\u0107 abstrakcj\u0119.<\/li>\n<\/ol>\n<p>Najpierw zdefiniujmy klasy abstrakcyjne. <a href=\"https:\/\/secure.php.net\/manual\/en\/language.oop5.abstract.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Wprost z podr\u0119cznika PHP<\/a> czytamy:<\/p>\n<blockquote>\n<p>Klasy zdefiniowane jako abstrakcyjne nie mog\u0105 by\u0107 tworzone, a ka\u017cda klasa, kt\u00f3ra zawiera co najmniej jedn\u0105 metod\u0119 abstrakcyjn\u0105, musi by\u0107 r\u00f3wnie\u017c abstrakcyjna. Metody zdefiniowane jako abstrakcyjne po prostu deklaruj\u0105 sygnatur\u0119 metody \u2013 nie mog\u0105 definiowa\u0107 implementacji.<\/p>\n<\/blockquote>\n<p>W skr\u00f3cie oznacza to, \u017ce nie mo\u017cemy w rzeczywisto\u015bci stworzy\u0107 instancji klasy abstrakcyjnej. Mo\u017cemy jedynie tworzy\u0107 instancje klas, kt\u00f3re definiuj\u0105 implementacj\u0119.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-161272-61e71e62f02d2.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-161272-61e71e62f02d2.png\" alt=\"Wid\u017cety WordPress: Refaktoryzacja, cz\u0119\u015b\u0107 3\"><\/a><\/p>\n<p>Nie oznacza to jednak, \u017ce klasa abstrakcyjna nie mo\u017ce implementowa\u0107 konkretnych rzeczy (takich jak definicja haka). Ale oznacza to, \u017ce istniej\u0105 pewne metody, kt\u00f3re nie maj\u0105 implementacji.<\/p>\n<p>W przeciwnym razie zostaje nam tylko podstawowa klasa.<\/p>\n<p>Ma sens? Sp\u00f3jrzmy.<\/p>\n<h3>Tworzenie klasy abstrakcyjnej<\/h3>\n<p>W tym po\u015bcie stworzymy klas\u0119 abstrakcyjn\u0105 specjalnie dla plik\u00f3w CSS i JavaScript.<\/p>\n<p>Pami\u0119taj, poniewa\u017c jest to klasa abstrakcyjna, konkretni subskrybenci mog\u0105 by\u0107 nazwani czym\u015b, co identyfikuje ich dzia\u0142anie (czyli mog\u0105 nazywa\u0107 siebie wszystkim, co reprezentuje ich cel). I do tego dojdziemy.<\/p>\n<p>Ale najpierw <a href=\"https:\/\/gist.github.com\/tommcfarlin\/9cf10f4aadbe54f2fc2e87b619a33bcc#file-00-abstract-subscriber-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">klasa abstrakcyjna.<\/a> Podziel\u0119 si\u0119 kodem, a nast\u0119pnie wyja\u015bni\u0119 dok\u0142adnie, co si\u0119 z nim dzieje:<\/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 WordPressWidgetBoilerplateSubscriber;\n\n\/**\n * An abstract implementation of a subscriber that requires a hook and the ability to\n * start the class.\n *\/\nabstract class AbstractSubscriber\n{\n    \/**\n     * @var string a reference to the hook to which the subscriber should be registered\n     *\/\n    protected $hook;\n\n    \/**\n     * @param string $hook the hook to which the subscriber is registered\n     *\/\n    public function __construct(string $hook)\n    {\n        $this-&gt;hook = $hook;\n    }\n\n    \/**\n     * @return string the hook to which the subscriber is registered\n     *\/\n    public function getHook(): string\n    {\n        return $this-&gt;hook;\n    }\n\n    \/**\n     * Implements the domain logic for the concrete class implementating this subcriber.\n     *\/\n    abstract public function load();\n}\n<\/code><\/pre>\n<ol>\n<li>Zauwa\u017c, \u017ce utworzona przez nas w\u0142a\u015bciwo\u015b\u0107 jest <strong>chroniona<\/strong>. Dzieje si\u0119 tak, aby klasy implementuj\u0105ce mia\u0142y do \u200b\u200bniego dost\u0119p, ale nic poza nim nie.<\/li>\n<li>Stworzy\u0142em funkcj\u0119 do pobierania haka, kt\u00f3ra stanie si\u0119 widoczna p\u00f3\u017aniej. Zazwyczaj nienawidz\u0119 implementowania funkcjonalno\u015bci, kt\u00f3ra nie jest od razu oczywista, ale jest to co\u015b wa\u017cnego, bior\u0105c pod uwag\u0119, dok\u0105d zmierzamy.<\/li>\n<li>Istnieje funkcja abstrakcyjna o nazwie <strong>load<\/strong>. W tym miejscu ka\u017cda klasa, kt\u00f3ra implementuje t\u0119 funkcj\u0119, b\u0119dzie zawiera\u0142a swoj\u0105 logik\u0119 biznesow\u0105, jak zobaczymy za chwil\u0119.<\/li>\n<li>Lubi\u0119 dokumentowa\u0107 przeznaczenie funkcji, gdy jest to konieczne, aby by\u0142y w jednym miejscu, a nast\u0119pnie pozwoli\u0107 klasom implementuj\u0105cym dostarczy\u0107 dokumentacj\u0119, kt\u00f3r\u0105 musz\u0105 dostarczy\u0107 podczas ich implementacji. Za chwil\u0119 to te\u017c zobaczysz.<\/li>\n<\/ol>\n<p>Teraz, gdy mamy ju\u017c klas\u0119 abstrakcyjn\u0105, ostatni\u0105 rzecz\u0105, kt\u00f3r\u0105 musimy zrobi\u0107, to upewni\u0107 si\u0119, \u017ce jest ona umieszczona we w\u0142a\u015bciwym katalogu i w przestrzeni nazw. Je\u015bli \u015bledzi\u0142e\u015b, zaczynaj\u0105c od poprzedniego posta, prawdopodobnie mog\u0142e\u015b odgadn\u0105\u0107, gdzie b\u0119dzie si\u0119 znajdowa\u0107, na podstawie przestrzeni nazw w kodzie.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-161272-61e71e66e7d4a.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-161272-61e71e66e7d4a.png\" alt=\"Wid\u017cety WordPress: Refaktoryzacja, cz\u0119\u015b\u0107 3\"><\/a><\/p>\n<p>A je\u015bli nie, nie martw si\u0119. Ustalenie przestrzeni nazw i tego, co nie, mo\u017ce zaj\u0105\u0107 troch\u0119 czasu. Mam wi\u0119c nadziej\u0119, \u017ce dzi\u0119ki tym wpisom cz\u0142onkowskim i przyk\u0142adom stanie si\u0119 to jasne z czasem.<\/p>\n<h3>Tworzenie klas betonu<\/h3>\n<p>Teraz zaimplementujmy t\u0119 konkretn\u0105 klas\u0119, aby doda\u0107 oba arkusze styl\u00f3w i \u017ar\u00f3d\u0142a JavaScript, kt\u00f3re posiadamy. Zauwa\u017cysz jednak, \u017ce s\u0105 bardzo podobne.<\/p>\n<p>Jedyn\u0105 r\u00f3\u017cnic\u0105 jest implementacja funkcji <strong>\u0142adowania<\/strong>, kt\u00f3ra dok\u0142adnie tak powinna dzia\u0142a\u0107.<\/p>\n<h5>Arkusze styl\u00f3w<\/h5>\n<p>Bior\u0105c pod uwag\u0119 powy\u017csz\u0105 klas\u0119 abstrakcyjn\u0105, teraz musimy stworzy\u0107 klas\u0119 do rejestracji arkuszy styl\u00f3w. Poniewa\u017c mamy dwa arkusze styl\u00f3w, stworzymy dwie klasy:<\/p>\n<ol>\n<li>pierwsza klasa b\u0119dzie odpowiedzialna za rejestracj\u0119 arkusza styl\u00f3w dla dashboardu, a konkretnie dla strony wid\u017cetu WordPress,<\/li>\n<li>druga klasa b\u0119dzie odpowiedzialna za rejestracj\u0119 wtyczki do w\u0142a\u015bciwego bloga.<\/li>\n<\/ol>\n<p>Wywo\u0142ajmy odpowiednio ka\u017cdy z tych <strong>AdminStylesheetSubscriber<\/strong> i <strong>PublicStylesheetSubscriber<\/strong>.<\/p>\n<p>Po pierwsze, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/9cf10f4aadbe54f2fc2e87b619a33bcc#file-03-admin-style-subscriber-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">subskrybent arkusza styl\u00f3w administratora<\/a> :<\/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?\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 WordPressWidgetBoilerplateSubscriber;\n\n\/**\n * The subscriber responsible for loading the stylesheet on the Widget administration page.\n *\/\nclass AdminStyleAssetSubscriber extends AbstractSubscriber\n{\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function __construct(string $hook)\n    {\n        parent::__construct($hook);\n    }\n\n    \/**\n     * Adds the administrative stylesheet to the widget administration page.\n     *\/\n    public function load()\n    {\n        if ('widgets' !== get_current_screen()-&gt;id) {\n            return;\n        }\n\n        wp_enqueue_style(\n            'wordpress-widget-boilerplate',\n            plugin_dir_url(dirname(__DIR__)).'assets\/css\/admin.css'\n        );\n    }\n}\n<\/code><\/pre>\n<p>Zauwa\u017c, \u017ce u\u017cywa to funkcji <a href=\"https:\/\/codex.wordpress.org\/Function_Reference\/get_current_screen\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">get_current_screen()<\/a>, kt\u00f3rej u\u017cywa\u0142em w poprzednich postach, aby upewni\u0107 si\u0119, \u017ce dodajemy zale\u017cno\u015bci tylko tam, gdzie jest to konieczne.<\/p>\n<p>Teraz <a href=\"https:\/\/gist.github.com\/tommcfarlin\/9cf10f4aadbe54f2fc2e87b619a33bcc#file-05-public-style-subscriber-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">publiczny subskrybent JavaScript<\/a>. U\u017cywa funkcji <a href=\"https:\/\/codex.wordpress.org\/Function_Reference\/is_admin\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">is_admin()<\/a>, aby upewni\u0107 si\u0119, \u017ce nie znajdujemy si\u0119 w obszarze administracyjnym WordPressa.<\/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 WordPressWidgetBoilerplateSubscriber;\n\n\/**\n * The subscriber responsible for loading the stylesheet on the blog.\n *\/\nclass PublicStyleAssetSubscriber extends AbstractSubscriber\n{\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function __construct(string $hook)\n    {\n        parent::__construct($hook);\n    }\n\n    \/**\n     * Adds the stylesheet to the public-facing side of the site.\n     *\/\n    public function load()\n    {\n        if (is_admin()) {\n            return;\n        }\n\n        wp_enqueue_style(\n            'wordpress-widget-boilerplate',\n            plugin_dir_url(dirname(__DIR__)).'assets\/css\/widget.css'\n        );\n    }\n}\n<\/code><\/pre>\n<p>Oczywi\u015bcie musimy jeszcze utworzy\u0107 instancj\u0119 tych klas. To nadejdzie w dalszej cz\u0119\u015bci serii.<\/p>\n<h5>JavaScript<\/h5>\n<p>Jak mo\u017cna si\u0119 domy\u015bli\u0107, subskrybenci JavaScript nie r\u00f3\u017cni\u0105 si\u0119 zbytnio. Oddzielimy je w zale\u017cno\u015bci od obszaru aplikacji, na kt\u00f3rym si\u0119 skupiaj\u0105, i odpowiednio je nazwiemy.<\/p>\n<p>Po pierwsze, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/9cf10f4aadbe54f2fc2e87b619a33bcc#file-02-admin-script-subscriber-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">subskrybent JavaScript administratora<\/a> :<\/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 WordPressWidgetBoilerplateSubscriber;\n\n\/**\n * The subscriber responsible for loading the JavaScript on the Widget's adminsitration page.\n *\/\nclass AdminScriptAssetSubscriber extends AbstractSubscriber\n{\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function __construct(string $hook)\n    {\n        parent::__construct($hook);\n    }\n\n    \/**\n     * Adds the administrative JavaScript to the widget administration page.\n     *\/\n    public function load()\n    {\n        if ('widgets' !== get_current_screen()-&gt;id) {\n            return;\n        }\n\n        wp_enqueue_script(\n            'wordpress-widget-boilerplate',\n            plugin_dir_url(dirname(__DIR__)).'assets\/js\/admin.js'\n        );\n    }\n}\n<\/code><\/pre>\n<p>Oraz <a href=\"https:\/\/gist.github.com\/tommcfarlin\/9cf10f4aadbe54f2fc2e87b619a33bcc#file-04-public-script-subscriber-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">publiczny subskrybent JavaScript:<\/a><\/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 WordPressWidgetBoilerplateSubscriber;\n\n\/**\n * The subscriber responsible for loading the JavaScript on the blog.\n *\/\nclass PublicScriptAssetSubscriber extends AbstractSubscriber\n{\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function __construct(string $hook)\n    {\n        parent::__construct($hook);\n    }\n\n    \/**\n     * Adds the JavaScript to the public-facing side of the site.\n     *\/\n    public function load()\n    {\n        if (is_admin()) {\n            return;\n        }\n\n        wp_enqueue_script(\n            'wordpress-widget-boilerplate',\n            plugin_dir_url(dirname(__DIR__)).'assets\/js\/widget.js'\n        );\n    }\n}\n<\/code><\/pre>\n<p>Ponownie, tych klas nie mo\u017cna jeszcze utworzy\u0107, ale skupimy si\u0119 na tym w nadchodz\u0105cym po\u015bcie.<\/p>\n<h2>Abstrakcje i interfejsy<\/h2>\n<p>Pami\u0119taj, \u017ce abstrakcje i interfejsy s\u0105 r\u00f3\u017cne, ale \u0142atwo je pomyli\u0107. Interfejsy zawieraj\u0105 absolutnie zerow\u0105 implementacj\u0119. Zamiast tego zapewniaj\u0105 gwarancj\u0119, \u017ce ka\u017cda klasa, kt\u00f3ra implementuje interfejs, zaimplementuje wszystkie metody.<\/p>\n<p>Z drugiej strony, klasy abstrakcyjne mog\u0105 mie\u0107 pewne funkcjonalno\u015bci zaimplementowane w klasie abstrakcyjnej, pozostawiaj\u0105c kod specyficzny dla domeny \u2013 taki jak \u0142adowanie arkuszy styl\u00f3w i JavaScript \u2013 do odpowiedniej metody.<\/p>\n<p>Stanie si\u0119 to widoczne, je\u015bli jeszcze tego nie zrobi\u0142o, im dalej wejdziemy w t\u0119 seri\u0119. W mi\u0119dzyczasie \u2013 i jak zwykle \u2013 nie zapomnij zajrze\u0107 do ga\u0142\u0119zi <a href=\"https:\/\/github.com\/tommcfarlin\/WordPress-Widget-Boilerplate\/tree\/develop\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">deweloperskiej<\/a>, aby zobaczy\u0107, na czym stoimy z kodem.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">\u0179r\u00f3d\u0142o nagrywania:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Prawdopodobnie najwi\u0119kszym problemem zwi\u0105zanym z Boilerplate jest to, \u017ce wszystko jest zamkni\u0119te w jednej klasie. Zmie\u0144my to wi\u0119c za pomoc\u0105 klas abstrakcyjnych.<\/p>\n","protected":false},"author":1,"featured_media":235804,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[721,805,836,866],"tags":[1169],"class_list":["post-230644","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-deweloper","category-php-7","category-przewodnik-dla-poczatkujacych","category-wordpress-7","tag-affiai-pl"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230644","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/comments?post=230644"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230644\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media\/235804"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media?parent=230644"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/categories?post=230644"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/tags?post=230644"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}