跳转到内容

应用程序


概览

The Phalcon\Mvc\Application该组件封装了运行MVC应用程序所需的操作。它集成了所有必要的组件和服务,提供了全栈应用程序体验。

快速开始

要快速开始使用Phalcon\Mvc\Application,您可以使用以下代码片段:

<?php

use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Application;

// Create a DI container
$container = new FactoryDefault();

// Create an application instance
$application = new Application($container);

try {
    // Handle the request and send the response
    $response = $application->handle($_SERVER["REQUEST_URI"]);
    $response->send();
} catch (\Exception $e) {
    echo 'Exception: ', $e->getMessage();
}

注意

handle()接受一个URI,并且没有URI将无法运行。你可以通过参数传递$_SERVER["REQUEST_URI"]作为参数

方法

public function __construct(
    DiInterface $container = null
)
构造函数。接受包含相关服务的DI容器

public function getDefaultModule(): string
返回默认的模块名称

public function getEventsManager(): ManagerInterface | null
返回内部事件管理器

public function getModule(
    string $name
): array | object
通过模块名称获取在应用程序中注册的模块定义

public function getModules(): array
返回在应用程序中注册的模块

public function registerModules(
    array $modules, 
    bool $merge = false
): AbstractApplication
注册应用程序中存在的模块数组

$this->registerModules(
    [
        "front" => [
            "className" => \Multi\Front\Module::class,
            "path"      => "../apps/front/Module.php",
        ],
        "back" => [
            "className" => \Multi\Back\Module::class,
            "path"      => "../apps/back/Module.php",
        ],
    ]
);

public function setDefaultModule(
    string $defaultModule
): AbstractApplication
如果路由器没有返回有效的模块,则设置要使用的模块名称

public function setEventsManager(
    ManagerInterface $eventsManager
): void
设置事件管理器

