在 Zend Framework 2 中加载具有多个模块的模块
Loading Modules which has multiple module in Zend Framework 2
问题
所以我尝试将我的应用程序解耦到多个模块项目(每个模块项目都有自己的 composer.json ),然后真正的应用程序将通过 composer
此模块项目中的每一个都将有一个可通过浏览器访问的用户界面,并且可以单独启动,因此它不仅仅是一个简单的库。该文件将存在于每个模块项目中:
- config/application.config.php
- public/index.php
Example Module(Dependency 是我在application.config.php中写的模块数组):
- UI模块
- 依赖项:AssetManager、UIModule
- CMS模块
- 依赖项:UIModule、CMSModule
- 会计模块:
- 依赖项:UIModule、会计模块
现在在我的最终应用程序中假设 MyApplication 它需要 CMSModule 和 AccountingModule,但是我不能在应用程序中只写这两个模块。config.php。相反,我必须写:
- AssetManager -> 这应该由 UIModule 加载
- UIModule -> 这应该由 CMS/Accounting 模块
加载
- CMS模块
- 会计模块
我应该只要求在MyApplication
中写这两个
- CMS模块
- 会计模块
这可以做到吗?我认为这家伙想在 Loading Modules Dynamically in Zend Framework 2
中实现什么
像这样,我添加了另一个额外的模块。
根据我们在评论和问题中的交流,您至少需要 3 个应用程序。我会给你一个简单的例子,你必须自己更新每个应用程序的要求。在 composer.json 配置之后,我会给你一个骨架模块作为主题模块。
这些配置将用作 root
composer.json 配置文件。每个必需的包都应该有自己的特定包的作曲家文件列表要求。
例如,"core" 模块需要各种 Zend Framework 包。 "theme" 包可能需要其他 ZF 包,例如 zendframework/zend-view
才能拥有 GUI 布局。
设置 3 个具有重叠需求的独立 Zend Framework 应用程序
composer.json
应用程序 1
{
"name": "COMPANY_NAME/APPLICATION_1",
"require": {
"COMPANY_NAME/MODULE_1_THEME": "*",
"COMPANY_NAME/MODULE_2_CMS": "*"
},
"repositories": [
{
"type": "git",
"url": "git@github.com/COMPANY_NAME/MODULE_1_THEME.git"
},
{
"type": "git",
"url": "git@github.com/COMPANY_NAME/MODULE_2_CMS.git"
},
]
}
composer.json
应用程序 2
{
"name": "COMPANY_NAME/APPLICATION_2",
"require": {
"COMPANY_NAME/MODULE_1_THEME": "*",
"COMPANY_NAME/MODULE_3_ACCOUNTING": "*"
},
"repositories": [
{
"type": "git",
"url": "git@github.com/COMPANY_NAME/MODULE_1_THEME.git"
},
{
"type": "git",
"url": "git@github.com/COMPANY_NAME/MODULE_3_ACCOUNTING.git"
},
]
}
composer.json
应用程序 3(没有主题)
{
"name": "COMPANY_NAME/APPLICATION_3",
"require": {
"COMPANY_NAME/MODULE_4_AUTH_MODULE": "*"
},
"repositories": [
{
"type": "git",
"url": "git@github.com/COMPANY_NAME/MODULE_4_AUTH_MODULE.git"
}
]
}
如您所见,应用程序 1 和 2 使用相同的 MODULE_THEME
包,正如您在问题中的图表中所概述的那样。
现在,为 Zend Framework 创建的包对于您创建的每个包来说几乎都是一样的,因此请根据您对每个模块(在包中)的要求修改以下内容。
创建主题模块
此模块基本上替换了安装 Zend Framework(2 或 3)骨架应用程序时默认获得的 Application
模块。
我最近将我所有的 Zend Framework 都升级到了 Zend Framework 3,所以我将为您提供一个为 ZF3 量身定制的设置。但是,降级 ZF2 应该不是什么大问题。
根据需要创建配置
一个典型的主题需要一些东西,例如:
- themes/layouts 用于不同类型的页面(例如登录、普通主题、错误)
- 翻译
- 显示错误(在开发模式下)
- 默认"home"路由
- 控制器处理默认"home"路由
这个的配置可以是(不限于!随心所欲!)在主题模块的 module.config.php
namespace COMPANY_NAME\Theme;
use COMPANY_NAME\Theme\Controller\ThemeController;
use COMPANY_NAME\Theme\Factory\ThemeControllerFactory;
return [
'controllers' => [
'factories' => [
ThemeController::class => ThemeControllerFactory::class,
],
],
'router' => [
'routes' => [
'home' => [
'type' => Literal::class,
'may_terminate' => true,
'options' => [
'route' => '/',
'defaults' => [
'controller' => ThemeController::class,
'action' => 'index',
],
],
],
],
],
'route_layouts' => [
'*' => 'layout/layout',
'login' => 'layout/login',
'register' => 'layout/login',
'error*' => 'error/index',
'error/404' => 'error/404',
],
'translator' => [
'locale' => 'en_US',
'translation_file_patterns' => [
[
'type' => 'gettext',
'base_dir' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'language',
'pattern' => '%s.mo',
],
],
],
'view_manager' => [
// controller_map is optional, but depending on your composer package nesting, could be a great help. Have a look here for how to use: https://blog.alejandrocelaya.com/2015/08/14/working-with-sub-namespaced-modules-in-zend-framework-2-the-right-way/
'controller_map' => [
'COMPANY_NAME\Theme' => 'company_name_path_alias',
],
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => [
'layout/layout' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR .
'layout' . DIRECTORY_SEPARATOR . 'layout.phtml',
'layout/login' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR .
'layout' . DIRECTORY_SEPARATOR . 'login.phtml',
'error/404' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR .
'error' . DIRECTORY_SEPARATOR . '404.phtml',
'error/index' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR .
'error' . DIRECTORY_SEPARATOR . 'index.phtml',
],
'template_path_stack' => [
__DIR__ . DIRECTORY_SEPARATOR .'..' . DIRECTORY_SEPARATOR . 'view',
],
],
];
File/module 结构基于配置
包的位置将是 /vendor/COMPANY_NAME/THEME_MODULE_NAME
(正如您在 composer.json
文件的 name
属性 中为此包定义的那样。
folder/file 结构为:
- /vendor/COMPANY_NAME/THEME_MODULE_NAME
- 配置/
- module.config.php
- 源/
- 控制器/
- ThemeController.php
- 工厂/
- ThemeControllerFactory.php
- Module.php
- 查看/
- 错误/
- index.phtml
- 404.phtml
- 布局/
- index.phtml
- login.phtml
- register.phtml
- composer.json
ThemeController & *Factory
这些非常简单,因为控制器几乎是骨架应用程序提供的原始 IndexController
的克隆。在这种情况下,工厂只做 return 控制器。因此,您可以将它的配置替换为 Zend Framework 3 的 InvokableFactory
的 FQCN,而不是使工厂 class。但是,如果您的 ThemeController
需要一些要求(例如 RegisterForm
),您将需要工厂提供这些。
主题控制器
namespace COMPANY_NAME\Controller;
use Zend\Mvc\Controller\AbstractActionController;
class ThemeController extends AbstractActionController
{
public function indexAction()
{
return [];
}
}
ThemeControllerFactory
namespace COMPANY_NAME\Factory;
use COMPANY_NAME\Controller\ThemeController;
use Zend\ServiceManager\Factory\FactoryInterface;
class ThemeControllerFactory implements FactoryInterface
{
/**
* @param ContainerInterface $container
* @param string $requestedName
* @param array|null $options
* @return ThemeController
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new ThemeController();
}
}
主题作曲家要求
显然您的模块不会有相同的要求。确保你弄清楚它们是什么,每个模块。
对于我自己的主题模块,我的 composer.json
文件中有以下 Zend Framework 要求:
{
"name": "COMPANY_NAME/THEME_MODULE_NAME",
"require": {
"zendframework/zend-di": "*",
"zendframework/zend-navigation": "*",
"zendframework/zend-view": "*",
}
}
在 require
部分我还有:"rwoverdijk/assetmanager": "^1.6",
。该模块用于将所有 CSS、JS(实际上是任何类型)文件混合到一个确定的位置。我建议您看一下 (here)。
答案注释
- 将
COMPANY_NAME
替换为您的 Github 帐户的用户名(如果您使用的是 Bitbucket 或 Gitlab,则为识别帐户名)
- 将
THEME_MODULE_NAME
替换为存储库的名称
- If/when 可能,对所需的包使用显式版本(例如
"rwoverdijk/assetmanager": "^1.6"
)。版本锁定可以让你以后省去很多麻烦...
另外:使用包作为 "Theme module" 允许您完全删除最初随 Zend Framework 的骨架应用程序一起提供的 module/
文件夹。但是,特此建议您将 module/
文件夹用于特定于应用程序的模块。如果你为所有东西创建一个包,你很快就会发现自己陷入了维护地狱。
是的,你的布局就是我最后的样子
However, you're hereby advised to use the module/ folder for application specific modules.
某种程度上,我最终将每个特定包(zf2 样式)放入一个文件夹中
- 包文件夹
- composer.json
- Module.php(此为php单元测试)
- public(对于UI包我有这个)
- index.php
- 配置
- application.config.php (显然需要为每个包写每个版本)
- 测试
- 来源
- MODULE_NAME
- 资产
- 来源
- MODULE_NAME
- 控制器
- 服务
- 型号
- { 其他... }
- 配置
- 查看
- Module.php
感谢您的澄清和回答。
问题
所以我尝试将我的应用程序解耦到多个模块项目(每个模块项目都有自己的 composer.json ),然后真正的应用程序将通过 composer
此模块项目中的每一个都将有一个可通过浏览器访问的用户界面,并且可以单独启动,因此它不仅仅是一个简单的库。该文件将存在于每个模块项目中:
- config/application.config.php
- public/index.php
Example Module(Dependency 是我在application.config.php中写的模块数组):
- UI模块
- 依赖项:AssetManager、UIModule
- CMS模块
- 依赖项:UIModule、CMSModule
- 会计模块:
- 依赖项:UIModule、会计模块
现在在我的最终应用程序中假设 MyApplication 它需要 CMSModule 和 AccountingModule,但是我不能在应用程序中只写这两个模块。config.php。相反,我必须写:
- AssetManager -> 这应该由 UIModule 加载
- UIModule -> 这应该由 CMS/Accounting 模块 加载
- CMS模块
- 会计模块
我应该只要求在MyApplication
中写这两个- CMS模块
- 会计模块
这可以做到吗?我认为这家伙想在 Loading Modules Dynamically in Zend Framework 2
中实现什么像这样,我添加了另一个额外的模块。
根据我们在评论和问题中的交流,您至少需要 3 个应用程序。我会给你一个简单的例子,你必须自己更新每个应用程序的要求。在 composer.json 配置之后,我会给你一个骨架模块作为主题模块。
这些配置将用作 root
composer.json 配置文件。每个必需的包都应该有自己的特定包的作曲家文件列表要求。
例如,"core" 模块需要各种 Zend Framework 包。 "theme" 包可能需要其他 ZF 包,例如 zendframework/zend-view
才能拥有 GUI 布局。
设置 3 个具有重叠需求的独立 Zend Framework 应用程序
composer.json
应用程序 1
{
"name": "COMPANY_NAME/APPLICATION_1",
"require": {
"COMPANY_NAME/MODULE_1_THEME": "*",
"COMPANY_NAME/MODULE_2_CMS": "*"
},
"repositories": [
{
"type": "git",
"url": "git@github.com/COMPANY_NAME/MODULE_1_THEME.git"
},
{
"type": "git",
"url": "git@github.com/COMPANY_NAME/MODULE_2_CMS.git"
},
]
}
composer.json
应用程序 2
{
"name": "COMPANY_NAME/APPLICATION_2",
"require": {
"COMPANY_NAME/MODULE_1_THEME": "*",
"COMPANY_NAME/MODULE_3_ACCOUNTING": "*"
},
"repositories": [
{
"type": "git",
"url": "git@github.com/COMPANY_NAME/MODULE_1_THEME.git"
},
{
"type": "git",
"url": "git@github.com/COMPANY_NAME/MODULE_3_ACCOUNTING.git"
},
]
}
composer.json
应用程序 3(没有主题)
{
"name": "COMPANY_NAME/APPLICATION_3",
"require": {
"COMPANY_NAME/MODULE_4_AUTH_MODULE": "*"
},
"repositories": [
{
"type": "git",
"url": "git@github.com/COMPANY_NAME/MODULE_4_AUTH_MODULE.git"
}
]
}
如您所见,应用程序 1 和 2 使用相同的 MODULE_THEME
包,正如您在问题中的图表中所概述的那样。
现在,为 Zend Framework 创建的包对于您创建的每个包来说几乎都是一样的,因此请根据您对每个模块(在包中)的要求修改以下内容。
创建主题模块
此模块基本上替换了安装 Zend Framework(2 或 3)骨架应用程序时默认获得的 Application
模块。
我最近将我所有的 Zend Framework 都升级到了 Zend Framework 3,所以我将为您提供一个为 ZF3 量身定制的设置。但是,降级 ZF2 应该不是什么大问题。
根据需要创建配置
一个典型的主题需要一些东西,例如:
- themes/layouts 用于不同类型的页面(例如登录、普通主题、错误)
- 翻译
- 显示错误(在开发模式下)
- 默认"home"路由
- 控制器处理默认"home"路由
这个的配置可以是(不限于!随心所欲!)在主题模块的 module.config.php
namespace COMPANY_NAME\Theme;
use COMPANY_NAME\Theme\Controller\ThemeController;
use COMPANY_NAME\Theme\Factory\ThemeControllerFactory;
return [
'controllers' => [
'factories' => [
ThemeController::class => ThemeControllerFactory::class,
],
],
'router' => [
'routes' => [
'home' => [
'type' => Literal::class,
'may_terminate' => true,
'options' => [
'route' => '/',
'defaults' => [
'controller' => ThemeController::class,
'action' => 'index',
],
],
],
],
],
'route_layouts' => [
'*' => 'layout/layout',
'login' => 'layout/login',
'register' => 'layout/login',
'error*' => 'error/index',
'error/404' => 'error/404',
],
'translator' => [
'locale' => 'en_US',
'translation_file_patterns' => [
[
'type' => 'gettext',
'base_dir' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'language',
'pattern' => '%s.mo',
],
],
],
'view_manager' => [
// controller_map is optional, but depending on your composer package nesting, could be a great help. Have a look here for how to use: https://blog.alejandrocelaya.com/2015/08/14/working-with-sub-namespaced-modules-in-zend-framework-2-the-right-way/
'controller_map' => [
'COMPANY_NAME\Theme' => 'company_name_path_alias',
],
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => [
'layout/layout' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR .
'layout' . DIRECTORY_SEPARATOR . 'layout.phtml',
'layout/login' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR .
'layout' . DIRECTORY_SEPARATOR . 'login.phtml',
'error/404' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR .
'error' . DIRECTORY_SEPARATOR . '404.phtml',
'error/index' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR .
'error' . DIRECTORY_SEPARATOR . 'index.phtml',
],
'template_path_stack' => [
__DIR__ . DIRECTORY_SEPARATOR .'..' . DIRECTORY_SEPARATOR . 'view',
],
],
];
File/module 结构基于配置
包的位置将是 /vendor/COMPANY_NAME/THEME_MODULE_NAME
(正如您在 composer.json
文件的 name
属性 中为此包定义的那样。
folder/file 结构为:
- /vendor/COMPANY_NAME/THEME_MODULE_NAME
- 配置/
- module.config.php
- 源/
- 控制器/
- ThemeController.php
- 工厂/
- ThemeControllerFactory.php
- Module.php
- 控制器/
- 查看/
- 错误/
- index.phtml
- 404.phtml
- 布局/
- index.phtml
- login.phtml
- register.phtml
- 错误/
- composer.json
- 配置/
ThemeController & *Factory
这些非常简单,因为控制器几乎是骨架应用程序提供的原始 IndexController
的克隆。在这种情况下,工厂只做 return 控制器。因此,您可以将它的配置替换为 Zend Framework 3 的 InvokableFactory
的 FQCN,而不是使工厂 class。但是,如果您的 ThemeController
需要一些要求(例如 RegisterForm
),您将需要工厂提供这些。
主题控制器
namespace COMPANY_NAME\Controller;
use Zend\Mvc\Controller\AbstractActionController;
class ThemeController extends AbstractActionController
{
public function indexAction()
{
return [];
}
}
ThemeControllerFactory
namespace COMPANY_NAME\Factory;
use COMPANY_NAME\Controller\ThemeController;
use Zend\ServiceManager\Factory\FactoryInterface;
class ThemeControllerFactory implements FactoryInterface
{
/**
* @param ContainerInterface $container
* @param string $requestedName
* @param array|null $options
* @return ThemeController
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new ThemeController();
}
}
主题作曲家要求
显然您的模块不会有相同的要求。确保你弄清楚它们是什么,每个模块。
对于我自己的主题模块,我的 composer.json
文件中有以下 Zend Framework 要求:
{
"name": "COMPANY_NAME/THEME_MODULE_NAME",
"require": {
"zendframework/zend-di": "*",
"zendframework/zend-navigation": "*",
"zendframework/zend-view": "*",
}
}
在 require
部分我还有:"rwoverdijk/assetmanager": "^1.6",
。该模块用于将所有 CSS、JS(实际上是任何类型)文件混合到一个确定的位置。我建议您看一下 (here)。
答案注释
- 将
COMPANY_NAME
替换为您的 Github 帐户的用户名(如果您使用的是 Bitbucket 或 Gitlab,则为识别帐户名) - 将
THEME_MODULE_NAME
替换为存储库的名称 - If/when 可能,对所需的包使用显式版本(例如
"rwoverdijk/assetmanager": "^1.6"
)。版本锁定可以让你以后省去很多麻烦...
另外:使用包作为 "Theme module" 允许您完全删除最初随 Zend Framework 的骨架应用程序一起提供的 module/
文件夹。但是,特此建议您将 module/
文件夹用于特定于应用程序的模块。如果你为所有东西创建一个包,你很快就会发现自己陷入了维护地狱。
是的,你的布局就是我最后的样子
However, you're hereby advised to use the module/ folder for application specific modules.
某种程度上,我最终将每个特定包(zf2 样式)放入一个文件夹中
- 包文件夹
- composer.json
- Module.php(此为php单元测试)
- public(对于UI包我有这个)
- index.php
- 配置
- application.config.php (显然需要为每个包写每个版本)
- 测试
- 来源
- MODULE_NAME
- 资产
- 来源
- MODULE_NAME
- 控制器
- 服务
- 型号
- { 其他... }
- MODULE_NAME
- 配置
- 查看
- Module.php
- MODULE_NAME
感谢您的澄清和回答。