Плагин WordPress: как мне избежать «жесткой связи»?

Я работаю над плагином WordPress и пытаюсь обеспечить лучшие практики. У меня есть два класса, мой класс плагина «Jargonaut», который требуется, а затем еще один класс под названием «Словарь», который включен в require_once() в мой основной файл плагина.

Большая часть кода класса Jargonaut обращается к инициализации и предоставляет функции, подобные контроллеру, но большая часть из них сильно зависит от использования объекта Dictionary (т.е. тесно связана с моим пониманием термина). Я хочу, чтобы класс Dictionary был разделен, поскольку он больше похож на модель (в архитектуре MVC) и взаимодействует с моей базой данных.

Я вижу много серой области в жесткой и свободной связи, и мне трудно решить, сколько слишком много?

Если вашему плагину нужен объект словаря, он должен попросить его:

 class MyPlugin { /** * @var Dictionary */ private $dictionary; private function __construct(Dictionary $dictionary) { $this->dictionary = $dictionary; } 

Теперь вы свободно связали свой плагин с Словарем, класс плагина больше не отвечает за создание Словаря для себя, потому что он вводится. Он требует того, что ему нужно.

Так как это будет работать? Плагин нужно где-то создать, поэтому для этого нужен завод. Метод сборки на заводе знает, что нужно вашему плагину:

 class MyPluginFactory { public static function build($pluginName) { $plugin = NULL; switch($pluginName) { case 'MyPlugin': $dictionary = new Dictionary(); $plugin = new MyPlugin($dictionary); } return $plugin; } } 

Поскольку это wordpress, мы знаем, что самозагрузка плагина выполняется путем включения файла плагина. Итак, в начале, необходимо создать плагин. Поскольку вложения выполняются в глобальном масштабе, мы хотим сохранить объект плагина в памяти, но, возможно, недоступны как глобальная переменная. Это не мешает вам создавать несколько экземпляров плагина, но это гарантирует, что когда wordpress инициализирует ваш плагин (загружает ваш плагин), он будет использовать только один экземпляр. Это можно сделать, добавив фабрике плагинов дополнительную функцию:

 class MyPluginFactory { ... public static $plugins; public static function bootstrap($pluginName) { $plugin = self::build($pluginName); self::$plugins[] = $plugin; return $plugin; } 

Позаботьтесь здесь, что единственное использование переменной статического члена класса – только для того, чтобы плагин оставался в памяти. Это технически глобальная переменная, которую мы обычно хотим предотвратить, однако экземпляр должен быть где-то сохранен, так что вот он (я изменил это на общедоступность, потому что это глобальная переменная, и это не должно стесняться этого. public может помочь в некоторых случаях, когда частные или защищенные являются слишком ограничительными. Также это не должно быть проблемой. Если это проблема, есть еще одна проблема, которая должна быть исправлена ​​в первую очередь).

Это в основном отделяет ваш код плагина от самого WordPress. Вы также можете создать класс, который предлагает и взаимодействует с любой функцией wordpress, которую вы используете, поэтому вы не привязаны к этим функциям напрямую, и ваш код плагина остается чистым и слабо связан с самим wordpress.

 class WordPressSystem { public function registerFilter($name, $plugin, $methodName) { ... do what this needs with WP, eg call the global wordpress function to register a filter. } ... } 

Затем добавьте его как зависимость снова, если ваш плагин нуждается в WordPressSystem для выполнения задач (что обычно имеет место):

 class MyPlugin { ... public function __construct(WordPressSystem $wp, Dictionary $dictionary) ... 

Чтобы, наконец, завершить это, нужен только файл php-плагина:

 <?php /* * MyPlugin * * Copyright 2010 by hakre <hakre.wordpress.com>, some rights reserved. * * WordPress Plugin Header: * * Plugin Name: My Plugin * Plugin URI: http://hakre.wordpress.com/plugins/my-plugin/ * Description: Yet another wordpress plugin, but this time mine * Version: 1.2-beta-2 * Stable tag: 1.1 * Min WP Version: 2.9 * Author: hakre * Author URI: http://hakre.wordpress.com/ * Donate link: http://www.prisonradio.org/donate.htm * Tags: my * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ Namespace MyPlugin; # if your file is named 'MyPlugin.php' this will be 'MyPlugin'. return PluginFactory::bootstrap(basename($plugin, '.php')); class PluginFactory { private static $plugins; public static function bootstrap($pluginName) { $plugin = self::build($pluginName); self::$plugins[] = $plugin; return $plugin; } public static function build($pluginName) { $plugin = NULL; switch($pluginName) { case 'MyPlugin': # Make your plugin work with different WordPress Implementations. $system = new System\Wordpress3(); $dictionary = new Dictionary(); $plugin = new Plugin($system, $dictionary); } return $plugin; } } class Plugin { /** * @var System */ private $system; /** * @var Dictionary */ private $dictionary; private function __construct(System $system, Dictionary $dictionary) { $this->system = $system; $this->dictionary = $dictionary; } ... 

Метод bootstrap также может позаботиться о регистрации автозагрузчика или необходимости.

Надеюсь, это полезно.