zoukankan      html  css  js  c++  java
  • Zend-MVC intro

      Zend-MVC intro

      Zend MVC层建立在servicemanager、eventmanager、http、stdlib、几个组件之上。相关组件介绍会在其他文章中详细说明。

      除了以上4大组件外,MVC还暴露了几个sub-components:Router、Controller、Service、View。以下是简单介绍:

    1、Router:将请求匹配给相关的控制器(也可以称之为调度,dispatch)

    2、Controller:是一系列的抽象类,职责有:事件联通、行为调度、控制器插件。

    3、Service:提供一系列的servicemanager工厂,为默认的application工作流程提供定义。

    4、View :提供默认渲染器,视图脚本的解析,helper注册等等。除此之外,还为MVC 工作流程提供监听器。提供如下特性:自动化模版名解析、自动化视图模型创建和注入等等。

      通向MVC的大门时ZendMvcApplication对象。主要职责为:引导资源、路由请求、在路由期间接受且调度匹配到的控制器。上诉职责完成后,将会渲染视图、完成请求并返回应答。

    Application的基础结构:

     1 application_root/
     2     config/
     3         application.config.php
     4         autoload/
     5             global.php
     6             local.php
     7             //etc.
     8     data/
     9     module/
    10     vendor/
    11     public/
    12         .htaccess
    13         index.php
    14     init_autoloader.php

      下面介绍相关作用:

      1、public/index.php:将所有的用户请求排列到你的网站里,从config/application.config.php里面获取配置信息。在返回时,使用run()方法运行Application,处理请求&返回应答。

      2、config/:modulemanager使用该目录下的配置文件来加载模块并且和合并这些配置。

      3、vendor/:你的application依赖的任何第三方模块或库文件都应该在这个目录下。一般来说该目录由Composer来管理。

      4、module/:本目录下可能包含一个或多个模块,这些模块决定了你的application的功能。

    基本模块结构:

      一个模块基本上可以包含任何东西:PHP代码、库代码、视图脚本、公共资产如:图片、CSS、JavaScript。唯一的要求(甚至也是可选的):一个模块担当一个PHP 命名空间,该空间下要包含一个Module类。这个类最终会被modulemanager利用,执行一些任务。

       推荐的模块结构如下:

     1 module_root<name-after-module-namespace>/
     2     Module.php
     3     autoload_classmap.php
     4     autoload_function.php
     5     autoload_register.php
     6     config/
     7         module.config.php
     8     public/
     9         images/
    10         css/
    11         js/
    12     src/
    13         <module_namespace>/
    14             <code file>
    15     test/
    16         phpunit.xml
    17         bootstrap.php
    18         <module_namespace>/
    19             <test code files>
    20     view/
    21         <dir-named-after-module-namespace>/
    22             <dir-named-after-a-conftroller>/
    23                 <.phtml files>

      由于一个模块担当以个命名空间,模块根目录就应该是那个命名空间。这个命名空间也可以包含一个供应商的前缀。比如一个模块的核心是User功能,该模块是由Zend提供的,那么该模块便可以命名为ZendUser。

      上诉结构实际上是一个遵从PSR-0的结构。你也可以使用PSR-4的结构,只要你恰当的设置了autoload。

      Module.php 直接放置在模块的根目录下,其命名空间应为模块担当的命名空间:

    1 namespace ZendUser;
    2 class Module
    3 {
    4 }

    注: Module类的位置:

      如果你定义了autoloader或者使用了Composer的autoloading特性,你就可以把Module.php放在同一个地方。目前推荐的是使用Composer来定义autoloading。

      如果你定义了init()方法,该方法会在加载模块类的时候被modulemanager 监听器触发,并被传入一个ModuleManager实例。这允许你执行类似于设立module-specific的事件监听器的任务。但要小心的是:每一个页面上的每一个模块只要有所请求,init()方法就会被调用。所以该方法因该只执行一些轻量级的任务(比如注册监听器)。相似的onBootstrap()(该方法接受MvcEvent实例)方法被定义时也应该只执行一些轻量级的任务。

      三个autoload_*.php文件并不是必须的。如果你不使用Composer来提供autoload的话,还是推荐使用这三个文件的。

    FILE               Description
    autoload_classmap.php 返回一个类映射的关联数组(name/filename),值filename由__DIR__魔法常量解析。
    autoload_function.php 返回一个php回调函数,这些回调函数可以被传入spl_autoload_register()函数。一般来说,这些回调函数会利用autoload_classmap.php返回的映射。
    autoload_register.php 注册PHP回调函数。(这些回调函数一般由autoload_function.php返回,使用spl_autoload_register()来注册)。

      这三个文件实际上提供了一种自动加载模块里面的类的机制,提供了一中不需要modulemanager也可以使用模块的方法。

      config目录应该包含模块限定的配置。这些文件可以是任何zend-config支持的格式。我们推荐将主配置命名为module.config.<format>(比如基于php的配置:module.config.php)。一般来说你会为router和servicemanager创建配置文件。

      src目录应当符合PSR-0或者PSR-4标准。

      test目录应当包含你的测试单元,一般来讲,可以使用PHPUnit来写。

      public目录应当用来存放你想暴露出来的东西(比如图片,CSS,JavaScript等等)

      view目录包含了与你的控制器相关的视图脚本。

    引导一个Application:

      Application有7个基础依赖:

      1、configuration;

      2、ServiceManager实例;

      3、EventManager实例(默认从ServiceManager中使用服务名“EventManager获取);

      4、SharedEventManager实例(同样从ServiceManager中获取,本实例会被注入   

        EventManager实例中);

      5、ModuleManager实例(获取方式同上);

      6、Request实例(获取方式同上);

      7、Reponse实例(获取方式同上)。

    依赖解决代码如下:

     1 use ZendEventManagerEventManager;
     2 use ZendEventManagerSharedManager;
     3 use ZendHttpPhpEnvironment;
     4 use ZendModuleManagerModuleManager;
     5 use ZendMvcApplication;
     6 use ZendServiceManagerServiceManager;
     7 
     8 $config = include 'config/application.config.php';
     9 $serviceManager = new ServiceManager();
    10 $serviceManger->setService('SharedEventManger', new SharedEventManager();
    11 $serviceManager->setService('ModuleManager', new ModuleManager($config));
    12 $serviceManager->setService('Request', new PhpEnvironmentRequest());
    13 $serviceManager->setService('Reponse',new PhpEnvironmentReponse());
    14 $serviceManager->setFactory('EventManager', function($serviceManager) {
    15     $eventManager = new EventManager();
    16     $eventManager->setSharedManager($serviceMnager->get('SharedEventManager');
    17     return $eventManager;
    18 });
    19 $serviceManager->setShared('EventManager', false);
    20 $application = new Application($config, $serviceManager);

    一旦你解决了依赖,你有两个额外的选择:

    1、引导Application;bootstrap()方法执行的步骤如下:

      连接默认路由(ZendMvcRouteListener);

      连接中间件调度监听器(ZendMvcMiddlewareListener);

      连接默认调度监听器(ZendMvcDispatchListener);

      连接ViewManager监听器(ZendMvcViewViewManager);

      创建MvcEvent,并使用application,request和response注入。此时它也会获取路由器(ZendMvcROuterHttpTreeRouteStack),并连入事件中;

      触发“bootstrap"事件。

      以上只是默认步骤,你也可以通过继承Application来选择你想要执行的步骤。

      2、如果你不想引导Application,有一个可替代的选择。使用配置好的Application,然后调用run()方法。调用该方法会执行如下动作

    触发路由事件;

    接着根据执行情况调度事件;

    触发render事件

    完成后,最后会触发finish事件,并返回应答实例。不论何时有错误发生,dispatch.error事件都会被发生。

      为了引导Application,看似有很多的工作需要做,但实际上你没必要覆盖那么多的服务,直接是用默认的ServiceManager配置便可以了。

    use ZendLoaderAutoloaderFactory;
    use ZendMvcServiceServiceMangerConfig;
    use ZendServiceManagerServiceManger;
    
    //setup autoloader
    AutoloaderFactory::factory();
    
    //get application stack configuratin
    $configuration = include 'config/application.php';

    //setup service manager
    $serviceManager = new ServiceManager(new ServiceManagerConfig());
    $serviceManager->setService('ApplicationConfig', $configuration);

    //load modules --which will provides services, configuration, and more
    $serviceManager->get('ModuleManager')->loadModules();

    //bootstrap and run application
    $application = $serviceManager->get('Application');
    $application->bootstrap();
    $application->run();

      你甚至可以让这更简单一些:我们使用Application里面的init()方法。这是一个快速初始化Application实例的静态方法。

    use ZendLoaderAutoloaderFactory;
    use ZendMvcApplication;
    use ZendMvcServiceServiceManagerConfig;
    use ZendServiceManagerServiceManager;
    
    //setup autoloader
    AutoloaderFactory::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()会执行如下步骤:

      获取application的配置信息,从serviceManager中获取键字,使用默认的服务和刚才的配置创建ServiceManager实例

      使用配置数组创建一个命名为ApplicationConfig的服务

      获取ModuleManager服务,然后加载模块

      bootstrap() Application 并返回实例

     注:关于ApplicationConfig服务:如果你使用了init方法,在你的服务管理配置里将无法指定一个同名的服务。这个名字被保留用作接收来自application.config.php的数组。下列服务只能在application.config.php里面重写:

      ModuleManager

      SharedEventManager

      EventManager

      ZendEventManagerEventManagerInterface

    其他的服务会在模块加载后配置,所以可以在模块里面重写。

    引导一个模块化的Application

      当我们创建模块化的应用实,我们假设配置文件来源于模块本身。我们是如何得到信息并聚合他们的呢?

      答案是通过modulemanager。该组件允许你指定application将要使用的模块。然后他会定位每一个模块并初始化化。模块类可以嵌入到不同的监听器里面来为application提供配置、服务、监听器等等。

    配置Module Manager

    第一步是配置模块管理器。通知模块管理器可以加载哪些模块,为模块监听器提供配置。在application.config.php里面我们有如下代码:

     1 <?php
     2 
     3 //config/application.php
     4 return array[
     5     'modules' => array[
     6     ],
     7     
     8     'module_listener_options' => [
     9         'module_paths' => [
    10             './module',
    11             './vendor',
    12         ]
    13     ]
    14 ];

    每一个想让Application知道配置信息的Module类都应该定义一个getConfig()方法。该方法应该返回一个数组或可遍历的对象(比如ZendConfigConfig实例)

    代码示例

    1 namespace ZendUser;
    2 class Module
    3 {
    4     public function getConfig()
    5     {
    6         return include __DIR__. '/config/module.config.php'
    7     }
    8 }
  • 相关阅读:
    5.22 css和基本选择器
    5.21http网页基础
    ArrayList类源码浅析(二)
    ArrayList类源码浅析(一)
    Long类源码浅析
    Integer类源码浅析
    JDK中String类的源码分析(二)
    JDK中String类的源码分析(一)
    Struts2漏洞修复总结
    [LeetCode]-011-Longest Common Prefix
  • 原文地址:https://www.cnblogs.com/san-fu-su/p/5694960.html
Copyright © 2011-2022 走看看