Помните, что WordPress использует шаблон проектирования, управляемый событиями, и хотя мы часто ссылаемся на действия и фильтры, концепция сводится к крючкам. Поток управления через программу выглядит примерно так:
- Выполнить программу,
- Всякий раз, когда программа натыкается на хук (в WordPress мы увидим
do_action
илиapply_filters
), перебираем все зарегистрированные хуки, - Верните управление обратно в программу,
- Выполнять до конца.
Это не полностью отличается от шаблона Publisher/Subscriber (или PubSub для краткости), но есть ключевое отличие: шаблон, управляемый событиями, просто сигнализирует о том, что что-то произошло, и если есть перехватчики, они сработают. Паттерн PubSub скажет зарегистрированному подписчику что-то сделать.
В любом случае, вернемся к хукам в WordPress. Легче всего сохранить две концепции крючков, которые у нас есть, если думать о них так:
- Действия нужны для того, чтобы что-то делать,
- Фильтры предназначены для обработки данных.
Если вы хотите подходить к разработке WordPress в объектно-ориентированном стиле, тесная связь вашего кода с ядром WordPress путем регистрации ваших классов через хуки для основного приложения не является хорошей идеей.
Другими словами, не регистрируйте свою бизнес-логику в WordPress. Держите их отдельно. Вот лакмусовая бумажка того, тесно ли ваша работа связана с WordPress: если вы не можете запустить модульный тест для своего класса без загрузки WordPress, значит, он тесно связан.
Итак, каково решение? Делегация.
Логика домена в WordPress
Логика домена и бизнес-логика, насколько я понимаю, взаимозаменяемы, поэтому, если вы читали предыдущие сообщения об этом, и я говорил о них по-разному, вы знаете, почему.
Затем идея делегирования логики из WordPress классу логики домена в WordPress реализуется промежуточным классом, который отвечает за следующее:
- Подписка на хук,
- Делегирование работы классу.
Я знаю, что классы должны хорошо делать «одну вещь», но что, если эта одна вещь — делегирование?
передавать (полномочия, функции и т. д.) другому в качестве агента
И чтобы правильно передать функциональность другому агенту или, в нашем случае, классу, вы должны иметь возможность знать, что вы делегируете. Иногда, чтобы сделать что-то одно, нужно знать несколько единиц информации.
Так как же это выглядит на практике? Представьте, что у вас есть [AbstractSubscriber](https://github.com/tommcfarlin/remove-empty-shortcodes/blob/master/src/Subscriber/AbstractSubscriber.php)
to, который возьмет имя хука в свой конструктор:
И затем, как только это будет сделано, load
функция отправит работу классу, ответственному за фактическую обработку.
Возьмем, к примеру, этот код из «Удалить пустые шорткоды» :
Класс подписывается на определенное событие, например [the_content](https://developer.wordpress.org/reference/functions/the_content/)
, а затем делегирует работу классу обработки пост-контента.
Это буквально позволяет загрузочному файлу плагина создавать экземпляр делегата. Затем делегат подключается к WordPress, и когда WordPress достигает нужной точки выполнения, делегат передает ответственность классу, ответственному за его обработку.
Вся эта архитектура не только полностью повторно используемая (см. выше использование абстрактного класса), но и позволяет нам отделить доменную логику от WordPress и протестировать ее изолированно.
Подробнее о разделении ответственности
Я написал несколько других сообщений о разделении интересов:
- Разделение проблем с шаблонами WordPress
- Разделение задач с помощью запросов и вспомогательных функций
- Программирование WordPress: разделение проблем