Как сделать модули, зависящие от других модулей?

dandandan

Мой дом здесь!
Регистрация
7 Авг 2008
Сообщения
1.036
Реакции
293
Есть движок, который подгружает модули. Некоторые модули работают автономно (независимо друг от друга), а есть модули, которые должны работать в определенном порядке. Например сначала отработал модуль 1. Затем результат работы должен получить модуль 2, модуль 3 и модуль 4. Результат работы модуля 3 получает модуль 5 и т.д.

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

Есть ли идеи, как реализовать такие зависимые модули?
 
Вообще есть несколько способов решения данной задачи:
  1. Внутри нужного модуля просто вызывать другие функции модулей (стандартное решение, полная привязка)
  2. Сделать правила в виде: Если вызов Модуль1.функция1 передать в Модуль1.функция2 (Для создания независимых модулей (применимо при ситуации с разными вариантами реализации комментариев, где нет единого шаблона действий)). Такую вещь можно хранить например в БД.
    Прмер:
    appId callAppId onFunction
    1 3 showNews
    В интерфейсе контролера сделать переопределить __call и реализовать отдачу $this
Подобную задачу я сейчас реализовую в своем Фрейме, и могу сказать, что второй способ отлично работает.
 
Так... тема интересна... сам год назад голову ломал... правда сделал.
Попробую рассказать понятней.

PHP:
<?php
/**
* Итак. Создадим абстрактный класс будующего модуля/сервиса
*
*/
 
  abstract class myModule
  {
        /* приоритет очередности запуска */
      public $priority;
 
      /* Для общения модулей */
      public static $buffer;
 
      /* конструктор класса для установки дефолтов */
      public function __construct() {
 
            /* Дефолтовая установка приоритета */
          $this->priority = 9;
 
          /* проверяем на наличие метода инициализации класса
          * Чтоб не трогать __construct
          */
          if( method_exists($this, '__initialize') ) {
              $this->__initialize();
          }
      }
 
      /* Метод отработки модуля */
      abstract public function run();
  }
 
/*
Теперь создаём некий файл с именем класса,
только маленькими буквами.
 
Ну и внутри него сам класс^
 
  имя_класса.module.php
 
*/
 
  /* файл executer.module.php
  *  Имя класса состоит из имени файла без .modules.php
  *  и добавка _Module
  */
  class Executor_Module extends myModule
  {
 
        /* Метод инициализации
        * Если конечно нужен
        */
      public function __initialize()
      {
 
      }
 
      public function run()
      {
          echo 'Executor runing!!!';
      }
  }
 
 
/**
* Так вот... у нас есть некая специальная директория где все модули
* Теперь нам нужно из неё выгребсти все модули и запустить их
* Обязательно первая буква в названии класса большая, остальные маленькие
*/
 
/* полный путь к модулям */
$MODULES_DIR = './';
 
/* выгребаем содержимое директории */
$MODULES    = glob( $MODULES_DIR . '*.modules.php' );
 
/* Наши модули
*
*  Сруктура будет такой
*
*  $MODULES_ARRAY[ приоритет запуска ][ имя модуля ] = объект модуля
*/
$MODULES_ARRAY = array();
 
 
if( !empty($MODULES) ) {
    foreach($MODULES as $key=>$val) {
        $module_file = str_replace( $MODULES_DIR, '', $val );
        $module_name = str_replace( '.modules.php', '', $module_file );
 
        /* Создаём имя класса */
        $module_class_name = ucfirst( strtolower($module_name) ) . '_Module';
 
        /* Проверяем наличие класса */
        if( !class_exists($module_class_name) ) {
 
              /* Грузим модуль */
            require( $MODULES_DIR . $module_file );
 
            /**
              * Опять проверяем наличие класса
              * Можно даже добавить else с выводом ошибки о отсутствии класса
            */
            if( class_exists($module_class_name) ) {
   
                  /* Создаём экземпляр класса */
                  $_mod = new $module_class_name();
   
                  /* и добавляем его в банк модулей */
                $MODULES_ARRAY[ $_mod->priority ][ $module_name ] = $_mod;
            }
        }
    }
}
 
ksort($MODULES_ARRAY);
 
 
/*
* Затем после такой инициализации мы делаем в любом месте,
* там где нам нужно запустить все модули,
* отработку модулей
*/
 
  foreach($MODULES_ARRAY as $priority=>$modules_list) {
      foreach($modules_list as $key=>$val) {
          if( is_object($val) ) {
              $val->run();
          }
      }
  }
 
  /**
  * Вот такой вот способ
  * Конечно в некоторых местах нужно добавить болше проверок,
  * Но то уже на личное усмотрение
  */

Далее всё просто.
Если есть файл модуля, он запустится.

Для передачи данных между модулями, нужно понимать их очередность...
и использовать, например так:

PHP:
public function run() {
    if( class_exists('Vasya_Module') ) {
        Vasya_Module::$buffer = 'Hello!';
    }
}

Ну а там проверяем наличие данных в self::$buffer и пользуем
 
Назад
Сверху