Project Versions

Table Of Contents

Previous topic

Volt模板引擎

Next topic

路由器(Routing)

This Page

MVC Applications

在 Phalcon 中,所有复杂的MVC相关工作都是由 Phalcon\Mvc\Application 来完成的。该组件封装了所有复杂的后台操作,包括每一个组件的实例化,组件之间的集成等。

Single or Multi Module Applications

使用此组件,您可以运行不同类型的MVC结构:

Single Module

单MVC应用程序只包含一个module,可以使用命名空间,但不是必需的。这样的应用程序的文件结构如下:

single/
    app/
        controllers/
        models/
        views/
    public/
        css/
        img/
        js/

如果不使用命名空间,引导文件被用来协调MVC流程:

<?php

$loader = new \Phalcon\Loader();

$loader->registerDirs(
    array(
        '../apps/controllers/',
        '../apps/models/'
    )
)->register();

$di = new \Phalcon\DI\FactoryDefault();

// Registering the view component
$di->set('view', function() {
    $view = new \Phalcon\Mvc\View();
    $view->setViewsDir('../apps/views/');
    return $view;
});

try {
    $application = new \Phalcon\Mvc\Application();
    $application->setDI($di);
    echo $application->handle()->getContent();
} catch(Phalcon\Exception $e) {
    echo $e->getMessage();
}

如果使用命名空间,引导文件可以这样做:

<?php

$loader = new \Phalcon\Loader();

// Use autoloading with namespaces prefixes
$loader->registerNamespaces(
    array(
        'Single\Controllers' => '../apps/controllers/',
        'Single\Models'      => '../apps/models/',
    )
)->register();

$di = new \Phalcon\DI\FactoryDefault();

// Register the dispatcher setting a Namespace for controllers
// Pay special attention to the double slashes at the end of the
// parameter used in the setDefaultNamespace function
$di->set('dispatcher', function() {
    $dispatcher = new \Phalcon\Mvc\Dispatcher();
    $dispatcher->setDefaultNamespace('Single\Controllers\\');
    return $dispatcher;
});

// Registering the view component
$di->set('view', function() {
    $view = new \Phalcon\Mvc\View();
    $view->setViewsDir('../apps/views/');
    return $view;
});

try {
    $application = new \Phalcon\Mvc\Application();
    $application->setDI($di);
    echo $application->handle()->getContent();
} catch(Phalcon\Exception $e){
    echo $e->getMessage();
}

Multi Module

一个multi-module(多模块)的应用程序是指使用相同的Document Root,但有超过一个module。在这种情况下,程序的文件结构如下:

multiple/
  apps/
    frontend/
       controllers/
       models/
       views/
       Module.php
    backend/
       controllers/
       models/
       views/
       Module.php
  public/
    css/
    img/
    js/

在 apps/ 目录下的每个目录都有自己的MVC结构,Module.php是每个Module特定的设置:

<?php

namespace Multiple\Backend;

use Phalcon\Mvc\ModuleDefinitionInterface;

class Module implements ModuleDefinitionInterface
{

    /**
     * Register a specific autoloader for the module
     */
    public function registerAutoloaders()
    {

        $loader = new \Phalcon\Loader();

        $loader->registerNamespaces(
            array(
                'Multiple\Backend\Controllers' => '../apps/backend/controllers/',
                'Multiple\Backend\Models'      => '../apps/backend/models/',
            )
        );

        $loader->register();
    }

    /**
     * Register specific services for the module
     */
    public function registerServices($di)
    {

        //Registering a dispatcher
        $di->set('dispatcher', function() {
            $dispatcher = new \Phalcon\Mvc\Dispatcher();
            $dispatcher->setDefaultNamespace("Multiple\Backend\Controllers\\");
            return $dispatcher;
        });

        //Registering the view component
        $di->set('view', function() {
            $view = new \Phalcon\Mvc\View();
            $view->setViewsDir('../apps/backend/views/');
            return $view;
        });
    }

}

一个特殊的引导文件,用以载入 multi-module MVC 结构:

<?php

$di = new \Phalcon\DI\FactoryDefault();

