Понедельник, 29.04.2024, 05:36
Меню сайта
Категории раздела
JQuery плагины [59]
JQuery уроки [69]
PHP полезное [24]
PHP уроки [21]
Css [26]
JS [3]
SQL [9]
Css 3 [17]
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Главная » Статьи » PHP уроки

PHP система плагинов на основе хуков (hooks)

PHP система плагинов на основе хуков (hooks)

07.12.2012
PHP система плагинов на основе хуков (hooks)

Здравствуйте, уважаемые читатели блога LifeExample, сегодня предлагаю затронуть очень редкую тему, информации о которой в интернете, кране не хватает. Говорить мы будем о том, как самостоятельно сделать систему плагинов для своей CMS.

Однажды, я где-то читал мысль, что каждый уважающий себя php программист, обязан, хотя бы попробовать сделать свою CMS. И на самом деле очень много, моих знакомых разрабатывали свои домашние системы управления сайтом. Вот и я не стал исключением, и сделал собственную CMS, которая в последствии вылилась в обособленный проект MOGUTA.CMS.

MOGUTA.CMS теперь имеет все задатки, для того, чтобы попытаться покорить сердца начинающих предпринимателей, дав им возможность комфортно управлять своими интернет-магазинами. Именно поэтому у меня давно уже зрело желание создать систему плагинов для своей CMS, да такую чтобы она была легкой и удобной для работы пользователей и программистов.

Проработав некоторое время с движком WordPress, я не мог не оценить его механизм взаимодействия плагинов и ядра, который основан на системе хуков (Hooks – с англ. крючек, зацепка). Опираясь именно на эту концепцию системы плагинов, я решил разработать ее аналог в своей CMS.

PHP hooks – хуки и их концепция

Система хуков как нельзя лучше подходит для расширения функционала CMS, поскольку позволяет довольно гибко оперировать функциями движка, меняя их логику и поведение. Поскольку мне не довелось встретить толкового и обширного объяснения природы плагинов на основе хуков, я попробую изложить ее смысл, настолько – насколько сам его понимаю.

Предлагаю рассмотреть, что такое php hooks, и как их реализовать на простом примере.

В упрощенном виде, система хуков в PHP может выглядеть таким образом:

  1. Имеется главный класс Main, в котором реализована вся логика приложения.
  2. Имеется файл plugin.php, содержащий обработчики событий, которые должны произойти классе Main. Например, событием может являться выполнение метода __construct().
  3. Также есть файл index.php, объединяющий эти два файла в одну систему.
  4. Запуская index.php инклудом подключается файл plugin.php, и создается экземпляр класса Main.
  5. В коде метода __construct() класса Main создаются хук (зацепка), для обработчика.
  6. В момент создания хука, выполняется тело функции из класса файла plugin.php, тем самым изменяя обычное создание экземпляра класса Main.

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

Но за такую гибкость приходится платить производительностью системы в целом, поэтому перед реализацией в php системы хуков, советую хорошенько подготовиться теоретически.

Как реализовать Hooks

На самом деле система хуков намного сложнее, чем приведенная ниже, но на первом этапе знакомства будет вполне достаточно рассмотреть в миниатюре механизм взаимодействия плагинов и ядра.

Скачать пример реализации системы плагинов ( Скачали: 50 чел. ) 

В архиве находится три файла:

  • index.php – файл запускающий псевдо систему;
  • plugin.php – мини плагин;
  • libHook.php – библиотека для механизма хуков.

Давайте начнем разбираться с файла index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
//Флаг использования плагинов
$plugin = true;
//подключаем библиотеку для хуков
include 'libHooks.php';
// Инициализация менеджера плагинов, он будет следить за произходящими событиями
$PM = new PM();
//Подключение плагина
if($plugin) {
  include 'plugin.php';
}


//псевдо ядро системы
class Core{
  public function __construct(){
    echo "...Действия ядра...";
    // Используем глобальный менеджер плагинов
    global $PM;
    //Происходит событие demoHook, где-то в недрах ядра
    $PM->createHook('demoHook');
    echo "...Действия ядра...";
  }
}

//Эмуляция запуска ядра системы
$core = new Core();

В данном скрипте происходит:

  • подключение плагина;
  • подключение библиотеки хуков;
  • создание менеджера плагинов – экземпляр класса который предназначен для связи плагина с ядром систмы;
  • эмуляция запуска дейсвий ядра.

Обратите внимание на конструктор класса Core, в нем происходит инициализаци хука.

Следующая строка, создает действие с именем ‘demoHook’

1
$PM->createHook('demoHook');

Если ранее в плагине был зарегистрирован обработчик данного события, то менеджер плагинов $PM найдет его и выполнит необходимую пользовательскую функцию.

Откроем из архива файл plugin.php

