Prosty przewodnik po organizacji zajęć opartych na WordPressie
Jedną z rzeczy, w które włożyłem dużo bardziej skoordynowany wysiłek, prawdopodobnie bardziej niż kiedykolwiek wcześniej, jest zarządzanie rozdzieleniem problemów między klasami odpowiedzialnymi za interfejs z WordPressem i tymi odpowiedzialnymi za pracę z problematyczną domeną.
Załóżmy na przykład, że pracujesz nad wtyczką i będzie ona komunikować się z interfejsem API innej firmy. Ponadto ta wtyczka będzie również oferować menu, typy postów, taksonomie itd. W obszarze administracyjnym WordPress.
Są tu dwa obszary odpowiedzialności:
- obszar odpowiedzialny za ogólne rozwiązanie problemu,
- obszar odpowiedzialny za współpracę z WordPressem.
Możesz argumentować, że ważne jest, aby obszary testów jednostkowych komunikowały się z WordPressem, ale wiem też, że są to wypróbowane i prawdziwe interfejsy API, które mają własny zestaw testów.
Zamiast tego powinniśmy skupić się na testach jednostkowych i oddzielić naszą logikę biznesową od WordPressa.
Ale nie o to chodzi w tym poście. Zamiast tego chodzi bardziej o sposób potencjalnego rozplanowania projektu, gdy jego część będzie współpracować z WordPress.
Mówiłem o znaczeniu i zaletach przestrzeni nazw w poprzednich postach, aby nie zagłębiać się zbyt głęboko w tę dyskusję tutaj.
Zamiast tego interesuje mnie organizowanie plików na poziomie systemu plików i na poziomie przestrzeni nazw, tak aby były one wyraźnie rozdzielone na ich obszary specjalizacji i abyśmy mogli upewnić się, że, powiedzmy, skupiamy się na naszych testach jednostkowych (i innych testowanie) w obszarach, które są najbardziej krytyczne.
Abstrahowanie metaboksów
Lubię się upewnić, że mój katalog i struktura plików odzwierciedlają moje przestrzenie nazw. Jasne, pomaga w organizacji plików, ale także w organizacji koncepcyjnej.
Oznacza to, że jeśli mam zamiar pracować z metaboxami, wiem, że prawdopodobnie znajdę pliki metabox w katalogu zagnieżdżonym w nadrzędnym katalogu WordPress, a następnie w podkatalogu Admin, a następnie w katalogu MetaBox.
W tym celu, jak mógłby wyglądać zestaw klas zaprojektowany do pracy z metaboxami, gdybyśmy napisali dla nich kod w sposób, który można ponownie wykorzystać? Biorąc pod uwagę to, co wiemy o metaboksach, wiemy, że prawdopodobnie będziemy potrzebować:
- klasa abstrakcyjna definiująca typ posta, do którego będzie przypisane każde pole meta,
- dwie funkcje dla metaboxa – jedna do zarejestrowania, druga do wyświetlania treści,
- katalog zawierający widok lub prezentację metaboxa,
- plik, który posłuży jako wspomniany widok.
Biorąc pod uwagę powyższe punkty, być może struktura katalogów wyglądałaby tak:
Następnie mamy kod, który odzwierciedla tę strukturę. Oznacza to, że w naszym katalogu WordPress mielibyśmy podkatalog Admin, ponieważ pole meta jest wyświetlane w obszarze administracyjnym WordPress, i mielibyśmy podkatalog Widok, który zawierałby plik odpowiedzialny za wyświetlanie informacji.
To pozostawia nam potrzebę stworzenia kilku klas wymienionych powyżej. Być może abstrakcyjna klasa bazowa wyglądałaby tak:
<?php
namespace AcmeWordPressAdminMetaBox;
abstract class AbstractMetaBox
{
protected $postType;
public function __construct()
{
$this->postType = 'acme_post_type';
}
abstract public function render();
abstract public function display();
}
Wtedy konkretna implementacja rozszerzyłaby klasę i wyglądałaby tak:
<?php
namespace AcmeWordPressAdminMetaBox;
class AcmeMetaBox extends AbstractMetaBox
{
/**
* {@inheritdoc}
*/
public function render()
{
add_meta_box(
'acme-product-image',
'Product Image',
[$this, 'display'],
$this->postType,
'side',
'default'
);
}
/**
* {@inheritdoc}
*/
public function display()
{
include_once plugin_dir_path(__FILE__).'Views/acme-product-image.php';
}
}
I wreszcie, widok dla klasy zawierałby dowolny kod znacznika i szablonu do renderowania informacji :
<div class="product-image-metabox">
<p>
<img src="<?= esc_html(get_post_meta(get_the_ID(), 'product_image', true)); ?>" alt="<?= esc_attr(get_the_title()); ?>" />
<input type="text" value="<?= esc_html(get_post_meta(get_the_ID(), 'product_image', true)); ?>" />
</p>
</div>
Daje nam to dokładnie to, czego potrzebujemy w dobrze zorganizowany sposób wielokrotnego użytku do pracy z metaboxami. Można go również powtórzyć dla takich rzeczy, jak menu, typy postów, taksonomie i tak dalej.
Ale robię dygresję.
Słowo o testowaniu jednostkowym (z PHPUnit)
Jak wspomniałem wcześniej w poście, uważam, że ważne są klasy testów jednostkowych, które rozwiązują problemy unikalne dla naszej przestrzeni problemów. Oznacza to, że musisz poinformować plik konfiguracyjny PHPUnit, aby wykluczył pliki oparte na WordPressie.
Zaletą tego, co przedstawiłem powyżej, jest to, że staje się to trywialnie łatwe. Mówiąc najprościej, możesz dodać to do swojego pliku phpunit.xml :
<testsuites>
<testsuite name="Plugin">
<directory>./tests</directory>
<exclude>./tests/phpunit</exclude>
<exclude>./src/WordPress</exclude>
</testsuite>
</testsuites>
Daje to możliwość skupienia się na pisaniu testów specjalnie dla obszaru problemu, jednocześnie upewniając się, że piszesz skalowalny, łatwy w utrzymaniu i wielokrotnego użytku kod oparty na WordPressie.
Obecnie piszę e-booka (wraz z wieloma innymi treściami premium). Jeśli jesteś zainteresowany, sprawdź co otrzymujesz.