Как использовать одни и те же модели в разных модулях в Zend Framework?

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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
8
0
11 487
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

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

редактировать: Такие функции, как 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.

Есть ли причина, по которой вы не используете addControllerDirectory () вместо добавления значения в INCLUDE_PATH?

Noah Goodrich 03.11.2008 21:26

Насколько мне известно, addControllerDirectory () не добавляет соответствующий каталог моделей в ваш путь включения. См. Примеры в моей редакции выше.

Bill Karwin 03.11.2008 22:42

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

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

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

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

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

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

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

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

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

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

Другие вопросы по теме