Я работаю над внедрением Zend Framework в рамках существующего проекта, который имеет область публичного маркетинга, зону частных пользователей, сайт администрирования и сайт управления маркетинговой кампанией. В настоящее время они плохо организованы с помощью скриптов диспетчера для области маркетинга и области участников, находящихся под корнем сайта, а затем отдельной папки для администратора и другой папки для сайта маркетинговой кампании.
При реализации Zend Framework я хотел бы создать возможность разделить контроллеры и представления на модули (один для области участников, один для области публичного маркетинга, один для сайта администратора и один для сайта администрирования маркетинговой кампании) но мне нужно указать каждый модуль на ту же модель, поскольку все три компонента работают в одной и той же базе данных и на тех же бизнес-объектах.
Однако я не смог найти информацию о том, как это сделать в документации. Может ли кто-нибудь помочь с ссылкой о том, как это сделать или какие-то простые инструкции о том, как это сделать?
То, что я делаю, – это поддерживать общие классы в "библиотечном" каталоге за пределами иерархии модулей. Затем установите INCLUDE_PATH
для использования каталога «models» соответствующего модуля, а также общей библиотеки «library».
docroot/ index.php application/ library/ <-- common classes go here default/ controllers/ models/ views/ members/ controllers/ models/ views/ admin/ controllers/ models/ views/ . . .
В моем скрипте bootstrap я добавляю « application/library/
» в INCLUDE_PATH
. Затем в функции init()
каждого контроллера я добавляю каталог « models/
» этого модуля в INCLUDE_PATH
.
edit: такие функции, как setControllerDirectory()
и setModuleDirectory()
, не добавляют соответствующие каталоги моделей в INCLUDE_PATH
. Вы должны сделать это сами в любом случае. Вот один пример того, как это сделать:
$app = APPLICATION_HOME; // you should define this in your bootstrap $d = DIRECTORY_SEPARATOR; $module = $this->_request->getModuleName(); // available after routing set_include_path( join(PATH_SEPARATOR, array( "$app{$d}library", "$app{$d}$module{$d}models", get_include_path() ) ) );
Вы можете добавить « library
» к вашему пути в начальной загрузке, но вы не можете добавить каталог « models
» для правильного модуля в bootstrap, потому что модуль зависит от маршрутизации. Некоторые люди делают это в методе init()
своих контроллеров, а некоторые люди пишут плагин для кэша preDispatch ActionController для установки INCLUDE_PATH
.
Это также можно выполнить с помощью соглашения об именах, чтобы следовать за Zend_Loader
. Храните файлы модели в папке с образцами в папке с модулем. Назовите их как Module_Models_ModelName
и сохраните их в имени файла ModelName.php в папке моделей для этого модуля. Убедитесь, что папка приложения находится в вашем пути включения и если вы используете Zend_Loader
для автоматической загрузки, вы можете просто ссылаться на модели по их имени класса.
Это имеет то преимущество, что ваш код модели сгруппирован с фактическим модулем, для которого он предназначен. Это сохраняет модуль, содержащийся в одной структуре папок, что помогает поощрять инкапсуляцию. Это также поможет в будущем, если вам необходимо перенести модуль в другой проект.
Я просто создал этот пользовательский помощник действий для описанной проблемы:
<?php class My_Controller_Action_Helper_GetModel extends Zend_Controller_Action_Helper_Abstract { /** * @var Zend_Loader_PluginLoader */ protected $_loader; /** * Initialize plugin loader for models * * @return void */ public function __construct() { // Get all models across all modules $front = Zend_Controller_Front::getInstance(); $curModule = $front->getRequest()->getModuleName(); // Get all module names, move default and current module to // back of the list so their models get precedence $modules = array_diff( array_keys($front->getDispatcher()->getControllerDirectory()), array('default', $curModule) ); $modules[] = 'default'; if ($curModule != 'default') { $modules[] = $curModule; } // Generate namespaces and paths for plugin loader $pluginPaths = array(); foreach($modules as $module) { $pluginPaths[ucwords($module)] = $front->getModuleDirectory($module) . '/models'; } // Load paths $this->_loader = new Zend_Loader_PluginLoader($pluginPaths); } /** * Load a model class and return an object instance * * @param string $model * @return object */ public function getModel($model) { $class = $this->_loader->load($model); return new $class; } /** * Proxy to getModel() * * @param string $model * @return object */ public function direct($model) { return $this->getModel($model); } }
Итак, в вашем Bootstrap.php:
Zend_Controller_Action_HelperBroker::addPrefix('My_Controller_Action_Helper');
И в любом из ваших контроллеров:
<?php class IndexController extends Zend_Controller_Action { public function indexAction() { $model = $this->_helper->getModel('SomeModel'); } }
И это позволит вам получить доступ к моделям любого контроллера во всех модулях.
У меня такая же проблема. Ответ Билла не подходит для меня – потому что я склонен разделить мои модули, а не «кто их видит», а «что они делают». Например, «форум-модуль» может управляться как администратором, так и общественностью. Я пытаюсь иметь модули переднего плана, такие как admin, members, public, но затем они используют другие модули, такие как «forum / validatepost», «форум / показать пользователям личную информацию». Если кто-то может пролить свет на то, как они защищают внутренний модуль от общественности, тогда это было бы удобно. Я думаю, что ACL может быть ключом, но он все еще заставляет меня нервничать, имея доступ, контролируемый объектами, в отличие от «файловой системы / .htaccess» и т. Д.
Чтобы ответить на вопрос PHPoet: (i) Пути к директориям диспетчера модулей могут быть заданы вызовами переднего контроллера: например, см. «12.11.2. Указание директорий контроллера модуля» (Zend Framework Docs)
(ii) Пути к представлениям могут быть установлены с помощью ViewRenderer (помощник действий контроллера), например, см. «Пример 12.12. Выбор другого сценария просмотра (документы Zend Framework)
Играя вокруг своего возможного, чтобы изменить пути по умолчанию к представлениям и контроллерам, освободив автозагрузчик для запуска в обычном режиме.
(Я не рассматривал способ работы автозагрузчика, но для него было бы целесообразно иметь некоторую систему картографов для решения этой проблемы).
<?php return array( 'modules' => array( 'Application', 'DoctrineModule', 'DoctrineORMModule', 'Merchant', ), 'module_listener_options' => array( 'config_glob_paths' => array( 'config/autoload/{,*.}{global,local}.php', ), 'module_paths' => array( './module', '../vendor', // 'here we can load module' 'comomonmodule' ), ), );