public function handle(
    string $uri
): ResponseInterface | bool
处理MVC请求。接受服务器URI(通常为$_SERVER['REQUEST_URI]`)

public function sendCookiesOnHandleRequest(
    bool $sendCookies
): Application
启用或禁用每次请求处理时发送cookies

public function sendHeadersOnHandleRequest(
    bool $sendHeaders
): Application
启用或禁用每次请求处理时发送头信息

public function useImplicitView(
    bool $implicitView
): Application
此功能默认启用。视图会隐式缓冲所有输出。可以使用此方法完全禁用视图组件

激活

Phalcon\Mvc\Application该方法执行所有必需的工作来整合所有必要组件,使应用程序能够运行。可以通过多种方式引导启动您的应用程序。最常见的方法如下:

<?php

use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Application;

$container = new FactoryDefault();

// Services
// ...

// Create an application instance
$application = new Application($container);

try {
    // Handle the request and send the response
    $response = $application->handle(
        $_SERVER["REQUEST_URI"]
    );
    $response->send();
} catch (\Exception $e) {
    echo 'Exception: ', $e->getMessage();
}

控制器核心工作的发生是在handle()被调用时:

<?php

$response = $application->handle(
    $_SERVER["REQUEST_URI"]
);

手动引导启动

如果您不想使用Phalcon\Mvc\Application,可以根据您的应用程序需求手动处理引导启动过程。以下是几种替代的手动引导启动方法:

标准Web应用程序

<?php

use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Application;

$container = new FactoryDefault();

// Get the 'router' service
$router = $container['router'];

// Handle the request
$router->handle(
    $_SERVER["REQUEST_URI"]
);

// Get the 'view' service
$view = $container['view'];

// Get the 'dispatcher' service
$dispatcher = $container['dispatcher'];

// Set controller, action, and params based on router
$dispatcher->setControllerName(
    $router->getControllerName()
);

$dispatcher->setActionName(
    $router->getActionName()
);

$dispatcher->setParams(
    $router->getParams()
);

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

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

// Render the view with controller, action, and params
$view->render(
    $dispatcher->getControllerName(),
    $dispatcher->getActionName(),
    $dispatcher->getParams()
);

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

// Get the 'response' service
$response = $container['response'];

// Set the response content from the view output
$response->setContent(
    $view->getContent()
);

// Send the response
$response->send();

REST API

<?php

use Phalcon\Di\FactoryDefault;
use Phalcon\Http\ResponseInterface;
use Phalcon\Mvc\Application;

$container = new FactoryDefault();

// Get the 'router' service
$router = $container['router'];

// Handle the request
$router->handle(
    $_SERVER["REQUEST_URI"]
);

// Get the 'dispatcher' service
$dispatcher = $container['dispatcher'];

// Set controller, action, and params based on router
$dispatcher->setControllerName(
    $router->getControllerName()
);

$dispatcher->setActionName(
    $router->getActionName()
);

$dispatcher->setParams(
    $router->getParams()
);

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

// Get the returned value from the dispatcher
$response = $dispatcher->getReturnedValue();

// If the response is an instance of ResponseInterface, send it
if ($response instanceof ResponseInterface) {
    $response->send();
}

捕获异常

<?php

use Phalcon\Di\FactoryDefault;
use Phalcon\Http\ResponseInterface;
use Phalcon\Mvc\Application;
use Phalcon\Mvc\Dispatcher\Exception as DispatcherException;

$container = new FactoryDefault();

// Get the 'router' service
$router = $container['router'];

// Handle the request
$router->handle(
    $_SERVER["REQUEST_URI"]
);

// Get the 'dispatcher' service
$dispatcher = $container['dispatcher'];

// Set controller, action, and params based on router
$dispatcher->setControllerName(
    $router->getControllerName()
);

$dispatcher->setActionName(
    $router->getActionName()
);

$dispatcher->setParams(
    $router->getParams()
);

try {
    // Dispatch the request
    $dispatcher->dispatch();
} catch (DispatcherException $e) {
    // Handle exceptions, for example,
    // forward to a 503 error page
    $dispatcher->setControllerName('errors');
    $dispatcher->setActionName('action503');
    $dispatcher->dispatch();
}

// Get the returned value from the dispatcher
$response = $dispatcher->getReturnedValue();

// If the response is an instance of
// `ResponseInterface`, send it
if ($response instanceof ResponseInterface) {
    $response->send();
}

选择最适合您应用程序需求的选项。根据您的要求,您可以完全控制实例化和组件替换以扩展默认功能。手动引导启动方法应与您的具体使用场景相匹配。

单模块 - 多模块

Phalcon\Mvc\Application支持单模块和多模块MVC结构。

单模块

在单模块MVC应用程序中,只有一个模块。命名空间是可选的。其结构通常如下所示:

single/
    app/
        controllers/
        models/
        views/
    public/
        css/
        img/
        js/
如果未使用命名空间,引导文件可能如下所示:

<?php

use Phalcon\Di\FactoryDefault;
use Phalcon\Autoload\Loader;
use Phalcon\Mvc\Application;
use Phalcon\Mvc\View;

$loader = new Loader();
$loader->setDirectories(
    [
        '../apps/controllers/',
        '../apps/models/',
    ]
);
$loader->register();

$container = new FactoryDefault();

$container->set(
    'view', 
    function () {
        $view = new View();
        $view->setViewsDir('../apps/views/');

        return $view;
    }
);

$application = new Application($container);

try {
    // Handle the request and send the response
    $response = $application->handle(
        $_SERVER["REQUEST_URI"]
    );
    $response->send();
} catch (\Exception $e) {
    echo 'Exception: ', $e->getMessage();
}
如果使用了命名空间,引导文件会有轻微变化:

<?php

use Phalcon\Di\FactoryDefault;
use Phalcon\Autoload\Loader;
use Phalcon\Mvc\Application;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\View;

$loader = new Loader();
$loader->setNamespaces(
    [
        'Single\Controllers' => '../apps/controllers/',
        'Single\Models'      => '../apps/models/',
    ]
);
$loader->register();

$container = new FactoryDefault();

$container->set('dispatcher', function () {
    $dispatcher = new Dispatcher();
    $dispatcher->setDefaultNamespace('Single\Controllers');

    return $dispatcher;
});

$container->set('view', function () {
    $view = new View();
    $view->setViewsDir('../apps/views/');

    return $view;
});

$application = new Application($container);

try {
    // Handle the request and send the response
    $response = $application->handle(
        $_SERVER["REQUEST_URI"]
    );
    $response->send();
} catch (\Exception $e) {
    echo 'Exception: ', $e->getMessage();
}

多模块

多模块应用程序在一个共享文档根目录下使用多个模块。模块有助于组织组件、增强可维护性并隔离功能。每个模块必须实现Phalcon\Mvc\ModuleDefinitionInterface以确保正常的功能。目录结构通常包括在apps/目录中的子目录,其中每个子目录都有自己的MVC结构。此外,每个模块目录包含一个Module.php文件用于配置模块特定的设置,如自动加载器和自定义服务。

目录结构

multiple/
  apps/
    front/
       controllers/
       models/
       views/
       Module.php
    back/
       controllers/
       models/
       views/
       Module.php
  public/
    css/
    img/
    js/
在每个模块目录中,Module.php文件负责注册特定模块的自动加载器和服务。以下是一个示例Module.php文件针对Multi\Back模块:

<?php

namespace Multi\Back;

use Phalcon\Autoload\Loader;
use Phalcon\Di\DiInterface;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\ModuleDefinitionInterface;
use Phalcon\Mvc\View;

class Module implements ModuleDefinitionInterface
{
    public function registerAutoloaders(DiInterface $container = null)
    {
        $loader = new Loader();
        $loader->setNamespaces(
            [
                'Multi\Back\Controllers' => '../apps/back/controllers/',
                'Multi\Back\Models'      => '../apps/back/models/',
            ]
        );

        $loader->register();
    }

    public function registerServices(DiInterface $container)
    {
        // Dispatcher
        $container->set(
            'dispatcher',
            function () {
                $dispatcher = new Dispatcher();
                $dispatcher->setDefaultNamespace(
                    'Multi\Back\Controllers'
                );

                return $dispatcher;
            }
        );

        // View
        $container->set(
            'view',
            function () {
                $view = new View();
                $view->setViewsDir(
                    '../apps/back/views/'
                );

                return $view;
            }
        );
    }
}

多模块架构的引导文件对于多模块MVC架构,引导文件需要进行稍微修改的设置。路由器需要显式配置,并向应用程序注册模块。以下是一个示例的引导文件:

<?php

use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Application;
use Phalcon\Mvc\Router;

$container = new FactoryDefault();

$container->set(
    'router',
    function () {
        $router = new Router();

        $router->setDefaultModule('front');

        $router->add(
            '/login',
            [
                'module'     => 'back',
                'controller' => 'login',
                'action'     => 'index',
            ]
        );

        $router->add(
            '/admin/products/:action',
            [
                'module'     => 'back',
                'controller' => 'products',
                'action'     => 1,
            ]
        );

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

        return $router;
    }
);

$application = new Application($container);

$application->registerModules(
    [
        'front' => [
            'className' => \Multi\Front\Module::class,
            'path'      => '../apps/front/Module.php',
        ],
        'back'  => [
            'className' => \Multi\Back\Module::class,
            'path'      => '../apps/back/Module.php',
        ]
    ]
);

try {
    $response = $application->handle(
        $_SERVER["REQUEST_URI"]
    );

    $response->send();
} catch (\Exception $e) {
    echo $e->getMessage();
}
或者,您可以使用匿名函数在引导文件中保留模块配置以注册模块。以下是一个示例:

<?php

use Phalcon\Mvc\View;

$view = new View();

// ...

$application->registerModules(
    [
        'front' => function ($container) use ($view) {
            $container->setShared(
                'view',
                function () use ($view) {
                    $view->setViewsDir(
                        '../apps/front/views/'
                    );

                    return $view;
                }
            );
        },
        'back' => function ($container) use ($view) {
            $container->setShared(
                'view',
                function () use ($view) {
                    $view->setViewsDir(
                        '../apps/back/views/'
                    );

                    return $view;
                }
            );
        }
    ]
);
Phalcon\Mvc\Application注册了模块后,每个匹配的路由都必须返回一个有效的模块。每个已注册模块都有一个关联的类,该类暴露用于模块设置的方法。

模块定义类必须实现两个方法:registerAutoloaders()registerServices()。这些方法将由Phalcon\Mvc\Application相应地调用。

异常

Phalcon\Mvc\Application组件中抛出的任何异常类型为Phalcon\Mvc\Application\ExceptionPhalcon\Application\Exception。你可以使用此异常选择性地捕获仅从此组件抛出的异常。

<?php

use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Application;
use Phalcon\Mvc\Application\Exception;

try {
    $container   = new FactoryDefault();

    // ...

    $application = new Application($container);
    $application->registerModules(
        [
            'front' => false,
        ]
    );

    $response = $application->handle(
        $_SERVER["REQUEST_URI"]
    );

    $response->send();
} catch (Exception $e) {
    echo $e->getMessage();
}

事件

Phalcon\Mvc\Application可以向EventsManager发送事件(如果存在的话)。事件使用application类型触发。支持的事件包括:

事件名称 触发时机
boot 当应用程序处理第一个请求时执行
beforeStartModule 在初始化模块之前触发,仅当注册了模块时
afterStartModule 在初始化模块之后触发,仅当注册了模块时
beforeHandleRequest 在执行分发循环之前触发
afterHandleRequest 在执行分发循环之后触发

以下是如何附加监听器到该组件的示例:

<?php

use Phalcon\Events\Event;
use Phalcon\Events\Manager;

$manager = new Manager();

$application->setEventsManager($manager);

$manager->attach(
    'application',
    function (Event $event, $application) {
        // ...
    }
);

外部资源

无噪 Logo
无噪文档
25 年 6 月翻译
版本号 5.9
文档源↗