1
2
3
4
5
6
7
8
9
<?php

//пользовательская функция выполняющаяся при определенном событии
function myFunction(){
  echo "<br/> >>>Действия плагина<<< <br/>";
}

//регистрируем пользовательскую функцию как обработчика для события demoHook
$PM->registration(new EventHook('demoHook', 'myFunction'));

Этот файл представляет собой аналог плагина, в котором имеется функция myFunction(), назначением которой является расширение стандартного функционала системы.

В плагине с помощью системы хуков (hooks) , мы должны привязать пользовательскую функцию к определенному событию, которое может произойти в ядре в любой момент и не единожды.

Строка:

1
$PM->registration(new EventHook('demoHook', 'myFunction'));

Регистрирует нашу функцию в качестве обработчика, для события demoHook. Теперь когда бы не произошло событие demoHook всегда будет выполнено тело функции myFunction().

Запустив файлы архива, мы увидим такой результат:

Система hooks хуков

Как устроена система хуков

В выше приведенном примере использовалась библиотека для механизма крючков и зацепок, мы подключали ее строкой:

1
include 'libHooks.php';

Давайте откроем этот файл и посмотрим, что же в нем хранится, и как все это работает.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<?php
/**
 * Библиотека хуков, содержит интерфейсы PluginManager и Hook,
 * а также класс PM и EventHook
 * Класс PM предназначен для управления плагинами
 * Класс Hook создает обработчик событий
 *
 * Автор: Авдеев Марк
 * Ссылка на описание: http://lifeexampl.nichost.ru/php-primeryi-skriptov/php-sistema-plaginov-na-osnove-hukov-hooks.html
 */


//Интерфейс для слушаемого
interface PluginManager {
  function registration(Hook $hook);
  function delete(Hook $hook);
  function createHook($hookName);
}

//Интерфейс для слушателя
interface Hook {
  function run(PluginManager $hookName);
}


// Клас PM (plugin Manager) управляет плагинами,
// регистрирует  плагины и устанавливает их взаимодействие с системой.
class PM implements PluginManager{

  // Заристрированные обработчики хуков
  private $_eventHook;

  public function __construct(){
    $this->_eventHook = array();
  }

  // регистрация обработчика для хука
  public function registration(Hook $eventHook){
    $this->_eventHook[] = $eventHook;
  }


  // удаление заданного обработчика
  public function delete(Hook $eventHook){
    if($id = array_search($eventHook, $this->_eventHook, TRUE)){
      unset($this->_eventHook[$id]);
    }
  }


  // Если в программе создан hook, сказать об этом всем
  // обработчикам, вдруг кто-то из них ждет этого
  // хука, для выполнения пользовательсякой функции.
  public function createHook($hookName){
    foreach($this->_eventHook as $eventHook){
      if($eventHook->getHookName() == $hookName){
        $eventHook->run($this);
      }
    }
  }

}

//Вешает обработчик для заданного хука
class EventHook implements Hook{

  // Наименование хука
  private $_hookName;
  // пользовательская функция, которая сработает при хуке
  private $_functionName;

  public function __construct($hookName, $functionName){
    $this->_hookName = $hookName;
    $this->_functionName = $functionName;
  }

  // Запуск обработчика для хука
  public function run(PluginManager $pm){
    if(function_exists($this->_functionName)){
      call_user_func($this->_functionName);
    }
  }

  public function getHookName(){
    return $this->_hookName;
  }

}

Вся логика взаимодействия хуков с обработчиками основана на паттерне observer, также известного как "Издатель и Подписчик". Я не буду сейчас описывать суть данного шаблона проектирования, поскольку делал это ранее.

Смысл заключается в том, что все пользовательские функции регистрируются для соответствующих действий классом PM в качестве обработчиков событий-хуков (EventHook).

Когда в системе происходит событие createHook("имя события – хука"), сгенерированное опять таки классом PM, то он как генератор имеет доступ к реестру пользовательских функций и начинает подбирать подходящую из них, для обработки текущего события.

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

Вывод

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

Ну а если вам все же интересно как можно развить данную заготовку до полноценной системы плагинов, рекомендую ознакомиться с моим движком MOGUTA.CMS, в котором механизм хуков учитывает все атрибуты настоящих плагинов такие как:

  • Регистрация плагина в системе;
  • Активация плагина;
  • Деактивация;
  • Изменение результата системной функции;
  • Изменение тела системной функции;
  • Подмена параметров системной функции.

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

Надеюсь эта реализация системы хуков оказалась для вас настолько же интересной как и для меня.

Категория: PHP уроки | Добавил: ChronoW (20.04.2013)
Просмотров: 1312 | Теги: hooks, php hooks, PHP хуки | Рейтинг: 0.0/0
Всего комментариев: 0