Как использовать одни и те же модели в разных модулях в Zend Framework? - PullRequest
8 голосов
/ 03 ноября 2008

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

При реализации Zend Framework я хотел бы создать возможность разбивать контроллеры и представления на модули (один для области участников, один для общедоступного маркетинга, один для сайта администратора и один для маркетинговой кампании). Администратор сайта), но мне нужно иметь возможность указывать каждый модуль на одну и ту же модель, поскольку все три компонента работают в одной базе данных и в одних и тех же бизнес-объектах.

Однако я не смог найти никакой информации о том, как это сделать, в документации. Может ли кто-нибудь помочь со ссылкой на то, как это сделать, или с некоторыми простыми инструкциями, как это сделать?

Ответы [ 5 ]

9 голосов
/ 03 ноября 2008

Что я делаю, так это храню общие классы в «библиотечном» каталоге вне иерархии модулей. Затем установите my 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/
. . .

В моем скрипте начальной загрузки я бы добавил "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» для правильного модуля в загрузочном устройстве, поскольку модуль зависит от маршрутизации. Некоторые люди делают это в методе init() своих контроллеров, а некоторые пишут плагин для ловушки preDispatch ActionController, чтобы установить INCLUDE_PATH.

3 голосов
/ 16 ноября 2008

Это также может быть достигнуто с помощью соглашения об именах, следующего за Zend_Loader. Храните файлы моделей в папке моделей в папке их модулей. Назовите их как Module_Models_ModelName и сохраните их в файле с именем ModelName.php в папке моделей для этого модуля. Убедитесь, что папка приложения находится в вашем пути включения, и, если вы используете Zend_Loader для автоматической загрузки, вы можете просто ссылаться на модели по имени класса.

Это имеет преимущество, заключающееся в том, что код вашей модели сгруппирован с фактическим модулем, для которого он предназначен. Это позволяет хранить модуль в одной структуре папок, что способствует инкапсуляции. Это также поможет в будущем, если вам нужно перенести модуль в другой проект.

1 голос
/ 03 июня 2009

Я только что создал этот пользовательский Помощник действий для описанной проблемы:

<?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');
  }
}

И это позволит вам получить доступ к моделям любого контроллера во всех модулях.

0 голосов
/ 03 октября 2013

<?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'   

    ),
),
);
0 голосов
/ 21 мая 2009

У меня такая же проблема. Ответ Билла мне не подходит - потому что я склонен делить свои модули не на «кто их видит», а на «то, что они делают». Например, «модулем форума» может управлять как администратор, так и публика. Я пытаюсь использовать внешние модули, такие как admin, members, public - но тогда они используют другие модули, такие как 'forum / validatepost', 'forum / show персональная информация пользователей'. Если бы кто-нибудь мог пролить свет на то, как они защищают внутренний модуль от публики, это было бы удобно. Я думаю, что ACL может быть ключом, но он все еще заставляет меня нервничать, когда доступ контролируется объектами, а не «файловой системой / .htaccess» и т. Д.

Чтобы ответить на вопрос PHPoet: (i) Пути к каталогам контроллера модуля могут быть указаны вызовами фронт-контроллера: например, см .: «12.11.2. Указание каталогов контроллера модуля» (Документы Zend Framework)

(ii) Пути к представлениям можно задать с помощью ViewRenderer (Помощник действий контроллера) например см .: «Пример 12.12. Выбор другого скрипта вида '(Zend Framework Docs)

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

(Я не изучал, как работает автозагрузчик, но было бы разумно иметь какую-то систему картографирования для решения такого рода проблем.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...