{"id":230162,"date":"2022-12-06T13:02:00","date_gmt":"2022-12-06T10:02:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230162"},"modified":"2022-11-09T20:23:33","modified_gmt":"2022-11-09T17:23:33","slug":"prosty-przewodnik-po-organizacji-zajec-opartych-na-wordpressie","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pl\/prosty-przewodnik-po-organizacji-zajec-opartych-na-wordpressie\/","title":{"rendered":"Prosty przewodnik po organizacji zaj\u0119\u0107 opartych na WordPressie"},"content":{"rendered":"\n<p>Jedn\u0105 z rzeczy, w kt\u00f3re w\u0142o\u017cy\u0142em du\u017co bardziej skoordynowany wysi\u0142ek, prawdopodobnie bardziej ni\u017c kiedykolwiek wcze\u015bniej, jest zarz\u0105dzanie rozdzieleniem problem\u00f3w mi\u0119dzy klasami odpowiedzialnymi za interfejs z WordPressem i tymi odpowiedzialnymi za prac\u0119 z problematyczn\u0105 domen\u0105.<\/p>\n<p>Za\u0142\u00f3\u017cmy na przyk\u0142ad, \u017ce pracujesz nad wtyczk\u0105 i b\u0119dzie ona komunikowa\u0107 si\u0119 z interfejsem API innej firmy. Ponadto ta wtyczka b\u0119dzie r\u00f3wnie\u017c oferowa\u0107 menu, typy post\u00f3w, taksonomie itd. W obszarze administracyjnym WordPress.<\/p>\n<p>S\u0105 tu dwa obszary odpowiedzialno\u015bci:<\/p>\n<ol>\n<li>obszar odpowiedzialny za og\u00f3lne rozwi\u0105zanie problemu,<\/li>\n<li>obszar odpowiedzialny za wsp\u00f3\u0142prac\u0119 z WordPressem.<\/li>\n<\/ol>\n<p>Mo\u017cesz argumentowa\u0107, \u017ce wa\u017cne jest, aby obszary test\u00f3w jednostkowych komunikowa\u0142y si\u0119 z WordPressem, ale wiem te\u017c, \u017ce s\u0105 to wypr\u00f3bowane i prawdziwe interfejsy API, kt\u00f3re maj\u0105 w\u0142asny zestaw test\u00f3w.<\/p>\n<p>Zamiast tego powinni\u015bmy skupi\u0107 si\u0119 na testach jednostkowych i oddzieli\u0107 nasz\u0105 logik\u0119 biznesow\u0105 od WordPressa.<\/p>\n<p>Ale nie o to chodzi w tym po\u015bcie. Zamiast tego chodzi bardziej o spos\u00f3b potencjalnego rozplanowania projektu, gdy jego cz\u0119\u015b\u0107 b\u0119dzie wsp\u00f3\u0142pracowa\u0107 z WordPress.<\/p>\n<p>M\u00f3wi\u0142em o znaczeniu i zaletach przestrzeni nazw w poprzednich postach, aby nie zag\u0142\u0119bia\u0107 si\u0119 zbyt g\u0142\u0119boko w t\u0119 dyskusj\u0119 tutaj.<\/p>\n<p>Zamiast tego interesuje mnie organizowanie plik\u00f3w na poziomie systemu plik\u00f3w i na poziomie przestrzeni nazw, tak aby by\u0142y one wyra\u017anie rozdzielone na ich obszary specjalizacji i aby\u015bmy mogli upewni\u0107 si\u0119, \u017ce, powiedzmy, skupiamy si\u0119 na naszych testach jednostkowych (i innych testowanie) w obszarach, kt\u00f3re s\u0105 najbardziej krytyczne.<\/p>\n<h3>Abstrahowanie metaboks\u00f3w<\/h3>\n<p>Lubi\u0119 si\u0119 upewni\u0107, \u017ce m\u00f3j katalog i struktura plik\u00f3w odzwierciedlaj\u0105 moje przestrzenie nazw. Jasne, pomaga w organizacji plik\u00f3w, ale tak\u017ce w organizacji koncepcyjnej.<\/p>\n<p>Oznacza to, \u017ce je\u015bli mam zamiar pracowa\u0107 z metaboxami, wiem, \u017ce prawdopodobnie znajd\u0119 pliki metabox w katalogu zagnie\u017cd\u017conym w nadrz\u0119dnym katalogu <strong>WordPress<\/strong>, a nast\u0119pnie w podkatalogu <strong>Admin, a nast\u0119pnie w katalogu<\/strong> <strong>MetaBox<\/strong>.<\/p>\n<p>W tym celu, jak m\u00f3g\u0142by wygl\u0105da\u0107 zestaw klas zaprojektowany do pracy z metaboxami, gdyby\u015bmy napisali dla nich kod w spos\u00f3b, kt\u00f3ry mo\u017cna ponownie wykorzysta\u0107? Bior\u0105c pod uwag\u0119 to, co wiemy o metaboksach, wiemy, \u017ce prawdopodobnie b\u0119dziemy potrzebowa\u0107:<\/p>\n<ul>\n<li>klasa abstrakcyjna definiuj\u0105ca typ posta, do kt\u00f3rego b\u0119dzie przypisane ka\u017cde pole meta,<\/li>\n<li>dwie funkcje dla metaboxa \u2013 jedna do zarejestrowania, druga do wy\u015bwietlania tre\u015bci,<\/li>\n<li>katalog zawieraj\u0105cy widok lub prezentacj\u0119 metaboxa,<\/li>\n<li>plik, kt\u00f3ry pos\u0142u\u017cy jako wspomniany widok.<\/li>\n<\/ul>\n<p>Bior\u0105c pod uwag\u0119 powy\u017csze punkty, by\u0107 mo\u017ce struktura katalog\u00f3w wygl\u0105da\u0142aby tak:<\/p>\n<\/p>\n<p>Nast\u0119pnie mamy kod, kt\u00f3ry odzwierciedla t\u0119 struktur\u0119. Oznacza to, \u017ce w naszym katalogu <strong>WordPress<\/strong> mieliby\u015bmy podkatalog <strong>Admin<\/strong>, poniewa\u017c pole meta jest wy\u015bwietlane w obszarze administracyjnym WordPress, i mieliby\u015bmy podkatalog <strong>Widok<\/strong>, kt\u00f3ry zawiera\u0142by plik odpowiedzialny za wy\u015bwietlanie informacji.<\/p>\n<p>To pozostawia nam potrzeb\u0119 stworzenia kilku klas wymienionych powy\u017cej. By\u0107 mo\u017ce abstrakcyjna klasa bazowa <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/2fd7f50706c3f1767dc8b5c2b7deefff#file-00-abstract-metabox-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wygl\u0105da\u0142aby tak:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\n\nnamespace AcmeWordPressAdminMetaBox;\n\nabstract class AbstractMetaBox\n{\n    protected $postType;\n\n    public function __construct()\n    {\n        $this-&gt;postType = 'acme_post_type';\n    }\n\n    abstract public function render();\n    abstract public function display();\n}\n<\/code><\/pre>\n<p>Wtedy konkretna implementacja rozszerzy\u0142aby klas\u0119 i <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/2fd7f50706c3f1767dc8b5c2b7deefff#file-01-acme-meta-box-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">wygl\u0105da\u0142aby tak:<\/a><\/strong><\/p>\n<pre><code>&lt;?php\n\nnamespace AcmeWordPressAdminMetaBox;\n\nclass AcmeMetaBox extends AbstractMetaBox\n{\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function render()\n    {\n        add_meta_box(\n            'acme-product-image',\n            'Product Image',\n            [$this, 'display'],\n            $this-&gt;postType,\n            'side',\n            'default'\n        );\n    }\n\n    \/**\n     * {@inheritdoc}\n     *\/\n    public function display()\n    {\n        include_once plugin_dir_path(__FILE__).'Views\/acme-product-image.php';\n    }\n}\n<\/code><\/pre>\n<p>I wreszcie, widok dla klasy zawiera\u0142by dowolny kod znacznika i szablonu <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/2fd7f50706c3f1767dc8b5c2b7deefff#file-02-acme-product-image-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">do renderowania informacji<\/a><\/strong> :<\/p>\n<pre><code>&lt;div class=\"product-image-metabox\"&gt;\n    &lt;p&gt;\n        &lt;img src=\"&lt;?= esc_html(get_post_meta(get_the_ID(), 'product_image', true)); ?&gt;\" alt=\"&lt;?= esc_attr(get_the_title()); ?&gt;\" \/&gt;\n        &lt;input type=\"text\" value=\"&lt;?= esc_html(get_post_meta(get_the_ID(), 'product_image', true)); ?&gt;\" \/&gt;\n    &lt;\/p&gt;\n&lt;\/div&gt;<\/code><\/pre>\n<p>Daje nam to dok\u0142adnie to, czego potrzebujemy w dobrze zorganizowany spos\u00f3b wielokrotnego u\u017cytku do pracy z metaboxami. Mo\u017cna go r\u00f3wnie\u017c powt\u00f3rzy\u0107 dla takich rzeczy, jak menu, typy post\u00f3w, taksonomie i tak dalej.<\/p>\n<p>Ale robi\u0119 dygresj\u0119.<\/p>\n<h3>S\u0142owo o testowaniu jednostkowym (z PHPUnit)<\/h3>\n<p>Jak wspomnia\u0142em wcze\u015bniej w po\u015bcie, uwa\u017cam, \u017ce wa\u017cne s\u0105 klasy test\u00f3w jednostkowych, kt\u00f3re rozwi\u0105zuj\u0105 problemy unikalne dla naszej przestrzeni problem\u00f3w. Oznacza to, \u017ce musisz poinformowa\u0107 plik konfiguracyjny PHPUnit, aby wykluczy\u0142 pliki oparte na WordPressie.<\/p>\n<p>Zalet\u0105 tego, co przedstawi\u0142em powy\u017cej, jest to, \u017ce staje si\u0119 to trywialnie \u0142atwe. M\u00f3wi\u0105c najpro\u015bciej, mo\u017cesz <strong><a href=\"https:\/\/gist.github.com\/tommcfarlin\/2fd7f50706c3f1767dc8b5c2b7deefff#file-03-phpunit-xml\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">doda\u0107 to<\/a><\/strong> do swojego pliku <strong>phpunit.xml<\/strong> :<\/p>\n<pre><code>&lt;testsuites&gt;\n  &lt;testsuite name=\"Plugin\"&gt;\n    &lt;directory&gt;.\/tests&lt;\/directory&gt;\n    &lt;exclude&gt;.\/tests\/phpunit&lt;\/exclude&gt;\n    &lt;exclude&gt;.\/src\/WordPress&lt;\/exclude&gt;\n  &lt;\/testsuite&gt;\n&lt;\/testsuites&gt;<\/code><\/pre>\n<p>Daje to mo\u017cliwo\u015b\u0107 skupienia si\u0119 na pisaniu test\u00f3w specjalnie dla obszaru problemu, jednocze\u015bnie upewniaj\u0105c si\u0119, \u017ce piszesz skalowalny, \u0142atwy w utrzymaniu i wielokrotnego u\u017cytku kod oparty na WordPressie.<\/p>\n<p>Obecnie pisz\u0119 e-booka (wraz z wieloma innymi tre\u015bciami premium). Je\u015bli jeste\u015b zainteresowany, <a href=\"https:\/\/tommcfarlin.com\/registration-info\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">sprawd\u017a co otrzymujesz<\/a>.<\/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>Porz\u0105dkowanie kodu dla klas opartych na WordPressie pomaga nam bardziej skoncentrowa\u0107 si\u0119 na naszej domenie zar\u00f3wno pod k\u0105tem rozwi\u0105zania problemu, jak i pisania test\u00f3w jednostkowych.<\/p>\n","protected":false},"author":1,"featured_media":236089,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[721],"tags":[1169],"class_list":["post-230162","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-deweloper","tag-affiai-pl"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230162","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=230162"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/posts\/230162\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media\/236089"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/media?parent=230162"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/categories?post=230162"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pl\/wp-json\/wp\/v2\/tags?post=230162"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}