Виджеты WordPress: рефакторинг, часть 7
В последних нескольких сообщениях мы проделали большую работу, чтобы довести код до уровня рефакторинга, который будет рассмотрен в этой статье.
В частности, мы рассмотрели:
- крючки,
- реестр, _
- и Подписчики.
Все это сыграет свою роль в том, что мы собираемся сделать сегодня.
Шаблон виджета WordPress: рефакторинг, часть 7
Те, кто знаком с API виджетов WordPress, вероятно, знают, что за последние несколько лет он не сильно изменился.
Более того, на самом деле он состоит только из четырех функций (одна из которых — конструктор):
- Конструктор отвечает за установку нескольких свойств виджета, чаще всего его имени и его описания.
- Функция виджета отвечает за отображение содержимого виджета.
- Функция формы отвечает за отображение формы в области администрирования WordPress при работе с виджетом.
- Функция обновления отвечает за обновление параметров, которые сохранены в базе данных (или инициализированы, а затем сохранены параметры, которые могут еще не существовать в базе данных).
Приятно то, что этот конкретный подход достигается за счет наследования функциональности класса WP_Widget.
Проблема, однако, в том, что для одного класса требуется много работы.
Вместо этого мы должны разделить каждую из функций на свою собственную область функциональности.
Как и во всем в программировании, будут способы, в которых некоторые вещи будут понятны, как их можно сделать, а затем будут некоторые вещи, которые можно сделать несколькими способами.
Что я собираюсь представить, так это то, как я подхожу к этому на данный момент. Это может измениться в будущем, а может и нет, и у других может быть другой взгляд на это.
Несмотря на это, реализация будет гораздо более объектно-ориентированной и наделит каждый класс собственным набором обязанностей.
Однако первый вопрос заключается в том, как разделить класс с четырьмя функциями, который наследуется от родительского класса?
Обновление Bootstrap
Во-первых, есть несколько вещей, которые нам нужно настроить в начальной загрузке плагина. А именно, нам нужно сделать следующее:
- создать реестр и сделать его доступным через проект,
- обновить класс Plugin, чтобы он принимал реестр и загружал подписчиков,
- просмотрите бутстрап
Вот посмотрите на все три вышеперечисленных.
1 Создайте экземпляр реестра
Поскольку мы уже рассмотрели это ранее в серии, должно быть ясно, как это сделать.
Во- первых, см. следующий код :
<?php
// Setup a filter so we can retrieve the registry throughout the plugin.
$registry = new Registry();
add_filter('wpwBoilerplateRegistry', function() use ($registry) {
return $registry;
});
Далее обратите внимание, что мы создаем экземпляр реестра (мы сейчас поговорим о его пространстве имен), а затем подключаем его к пользовательскому фильтру, который позволяет нам получать к нему доступ через плагин в любое время.
2 Обновите класс плагина
Затем нам нужно обновить основной класс плагина (который находится в каталоге src ), чтобы он ссылался на реестр и загружал всех зарегистрированных подписчиков :
<?php
/*
* This file is part of WordPress Widget Boilerplate
* (c) Tom McFarlin <tom@tommcfarlin.com>
*
* This source file is subject to the GPL license that is bundled
* with this source code in the file LICENSE.
*/
namespace WordPressWidgetBoilerplate;
use WordPressWidgetBoilerplateUtilitiesRegistry;
/**
* The base class for this plugin. Maintains a copy of the registry and starts
* all of the objects that should hook into WordPress.
*/
class Plugin
{
/**
* @var Registry a reference to the simple container used to maintain plugin objects
*/
private $registry;
/**
* @param Registry $registry a reference to the simple container used to maintain plugin objects
*/
public function __construct(Registry $registry)
{
$this->registry = $registry;
}
/**
* Iterates through each of the subscribers maintained in the registry and registers them
* to the proper WordPress hook.
*/
public function start()
{
array_map(function ($subscriber) {
add_action($subscriber->getHook(), [$subscriber, 'load']);
}, $this->registry->getRegisteredSubscribers());
}
}
Обратите внимание, однако, что мы еще не настроили никаких подписчиков. Мы начали это ранее в серии, и теперь пришло время вернуться к этому, но мы сделаем это позже.
Однако нам нужно добавить функцию — даже если она временная — чтобы мы могли добавлять классы, которые не являются явными подписчиками событий:
<?php
/**
* @return array all of the the objects that aren't subscribers registered with WordPress
*/
public function getRegisteredObjects()
{
$objects = [];
foreach ($this->registry as $object) {
if (!$object instanceof AbstractSubscriber) {
$objects[] = $object;
}
}
return array_filter($objects);
}
Это будет переработано позже, так как позже мы превратим основные классы в подписчиков.
3 Просмотрите Bootstrap
Прежде чем идти дальше, я думаю, что важно рассмотреть бутстрап. Хотя ваш заголовок и документация могут различаться, важно отметить, что мы делаем следующее:
- пространство имен бутстрапа,
- предотвращение доступа к файлу,
- вызов автозагрузчика,
- настройка реестра,
- и запуск плагина.
Звучит много, но код довольно короткий :
<?php
/**
* WordPress Widget Boilerplate
*
* The WordPress Widget Boilerplate is an organized, maintainable boilerplate for building
* widgets using WordPress best practices.
*
* @package WordPressWidgetBoilerplate
* @author Your Name <email@example.com>
* @license GPL-3.0+
* @link http://example.com
* @copyright 2018 - 2019 Your Name or Company Name
*
* @wordpress-plugin
* Plugin Name: WordPress Widget Boilerplate
* Plugin URI: https://github.com/tommcfarlin/wordpress-widget-boilerplate
* Description: An object-oriented foundation for building WordPress Widgets.
* Version: 1.0.0
* Author: Tom McFarlin
* Author URI: https://tommcfarlin.com
* Text Domain: widget-name
* License: GPL-3.0+
* License URI: http://www.gnu.org/licenses/gpl-3.0.txt
* Domain Path: /lang
*/
namespace WordPressWidgetBoilerplate;
use WordPressWidgetBoilerplateUtilitiesRegistry;
use WordPressWidgetBoilerplatePlugin;
// Prevent this file from being called directly.
defined('WPINC') || die;
// Include the autoloader.
require_once __DIR__. '/vendor/autoload.php';
// Setup a filter so we can retrieve the registry throughout the plugin.
$registry = new Registry();
add_filter('wpwBoilerplateRegistry', function() use ($registry) {
return $registry;
});
// Start the machine.
(new Plugin($registry))->start();
На данный момент, однако, пришло время взглянуть на то, что значит разделить дочерний класс из стандартного API виджетов на что-то, что соответствует модели кода, с которой мы работаем.
Разделение дочернего класса
Эта часть, скорее всего, займет несколько постов, так как предстоит проделать небольшую работу, но мы начнем с создания нашего собственного класса виджетов, который будет наследоваться от базового класса Widget.
Во-первых, создайте каталог API в каталоге src и добавьте файл с именем Widget.php. Здесь будут находиться основы виджета. В следующем посте мы рассмотрим административные и общедоступные таблицы стилей и файлы JavaScript.
На этом этапе основы файла должны выглядеть так :
<?php
/*
* This file is part of WordPress Widget Boilerplate
* (c) Tom McFarlin <tom@tommcfarlin.com>
*
* This source file is subject to the GPL license that is bundled
* with this source code in the file LICENSE.
*/
namespace WordPressWidgetBoilerplateAPI;
use WP_Widget;
class Widget extends WP_Widget
{
/**
* @var string unique identifier for your widget
*/
protected $widgetSlug;
/**
* Initializes the plugin by setting its properties and calling the parent class with the description.
*
* @param mixed $widgetSlug
*/
public function __construct($widgetSlug)
{
$this->widgetSlug = $widgetSlug;
// TODO: update description
parent::__construct(
$this->getWidgetSlug(),
__('Widget Name', $this->getWidgetSlug()),
[
'classname' => $this->getWidgetSlug().'-class',
'description' => __('Short description of the widget goes here.', $this->getWidgetSlug()),
]
);
}
/**
* Return the widget slug.
*
* @return string slug variable
*/
public function getWidgetSlug()
{
return $this->widgetSlug;
}
/**
* TODO: This is a temporary message to show that the Boilerplate has loaded.
*/
public function load()
{
$html = '<p style="text-align:center; background: #fff; padding: 1em; border: 1px dotted gray; margin: 2em 2em 2em 14em;">';
$html .= 'The Widget Boilerplate is loaded.';
$html .= '</p>';
echo $html;
}
}
Обратите внимание, что он принимает один аргумент. Я использовал имя виджета, но вы можете использовать любое имя, если оно представляет ваш виджет.
Это должно показать, что класс правильно создается и загружается при активации плагина. Если вы этого не видите, значит что-то не так (что мы сейчас рассмотрим).
Далее важно убедиться, что этот класс добавлен в реестр. Поэтому добавьте следующие строки кода в бутстрап:
<?php
// Add the Widget base class to the Registry.
$registry->add('widget', new Widget('widget-name'));
И теперь, когда вы активируете плагин, вы должны увидеть следующее:
Если нет, обязательно просмотрите код в ветке разработки, чтобы убедиться, что у вас есть все, что описано в этом посте.
Реализация подписчиков
В следующих сообщениях мы рассмотрим, как мы можем реализовать подписчиков для общедоступной части сайта (то есть там, где отображается содержимое виджета). И то же самое мы сделаем для области администрирования сайта.
Наконец, мы обратим наше внимание на код, отвечающий за защиту и сериализацию данных (читай: обновление нашего виджета), а затем посмотрим, как выглядит окончательная версия обновленного шаблона.
Однако в этом посте основная стратегия, которую мы используем, заключается в разделении дочернего класса, чтобы его по-прежнему можно было использовать с другими классами, используя интерфейсы и базовые классы, которые уже определены в кодовой базе.
