Я пытаюсь придумать способ создания плагиновой архитектуры для своей собственной структуры. Я читал множество тем и размещал здесь и на других сайтах. И в основном я пришел к следующему решению, которое, по-видимому, является единственным хорошим вариантом в PHP (в настоящее время).
Идея состоит в том, что каждый класс расширяет своего рода наблюдатель, как класс. Таким образом, класс Template, BaseController и т. Д. Всегда расширяют класс Plugin.
class BaseController extends Plugin { public function __construct() { // Plugin check, notify all loaded plugins $this->checkForEarlyHooks(); // Init some standard stuff $this->view = new Template(); $this->baseLayout = 'layout.html'; $this->something = new Something(); // Plugin check, notify all loaded plugins $this->checkForLateHooks(); } }
Итак, что в основном происходит здесь, так это то, что когда indexController расширяет baseController, выполняется проверка плагина. В этом случае для конструктора. Это может быть удобно, если вы хотите сделать какую-то проверку входа в систему с помощью плагина, прежде чем на самом деле вызывается метод Action.
Класс Plugin может решить, из какого класса вызывается и знает, для каких функций искать в загружаемых плагинах.
Также обратите внимание, что он проверяет загруженный список плагинов 2 раза. Прежде чем что-либо загрузится (раньше) в конструкторе, и когда все вары будут загружены (позже).
Я также могу добавить переменные в функцию checkForLateHooks (). Таким образом, функции hook также могут манипулировать ими, как и переменная baseLayout.
Функция hook будет выглядеть так:
public function hookConstruct ( &$baseLayout ) { $baseLayout = 'login.html'; }
Теперь, в основном, мой вопрос: этот подход какой-то хороший? Я знаю, что, возможно, есть много других способов сделать это. Но я в основном не хочу сталкиваться с проблемами дизайна позже. Сейчас это кажется хорошей идеей, но вы никогда не знаете, как все будет развиваться позже …
Если я помню это правильно (со всех сообщений, которые я прочитал), это похоже на WordPress (и некоторые другие фреймворки).
UPDATE : ответ теперь отражает современные ссылки и лучшее описание.
Конечно, существует много разных способов разработки плагиновой системы и, возможно, задание https://softwareengineering.stackexchange.com/ даст вам больше идей, но я постараюсь помочь, делясь своими идеями и опытом.
Я расскажу о некоторых своих собственных опытах, которые я узнал из серии своих собственных фреймворков. В настоящее время Agile UI и Agile Data поддерживают многие функции, которые будут расширены, но я сосредоточусь на «Компонентах»,
Когда вы пытаетесь ввести код в существующий объект, крючок является стандартным способом. Это лучший вариант для расширения приложения или потока с установленной структурой.
Во время рефакторинга моих фреймворков я разделил реализацию перехвата на отдельный признак и задокументировал его здесь: http://agile-core.readthedocs.io/en/develop/hook.html
Хост-приложение:
... some code here .. $this->hook('beforeInit'); $this->init(); $this->hook('afterInit'); ... code goes on ..
Плагин:
$host_app->addHook('beforeInit', function($object) { echo "About to execute init of $object"; });
Компоненты представляют собой другой шаблон проектирования, который подходит для пользовательских интерфейсов. Вы начинаете с макета страницы / приложения, который затем разбивается на «Меню», «Заголовок», «Нижний колонтитул», «Контент».
Компонент – это объект, который может быть связан с макетом или другим компонентом. Каждый компонент способен передавать и передавать дополнительный HTML / JS своему родительскому элементу. Большинство компонентов также будут являться объектами-преломлениями.
Этот подход называется «Render Tree», а выполнение приложения проходит через 2 этапа – «инициализация дерева рендеринга», а затем «рендеринг».
Хост-приложение:
$layout->menu = new \atk4\ui\Menu(); $layout->add($layout->menu, 'TopMenu');
Вышеприведенный код показывает, как новый компонент (меню) можно инициализировать и вставить в $layou
. Кроме того, вывод HTML из меню $ направляется в тег {$ TopMenu}, который определен в шаблоне HTML макета.
Плагин может взаимодействовать с деревом рендеринга:
Когда эти подходы объединены, вы можете использовать что-то вроде этого:
$app->addHook('afterInitLayout', function($app) { $app->layout->menu->destroy(); // remove default menu $app->layout->menu = new \plugin\SuperMenu(); $app->layout->add($app->layout->menu); });
Это можно использовать для замены стандартного меню с более мощной реализацией из вашего дополнения.
Моя реализация компонентов документирована здесь:
http://agile-ui.readthedocs.io/en/latest/view.html#initializing-render-tree
Хотя, возможно, не так много ответов на вопрос, но еще один мощный способ расширения – это разделение проблем. Все компоненты пользовательского интерфейса в пользовательском интерфейсе Agile не знают, как делать что-либо с данными.
Хотя многие генераторы UI требуют, чтобы разработчик вручную создавал их и связывался с данными, я вводил объект «Model» следующим образом:
$form->setModel(new User($db)); // populates name, surname and gender fields
Демо: http://ui.agiletoolkit.org/demos/form2.php (2-я форма)
В этом подходе объект User
содержит достаточно метаданных для заполнения Формой своих полей, титры выполняют валидацию, а также сохраняют / загружают данные.
Поскольку класс «Пользователь» также может быть объявлен в надстройке, он делает довольно мощный способ расширить существующую функциональность, добавив поддержку новых объектов данных.
Некоторые другие подходы к расширению с дополнениями включают в себя:
Фабрика:
Возможность разрешить класс, указанный в виде строки в пространстве имен / файле:
$api->add('MyClass');
Предоставляет возможность добавления для повторного маршрута стандартных классов, но не очень дружелюбен с типом намека на IDE.
Новые типы / Черты:
Add-on может предоставить новые классы, добавляющие Persistences, Table Columns, Form Fields, Actions и т. Д.
Я думаю, что добавление deign сводится к:
Взгляните на PHPPlugin на https://github.com/gheevel/PHPPlugin . Простая инфраструктура плагинов PHP, вдохновленная архитектурой плагинов eclipse и jira. В основном, ваше приложение может определять точки расширения, а экземпляры плагина могут регистрироваться в этих точках расширения для обеспечения дополнительной функциональности. Хорошо работает в сочетании с композитором и / или symfony.