В ZF можно реализовать подмодули с относительно небольшими усилиями. Допустим, у вас есть структура каталогов, такая как:
application/
modules/
admin/
cms/
controllers/
views/
controllers/
views/
Вы должны зарегистрировать такие модули в своем бутстрапе (подмодули используют _ для отделения подмодуля от основного модуля):
$frontController->setControllerDirectory(array(
'default' => APPLICATION_PATH . '/modules/default/controllers',
'admin' => APPLICATION_PATH . '/modules/admin/controllers',
'admin_cms' => APPLICATION_PATH . '/modules/admin/cms/controllers'
));
Проблема с этим заключается в том, что вместо косой черты в URL-адресе будет использоваться подчеркивание, например: «admin_cms/conteroller/action» вместо «admin/cms/controller/action». Пока это "работает", это некрасиво. Один из способов решить эту проблему — указать собственный маршрут для маршрута по умолчанию. Поскольку Zend_Controller_Router_Route_Module по умолчанию делает это почти правильно, вы можете просто расширить его и добавить желаемое поведение:
<?php
class App_Router_Route_Module extends Zend_Controller_Router_Route_Module
{
public function __construct()
{
$frontController = Zend_Controller_Front::getInstance();
$dispatcher = $frontController->getDispatcher();
$request = $frontController->getRequest();
parent::__construct(array(), $dispatcher, $request);
}
public function match($path)
{
// Get front controller instance
$frontController = Zend_Controller_Front::getInstance();
// Parse path parts
$parts = explode('/', $path);
// Get all registered modules
$modules = $frontController->getControllerDirectory();
// Check if we're in default module
if (count($parts) == 0 || !isset($modules[$parts[0]]))
array_unshift($parts, $frontController->getDefaultModule());
// Module name
$module = $parts[0];
// While there are more parts to parse
while (isset($parts[1])) {
// Construct new module name
$module .= '_' . $parts[1];
// If module doesn't exist, stop processing
if (!isset($modules[$module]))
break;
// Replace the parts with the new module name
array_splice($parts, 0, 2, $module);
}
// Put path back together
$path = implode('/', $parts);
// Let Zend's module router deal with the rest
return parent::match($path);
}
}
И в вашем бутстрапе:
$router = Zend_Controller_Front::getInstance()->getRouter();
$router->addRoute('default', new App_Router_Route_Module);
Что это делает, так это проходит путь до тех пор, пока он находит модуль, и прозрачно переписывает путь, чтобы Zend_Controller_Router_Route_Module по умолчанию мог выполнять реальную работу. Например, следующий путь: «/admin/cms/article/edit» будет преобразован в «/admin_cms/article/edit», что позволяет стандартному соглашению ZF «:module/:controller/:action» творить чудеса. .
Это позволяет вам иметь красивую модульную структуру с автономными модулями, но при этом использовать красивые, логичные URL-адреса. Одна вещь, которую вы хотите отметить, это то, что если вы используете Zend_Navigation и указываете элементы навигации, используя параметры модуля/контроллера/действия, вам нужно сообщить ZF, как правильно построить URL-адрес, используя «/» вместо «_» в именах модулей. (по умолчанию ZF использует спецификацию :module/:controller/:action при создании URL-адресов). Вы можете сделать это, реализовав свой собственный Zend_Controller_Action_Helper_Url, например:
<?php
class App_Router_Helper_Url extends Zend_Controller_Action_Helper_Url
{
public function url($urlOptions = array(), $name = null, $reset = false, $encode = false)
{
// Replace the _ with / in the module name
$urlOptions['module'] = str_replace('_', '/', $urlOptions['module']);
// Let the router do rest of the work
return $this->getFrontController()->getRouter()->assemble($urlOptions, $name, $reset, $encode);
}
}
И в вашем бутстрапе:
Zend_Controller_Action_HelperBroker::addHelper(new App_Router_Helper_Url);
Теперь Zend_Navigation прекрасно работает и с поддержкой ваших подмодулей.
person
reko_t
schedule
28.10.2009