//Specify routes for modules
$di->set('router', function () {

    $router = new \Phalcon\Mvc\Router();

    $router->setDefaultModule("frontend");

    $router->add(
        "/login",
        array(
            'module'     => 'backend',
            'controller' => 'login',
            'action'     => 'index',
        )
    );

    $router->add(
        "/admin/products/:action",
        array(
            'module'     => 'backend',
            'controller' => 'products',
            'action'     => 1,
        )
    );

    $router->add(
        "/products/:action",
        array(
            'controller' => 'products',
            'action'     => 1,
        )
    );

    return $router;

});

try {

    //Create an application
    $application = new \Phalcon\Mvc\Application();
    $application->setDI($di);

    // Register the installed modules
    $application->registerModules(
        array(
            'frontend' => array(
                'className' => 'Multiple\Frontend\Module',
                'path'      => '../apps/frontend/Module.php',
            ),
            'backend'  => array(
                'className' => 'Multiple\Backend\Module',
                'path'      => '../apps/backend/Module.php',
            )
        )
    );

    //Handle the request
    echo $application->handle()->getContent();

} catch(Phalcon\Exception $e){
    echo $e->getMessage();
}

如果你想把配置文件完全写入到引导文件,你可以使用一个匿名函数的方式来注册 Module :

<?php

//Creating a view component
$view = new \Phalcon\Mvc\View();

// Register the installed modules
$application->registerModules(
    array(
        'frontend' => function($di) use ($view) {
            $di->setShared('view', function() use ($view) {
                $view->setViewsDir('../apps/frontend/views/');
                return $view;
            });
        },
        'backend' => function($di) use ($view) {
            $di->setShared('view', function() use ($view) {
                $view->setViewsDir('../apps/frontend/views/');
                return $view;
            });
        }
    )
);

Phalcon\Mvc\Application Module注册后,每个匹配的route都必须返回一个有效的module。注册的module都有一个相关的类,用于设置module本身提供的功能。每个module类都必须实现 registerAutoloaders() 和 registerServices() 这两个方法,Phalcon\Mvc\Application 将调用它们执行要执行的module。

了解默认行为

如果你一直关注 tutorial 或 使用 Phalcon Devtools 生成过代码,你可能会熟悉以下的引导文件:

<?php

try {

    // Register autoloaders
    //...

    // Register services
    //...

    // Handle the request
    $application = new \Phalcon\Mvc\Application();
    $application->setDI($di);
    echo $application->handle()->getContent();

} catch (\Phalcon\Exception $e) {
    echo "PhalconException: ", $e->getMessage();
}

所有控制器工作的核心是 handle()方法被调用:

<?php

echo $application->handle()->getContent();

如果您不希望使用 Phalcon\Mvc\Application ,上面的代码可以修改如下:

<?php

// Request the services from the services container
$router = $di->get('router');
$router->handle();

$view = $di->getShared('view');

$dispatcher = $di->get('dispatcher');

// Pass the proccessed router parameters to the dispatcher
$dispatcher->setControllerName($router->getControllerName());
$dispatcher->setActionName($router->getActionName());
$dispatcher->setParams($router->getParams());

// Start the view
$view->start();

// Dispatch the request
$dispatcher->dispatch();

// Render the related views
$view->render(
    $dispatcher->getControllerName(),
    $dispatcher->getActionName(),
    $dispatcher->getParams()
);

// Finish the view
$view->finish();

$response = $di->get('response');

// Pass the output of the view to the response
$response->setContent($view->getContent());

// Send the request headers
$response->sendHeaders();

// Print the response
echo $response->getContent();

尽管上面的代码显得比使用 Phalcon\Mvc\Application 罗唆,但它提供了一种替代bootstrap文件的方式。根据你的需要,你可能希望完全掌握哪些类应该被实例化,或使用自己的组件来扩展默认的功能。

Application Events

Phalcon\Mvc\Application 能够将事件发送到 EventsManager,事件管理器通过触发 “application”来实现,支持以下的事件:

Event Name Triggered
beforeStartModule Before initialize a module, only when modules are registered
afterStartModule After initialize a module, only when modules are registered
beforeHandleRequest Before execute the dispatch loop
afterHandleRequest After execute the dispatch loop

下面的示例演示如何在此组件上添加监听器:

<?php

$eventsManager = new Phalcon\Events\Manager();

$application->setEventsManager($eventsManager);

$eventsManager->attach(
    "application",
    function($event, $application) {
        // ...
    }
);