Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Модульность. Обсуждение принципов и проблем. 
:(
    Опции темы
Wowa
Дата 4.5.2005, 18:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Есть программа. Необходимо обеспечить подключение к ней модулей различной направленности. Состоящих не только из одного файла. Какие пути реализации вы видите?

я вижу такой путь:
1. Создается таблица
Код

CREATE TABLE modules (
modulename varchar(255) NOT NULL PRIMARY KEY,
description varchar(255) NOT NULL,
status enum('false','true'),
)


2. При запуске программы читаются все записи из таблицы modules WHERE status='true'

3. Теперь мы знаем, как называется каталог, в котором лежит модуль. Он называется также, как и modulename из таблицы.

4. Загружаем файл:
include("modules/extra/$modulename/conf.php");

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


Подключение нового модуля к системе
- Загружаем все файлы модуля в каталог: modules/extra/имя_модуля
- Делаем запись в таблицу modules о новом модуле.
- Подключаем файл install.php
Этот файл содержит две функции:
1. install_module
2. uninstall_module
- Запускаем функцию install_module, которая создает нужную таблицу, нужные поля в таблица и т.п., а также делает все, что нужно для установки модуля.
- По окончании своей работы, если модуль подключен успешно, то она в таблице modules ставит status=true для себя.
PM WWW   Вверх
Wowa
Дата 4.5.2005, 18:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Нужно очень хорошо продуманная система модульности.
PM WWW   Вверх
Opik
Дата 4.5.2005, 19:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Vingrad developer
Сообщений: 1918
Регистрация: 6.10.2004
Где: Рига

Репутация: 3
Всего: 55



А инфу из файла в таблицу зенести нельзя?
PM MAIL Skype   Вверх
Wowa
Дата 4.5.2005, 19:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Остается тонкий момент... Что делать, когда один подключаемый модуль должен как-то влиять на другой уже подключенный модуль? Например, добавить ему некоторую функциональность.
имхо это можно реализовать только двумя способами:
1. Подключенный модуль заменит своими некоторые функции прежнего модуля.
2. Если прежний модуль знает о возможности расширения функциональности за счет подключения внешнего модуля, то в нем должна быть организована стыковка с модулем.
Например, в тех местах, где требуется выполнить какое-то действие, проверяется по таблице modules наличие такого модуля, и если он там есть, то вызывается с него определенная функция.
PM WWW   Вверх
Opik
Дата 4.5.2005, 19:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Vingrad developer
Сообщений: 1918
Регистрация: 6.10.2004
Где: Рига

Репутация: 3
Всего: 55



Думаю вызывать через:
Module::method;
PM MAIL Skype   Вверх
Wowa
Дата 4.5.2005, 19:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Цитата(Opr @ 4.5.2005, 17:01)
А инфу из файла в таблицу зенести нельзя?

Какую инфу и из какого файла? Из файла конфига? имхо нет в этом необходимости. Т.к. конфиг модуля будет меняться в моем случае все равно только специалистов, и что будет в этом конфиге хранится, я сам толком еще не знаю.. Может у кого-то есть мысли, что там можно хранить?
PM WWW   Вверх
Farik
Дата 4.5.2005, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 49
Регистрация: 1.2.2005

Репутация: нет
Всего: 1



всё равно не совсем понятно, зачем разделять инициализацию модуля на два этапа - чтение из базы и чтение из файла
почему бы не хранить настройки в базе?
соответсвенни и взаимодействие модулей тоже можно в таком случае сохранять в базе и вызывать не конфигурационный файл, а конфигурационные опции....
PM MAIL   Вверх
Wowa
Дата 4.5.2005, 19:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Цитата(Farik @ 4.5.2005, 17:09)
всё равно не совсем понятно, зачем разделять инициализацию модуля на два этапа - чтение из базы и чтение из файла
почему бы не хранить настройки в базе?

Если вышла новая версия модуля, то мне достаточно загрузить новые файлы модуля в нужный каталог. Иначе же мне нужно еще запрос делать к базе, в котором менять версию модуля в базе. К тому же, может будут локальные настройки для модуля, которые только этот подключаемый модуль будет использовать. Их также удобнее хранить в файле.
PM WWW   Вверх
AntonioBanderaz
Дата 4.5.2005, 23:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 1
Всего: 18



А автозпгрузкой не пробывал?

Код

<?php
   //Фкнуция автозагрузки
    function  __autoload($class) {
         include("module_".ucfirst($class).".php");
    }
    
    $u = new User; 
?>


Он сам будет искать в ТЕКУЩЕМ каталоге, все файлы типа module_траля-ля.php и смотреть нет ли в них класса User, если таковой не определён!!!

Это сообщение отредактировал(а) AntonioBanderaz - 4.5.2005, 23:21


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Wowa
Дата 5.5.2005, 00:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



AntonioBanderaz но тогда, чтобы отключить какой-то модуль, получается мне его надо удалять. А это плохо.
PM WWW   Вверх
Opik
Дата 5.5.2005, 01:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Vingrad developer
Сообщений: 1918
Регистрация: 6.10.2004
Где: Рига

Репутация: 3
Всего: 55



Wowa
Это почему удалять? он же подключается только при вызове.
PM MAIL Skype   Вверх
Wowa
Дата 5.5.2005, 02:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Цитата(Opr @ 4.5.2005, 23:33)
Это почему удалять? он же подключается только при вызове.

а если мне его не надо подключать? Есди этот модуль мне надо отключить?
PM WWW   Вверх
AntonioBanderaz
Дата 5.5.2005, 05:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 1
Всего: 18



Wowa - логично будет его не вызывать, тогда он и будет отключён....


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
AntonioBanderaz
Дата 5.5.2005, 05:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 1
Всего: 18



Изменить функцию на проверку из какой-нидь хни и имени модуля, если он там есть - то не подключать, если нет, то подключать....
Т.е.
Код

<?php    
   //Функция автозагрузки    
    function  __autoload($class) {    
         if(searchModule($class))
             include("module_".ucfirst($class).".php"); //инклюднуть заразу
         else 
            // типо вывод, такой модуль отключён...    
    }    
    function searchModule($mod) {
         $conf = // читаешь запрещённые модули или наоборот, и распологай это где хош, хоть в базе, хоть в файле
         if($conf != str_replace($mod,'',$conf) return false; //наш модуль в списке запрещённых
         return true; // Его там не оказалось
    }
     
    $u = new User;    
?>


Вот Тебе и отключение....

Это сообщение отредактировал(а) AntonioBanderaz - 5.5.2005, 15:11


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
IZ@TOP
Дата 5.5.2005, 09:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: 1
Всего: 73



Я бы делал немного по другому. Представим что у нас есть таблица скилета системы работающей с модулями и т.п. Вот ее SQL структура:

Код

create table site_tree (
    id int not null auto_increment,
    parent int not null default '0',
    modid int not null default '0',
    name varchar(30) not null,
    title varchar(150) not null,
    content text,
    alias varchar(20),
    visible bool,
    created timestamp,
    updated timestamp,
    primary key (id)
);


Данная таблица, допустим, будет определять структуру нашего сайта. К разделам можно обращаться несколькими путями - по алиасу или по идентификатору в базе.
В данном примере правда эта структура может иметь не более одной вложенности категорий, но при желании это можно изменить. Поле modid ссылается на подключаемый модуль, таблица которого, по моим соображениям, должна быть устроена примерно следующим образом:

Код

create table site_modules (
    id int not null auto_increment,
    name varchar(20) not null,
    source varchar(50) not null,
    type enum('class', 'function'),
    initialize varchar(50),
    visible bool,
    accesslevel tinyint,
    primary key(id)
);


Итак, у нас есть таблица модуля предоставляющая нам следующие данные:
Имя модуля - оно же может быть каталогом в папке ответственной за храниение модулей. Это зависит уже от ваших настроек.
Сорс модуля - исполняемый файл. Может содержать в себе несколько модулей - т.е. мы представляем отдельный файл не как отдельный модуль, а как например хранилище методов класса или функций.
Соответственно учитываем тип модуля - класс или функция.
Какой метод класса или фуункцию нам нужно инициализировать. Если нам не нужно ничего инициализировать внутри модуля, просто ничего не делаем.
Ну и на всякий случай определим уровень доступа, но об этом думайте сами.

Представлю на конкретном примере как все это должно работать:

Представим что пользователь запршивает страничку с идентификатором 387, к которой привязан модуль с ID 8, этот модуль отвечает за вывод новостей.

Вот примерный план действий:

Код

<?php

// ... загрзили данные о страничке. Далее проерка некоторых параметров и загрзка модуля
// В siteTree находится инфа выбранная из таблицы site_tree

if($siteTree['modid'] != 0) {
    if(!$db->sendQuery('select name, source, type, initialize from site_modules where accesslevel <= ${0 i} and visible = 1 and id = ${1 i}',
        $siteTree['modid'])) {
        // Если модуль не найден, выводим сообщение об ошибке и завершаем работу
        die("Can't load module");
    }
    
    $Module    = $db->nextRow();
    
    // Проверяем сначало нужна ли инициализация модуля, затем его тип и в соответствии
    // с полученными данными выполняем необходимые действия
    
    if(!empty($Module['initialize'])) {
        
        switch($Module['type']) {
            case 'class': {
                // Если наш модуль это класс, то проверям его загрузку в массиве 
                // инициализированных модулей
                
                if(isset($GLOBAL_MODULES[$Module['name']])) {
                    
                    // Проверяем что наш класс был инициализирован, если нет - создаем объект
                    
                    if(!is_object($GLOBAL_MODULES[$Module['name']])) {
                        $GLOBAL_MODULES[$Module['name']]    = new $Module['name'];
                    }
                    
                    // Проверяем существует ли метод в нашем объекте, если да - вызываем,
                    // если нет - выводим сообщение об ошибке
                    
                    if(method_exists($GLOBAL_MODULES[$Module['name']], $Module['initialize'])) {
                        $GLOBAL_MODULES[$Module['name']]->$Module['initialize']();
                    } else {
                        die('Object method not exists');
                    }

                } else {
                    
                    // Если наш модуль не разу не загружался, выолняем подключение файла и
                    // инициализацию объекта класса
                    
                    require_once "{$CONFIG['MODULE_DIR']}/{$Module['name']}/{$Module['source']}";
                    $GLOBAL_MODULES[$Module['name']]    = new $Module['name'];
                    
                    if(method_exists($GLOBAL_MODULES[$Module['name']], $Module['initialize'])) {
                        $GLOBAL_MODULES[$Module['name']]->$Module['initialize']();
                    } else {
                        die('Object method not exists');
                    }
                }
                
            } default: {
                
                // По умолчанию у нас вызывается функция из файла модуля
                
                if(!isset($GLOBAL_MODULES[$Module['name']])) {
                    require_once "{$CONFIG['MODULE_DIR']}/{$Module['name']}/{$Module['source']}";
                    $GLOBAL_MODULES[$Module['name']] = true;
                }
                
                if(function_exists($Module['initialize'])) {
                    $Module['initialize']();
                } else {
                    die('function not exists');
                }
            }
        }
    }
}

?>


Код не проверял, могут быть ошибки. Но логика должна быть понятна.


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
Ответ в темуСоздание новой темы Создание опроса

Внимание: данный раздел предназначен для решения сложных, нестандартных задач.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Для профи | Следующая тема »


 




[ Время генерации скрипта: 0.0597 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.