想,我们在来看模块。模块是构成web应用的基本模块。
基本模块结构
一个模块可以包含任何PHP代码,包括MVC功能,代码库,视图脚本,和共用资源,如图像,CSS和JavaScript。唯一的要求——甚至也是可选的——一个作为PHP命名空间的模块,在此命名空间下需包含一个Module.php类。这个类最终会被用作Zend\ModuleManager执行任务的消费。
推荐的模块结构如下:
module_root<named-after-module-namespace>/ Module.php autoload_classmap.php autoload_function.php autoload_register.php config/ module.config.php public/ images/ css/ js/ src/ <module_namespace>/ <code files> test/ phpunit.xml bootstrap.php <module_namespace>/ <test code files> view/ <dir-named-after-module-namespace>/ <dir-named-after-a-controller>/ <.phtml files>
由于模块作为命名空间,模块的根目录应该为对应的命名空间。命名空间也可包含提供商的前缀。作为示例,由Zend公司提供的以“User”为中心的功能模块,可命名为“ZendUser”,而这同时也是此模块的命名。
模块根目录下的Module.php文件,会定义在如下所示的命名空间内。
12345 | namespace ZendUser;class Module{} |
init()方法被定义时,当完成载入模块类并默认传递Zend\ModuleMananger实例时,这个方法便会被Zend\ModuleManager监听者触发。这就允许你处理如设置特定模块事件监听器等任务。但是需要注意,init()方法被每个模块每个页面所调用,并且只可以用于处理如注册时间监听者等轻量级的任务。同样地,onBootstrap()方法(接收MvcEvent实例)也会被定义,他也会被每个页面所触发,同样只可以用来处理一些轻量级的任务。
下面三个 autoload_*.php文件不是要求的,但是推荐使用。它们提供如下功能:
File | Description |
---|---|
autoload_classmap.php | 返回一个“键名/文件名”的映射表数组(通过魔术__DIR__老解决文件名)。 |
autoload_function.php | 返回一个可通过spl_autoload_register()的PHP回调。通常这个回调应该可利用autoload_classmap.php返回的映射。 |
autoload_register.php | 通过spl_autoload_register()注册PHP回调(通常由autoload_function.php返回)。 |
这三个文件的要点是为自动加载模块中包含的类提供合理的默认机制,从而提供一个简单的方式用以消耗模块,而不必请Zendx\ModuleMangager(如使用ZF2之外的应用)。
config目录应包含任何特定的配置。这些文件可为Zend\Config支持的任何格式。建议将主要的配置命名为“module.format”,对于基于PHP的配置应为“module.config.php”。通常,你可以为路由和依赖注册创建配置。
src目录的源码应为符合PSR-0兼容的目录结构。通常,需要最好要有一个以模块命名空间命名的子目录。当然,如果需要的话,也可存放多个命名空间下的代码。
test目录用来存放单元测试。通常,这些文件是用PHPUnit编写的,并包含其配置(如phpunit.xml,bootstrap.php)。
public目录用户存放可在根目录公开的资源,通常是图像文件,CSS文件,或者JavaScript文件等。这些文件通常对于开发这是公开的。
view目录包含与控制器相关的视图脚本。
引导应用
应用有六个基本依赖。
下面的代码或许是让你满意的实例:
1 2 3 4 5 6 7 8 9101112131415 | use Zend\EventManager\EventManager;use Zend\Http\PhpEnvironment;use Zend\ModuleManager\ModuleManager;use Zend\Mvc\Application;use Zend\ServiceManager\ServiceManager;$config = include 'config/application.config.php';$serviceManager = new ServiceManager();$serviceManager->setService('EventManager', new EventManager());$serviceManager->setService('ModuleManager', new ModuleManager());$serviceManager->setService('Request', new PhpEnvironment\Request());$serviceManager->setService('Response', new PhpEnvironment\Response());$application = new Application($config, $serviceManager); |
一旦你这么做了,你还需要两个额外的操作。第一个是“引导”应用。默认的实现,如下所示:
如果你不希望这些操作,或者想要提供一些替代的操作,你可以扩展Application类并(或)简单的为一希望的实现编写代码。
对于已配置好的应用,你可采取的第二个操作便是run()。调用这个方法便会简单地做到以下几点:触发“路由(route)”事件,其实是“派遣(dispatch)”事件,并取决于执行结果触发“渲染(render)”事件;一切完成后,会触发“完成(finish)”事件,并返回响应实例。无论“路由”或“派遣”哪一个事件出错,都会触发“派遣错误(dispatch.error)”事件。
引导应用要记很多的东西。事实上,我们还没有覆盖到所有可用的服务。使用MVC中默认的ServiceManager配置可以大大简化工作。
1 2 3 4 5 6 7 8 910111213141516171819202122 | use Zend\Loader\AutoloaderFactory;use Zend\Mvc\Service\ServiceManagerConfig;use Zend\ServiceManager\ServiceManager;// setup autoloaderAutoloaderFactory::factory();// get application stack configuration$configuration = include 'config/application.config.php';// setup service manager$serviceManager = new ServiceManager(new ServiceManagerConfig());$serviceManager->setService('ApplicationConfig', $configuration);// load modules -- which will provide services, configuration, and more$serviceManager->get('ModuleManager')->loadModules();// bootstrap and run application$application = $serviceManager->get('Application');$application->bootstrap();$response = $application->run();$response->send(); |
通过使用Appication中的init()方法可使这个事情变得简单。这个静态方法让应用的初始化变得快捷、简单。
1 2 3 4 5 6 7 8 910111213 | use Zend\Loader\AutoloaderFactory;use Zend\Mvc\Application;use Zend\Mvc\Service\ServiceManagerConfig;use Zend\ServiceManager\ServiceManager;// setup autoloaderAutoloaderFactory::factory();// get application stack configuration$configuration = include 'config/application.config.php';// The init() method does something very similar with the previous example.Application::init($configuration)->run(); |
init()方法将做到以下几点:
注意
如果你使用init()方法,在你的服务管理配置中你不能指定名称为“ApplicationConfig”的服务。这个服务保留了application.config.php存储的数组。
以下的服务只可被application.config.php所重写:
其他的服务都是在模块加载后配置的,因而可被模块所重写。
你会注意到,你有大量的工作流程控制权。使用ServiceManager,对于什么服务有效,这些服务如何被实例化,又依赖什么样的注入,你都可进行精细地控制。EventManager的优先级系统使你可以在程序执行过程中拦截任何的应用事件(“引导”,“路由”,“派遣”,“派遣错误”)。这使你可以按照需要来设定你自己的工作流程。
引导模块化应用
之前的工作,配置从何而来?当我们创建一个模块化应用时,假设配置是从模块本身而来。那么我们如何获取到这些信息并对其进行汇总?
答案是通过Zend\ModuleManager\ModuleManager。该组件允许你指定模块的位置。然后,它会找到每一个模块并对其初始化。模块类可与不同的ModuleManager监听者结合,为应用提供配置,服务,监听者等。听起来很复杂?实际上并非如此。
配置模块管理
第一个步骤是配置模块管理器。只需简单地通知模块管理器需载入的模块,可能还需要为模块监听者提供配置。
记得之前的application.config.php?我们将提供一些配置。
1 2 3 4 5 6 7 8 910111213 | <?php// config/application.config.phpreturn array( 'modules' => array( /* ... */ ), 'module_listener_options' => array( 'module_paths' => array( './module', './vendor', ), ),); |
正如我们为系统添加的模块,我们将在modules数组中添加项目。
每个具有配置项的模块类应具有getConfig()方法。该方法应返回一个数组或者Traversable对象,如Zend\Config\Config。来看下面的例子:
123456789 | namespace ZendUser;class Module{ public function getConfig() { return include __DIR__ . '/config/module.config.php' }} |
你可为任务定义一系列的其他方法,从提供自动加载配置,到为ServiceManager提供服务,到监听引导事件。
结论
ZF2 MVC令人难以置信的灵活,他提供了可选择、简单的方式创建模块结构。同样地,通过ServiceManager和EventManager你可以创建自己的工作流程。ModuleManager是轻量级的,且方便用来创建松耦合、代码复用的模块化结构。
联系客服