8

我正在一个现有项目中实施 Zend 框架,该项目有一个公共营销区域、一个私人成员区域、一个管理站点和一个营销活动管理站点。目前,这些都组织得很差,营销区域的控制器脚本和成员区域都位于站点的根目录下,然后是一个单独的文件夹用于管理员,另一个文件夹用于营销活动站点。

在实现 Zend 框架时,我想创建能够将控制器和视图拆分为模块(一个用于成员区域,一个用于公共营销区域,一个用于管理站点,一个用于营销活动管理站点)但我需要能够将每个模块指向同一个模型,因为所有三个组件都在同一个数据库和同一个业务对象上工作。

但是,我无法在文档中找到有关如何执行此操作的任何信息。任何人都可以提供有关如何执行此操作的链接或有关如何完成此操作的一些简单说明的帮助吗?

4

5 回答 5

9

我所做的是将公共类保存在模块层次结构之外的“库”目录中。然后设置我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()他们的控制器的方法中这样做,有些人为 ActionController 的 preDispatch 钩子编写一个插件来设置INCLUDE_PATH.

于 2008-11-03T18:22:00.327 回答
3

这也可以通过遵循的命名约定来完成Zend_Loader。将模型文件保存在模块文件夹下的模型文件夹中。将它们命名为Module_Models_ModelName并将它们保存在该模块的模型文件夹中的文件名 ModelName.php 中。确保应用程序文件夹在您的包含路径中,并假设您正在使用Zend_Loader自动加载,然后您可以通过它们的类名引用模型。

这样做的好处是可以将您的模型代码与它所针对的实际模块组合在一起。这使模块包含在单个文件夹结构中,这有助于鼓励封装。如果您需要将模块移植到另一个项目,这也将在未来有所帮助。

于 2008-11-16T04:14:39.013 回答
1

我刚刚为您描述的问题构建了这个自定义操作助手:

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

这将允许您跨所有模块访问任何控制器中的模型。

于 2009-06-02T23:19:09.667 回答
0

我有同样的问题。比尔的回答不适合我——因为我倾向于划分我的模块,不是按“谁在看它们”,而是按“他们做了什么”。例如,“论坛模块”可能由管理员和公众共同管理。我正在尝试使用前端模块,例如 admin、members、public - 但这些模块随后会使用其他模块,例如“forum/validatepost”、“forum/show users personal info”。如果有人能阐明他们如何保护后端模块不受公众的影响,那将很方便。我猜 ACL 可能是关键,但它仍然让我紧张由对象控制访问,而不是“文件系统/.htaccess”等。

回答 PHPoet 的问题:(i)模块控制器目录的路径可以通过调用前端控制器来指定:例如,参见:“12.11.2. 指定模块控制器目录”(Zend Framework Docs)

(ii) 可以使用 ViewRenderer (Controller Action Helper) 设置视图的路径,例如:'Example 12.12. 选择不同的视图脚本'(Zend Framework Docs)

通过尝试改变视图和控制器的默认路径,从而释放自动加载器以正常运行。

(我没有研究过自动加载器的工作方式,但是拥有一些映射器系统来解决这类问题是有意义的。)

于 2009-05-20T22:45:43.230 回答
0

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

    ),
),
);
于 2013-10-03T05:42:29.517 回答