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

Тема в разделе "Как сделать...", создана пользователем dandandan, 28 окт 2012.

  1. dandandan

    dandandan

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

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

    Есть ли идеи, как реализовать такие зависимые модули?
     
  2. Ion-Software

    Ion-Software Создатель

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

    cruide Писатель

    Регистр.:
    25 июл 2012
    Сообщения:
    8
    Симпатии:
    22
    Так... тема интересна... сам год назад голову ломал... правда сделал.
    Попробую рассказать понятней.

    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 ucfirststrtolower($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 и пользуем
     
    dandandan нравится это.