[TOC]
# MVC 应用
在Phalcon中编排MVC操作的所有艰苦工作通常由`Phalcon\Mvc\Application`完成。该组件封装了后台所需的所有复杂操作,实例化了所需的每个组件并将其与项目集成,以允许MVC模式按需运行。
以下引导代码是Phalcon应用程序的典型代码:
```php
<?php
use Phalcon\Mvc\Application;
// 注册自动加载器
// ...
// 注册服务
// ...
// 处理请求
$application = new Application($di);
try {
$response = $application->handle();
$response->send();
} catch (\Exception $e) {
echo 'Exception: ', $e->getMessage();
}
```
调用`handle()`时是控制器的所有工作的核心:
```php
<?php
$response = $application->handle();
```
## 手动引导
如果您不想使用`Phalcon\Mvc\Application`,可以按如下方式更改上面的代码:
```php
<?php
// 获取 router 服务
$router = $di['router'];
$router->handle();
$view = $di['view'];
$dispatcher = $di['dispatcher'];
// 将已处理的路由器参数传递给调度程序
$dispatcher->setControllerName(
$router->getControllerName()
);
$dispatcher->setActionName(
$router->getActionName()
);
$dispatcher->setParams(
$router->getParams()
);
// 开始视图
$view->start();
// 发送请求
$dispatcher->dispatch();
// 呈现相关视图
$view->render(
$dispatcher->getControllerName(),
$dispatcher->getActionName(),
$dispatcher->getParams()
);
// 结束视图
$view->finish();
$response = $di['response'];
// 将视图的输出传递给响应
$response->setContent(
$view->getContent()
);
// 发送响应
$response->send();
```
以下替换`Phalcon\Mvc\Application`缺少一个视图组件,使其适用于Rest API:
```php
<?php
use Phalcon\Http\ResponseInterface;
// 获取 router 服务
$router = $di['router'];
$router->handle();
$dispatcher = $di['dispatcher'];
// 将已处理的路由器参数传递给调度程序
$dispatcher->setControllerName(
$router->getControllerName()
);
$dispatcher->setActionName(
$router->getActionName()
);
$dispatcher->setParams(
$router->getParams()
);
// 发送请求
$dispatcher->dispatch();
// 通过上次执行的操作获取返回值
$response = $dispatcher->getReturnedValue();
// 检查返回的操作是否为“响应”对象
if ($response instanceof ResponseInterface) {
// 发送响应
$response->send();
}
```
另一种替代方法是捕获调度员转发到其他操作时产生的异常:
```php
<?php
use Phalcon\Http\ResponseInterface;
// 获取 router 服务
$router = $di['router'];
$router->handle();
$dispatcher = $di['dispatcher'];
// 将已处理的路由器参数传递给调度程序
$dispatcher->setControllerName(
$router->getControllerName()
);
$dispatcher->setActionName(
$router->getActionName()
);
$dispatcher->setParams(
$router->getParams()
);
try {
// 发送请求
$dispatcher->dispatch();
} catch (Exception $e) {
// 发生异常,发送一些针对此的控制器/操作
// 将已处理的路由器参数传递给调度程序
$dispatcher->setControllerName('errors');
$dispatcher->setActionName('action503');
// 发送请求
$dispatcher->dispatch();
}
// 通过上次执行的操作获取返回值
$response = $dispatcher->getReturnedValue();
// 检查返回的操作是否为“响应”对象
if ($response instanceof ResponseInterface) {
// 发送响应
$response->send();
}
```
虽然上述实现比使用`Phalcon\Mvc\Application`时所需的代码要冗长得多,但在引导应用程序时提供了另一种选择。根据您的需要,您可能希望完全控制应该实例化的内容,或者使用您自己的组件替换某些组件以扩展默认功能。
## 单/多模块应用
使用此组件,您可以运行各种类型的MVC结构:
### 单模块
单个MVC应用程序仅包含一个模块。可以使用命名空间,但不是必需的。像这样的应用程序将具有以下文件结构:
```php
single/
app/
controllers/
models/
views/
public/
css/
img/
js/
```
如果未使用名称空间,则可以使用以下引导文件来编排MVC流:
```php
<?php
use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\Mvc\Application;
use Phalcon\Di\FactoryDefault;
$loader = new Loader();
$loader->registerDirs(
[
'../apps/controllers/',
'../apps/models/',
]
);
$loader->register();
$di = new FactoryDefault();
// 注册视图组件
$di->set(
'view',
function () {
$view = new View();
$view->setViewsDir('../apps/views/');
return $view;
}
);
$application = new Application($di);
try {
$response = $application->handle();
$response->send();
} catch (\Exception $e) {
echo $e->getMessage();
}
```
如果使用名称空间,可以使用以下引导程序:
```php
<?php
use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\Application;
use Phalcon\Di\FactoryDefault;
$loader = new Loader();
// 使用带名称空间前缀的自动加载
$loader->registerNamespaces(
[
'Single\Controllers' => '../apps/controllers/',
'Single\Models' => '../apps/models/',
]
);
$loader->register();
$di = new FactoryDefault();
// 为控制器注册默认调度程序的命名空间
$di->set(
'dispatcher',
function () {
$dispatcher = new Dispatcher();
$dispatcher->setDefaultNamespace('Single\Controllers');
return $dispatcher;
}
);
// 注册视图组件
$di->set(
'view',
function () {
$view = new View();
$view->setViewsDir('../apps/views/');
return $view;
}
);
$application = new Application($di);
try {
$response = $application->handle();
$response->send();
} catch (\Exception $e) {
echo $e->getMessage();
}
```
### 多模块
多模块应用程序对多个模块使用相同的文档根。在这种情况下,可以使用以下文件结构:
```php
multiple/
apps/
frontend/
controllers/
models/
views/
Module.php
backend/
controllers/
models/
views/
Module.php
public/
css/
img/
js/
```
apps/ 中的每个目录都有自己的MVC结构。`Module.php`用于配置每个模块的特定设置,如自动加载器或自定义服务:
```php
<?php
namespace Multiple\Backend;
use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\DiInterface;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\ModuleDefinitionInterface;
class Module implements ModuleDefinitionInterface
{
/**
* 注册模块的特定自动加载
*/
public function registerAutoloaders(DiInterface $di = null)
{
$loader = new Loader();
$loader->registerNamespaces(
[
'Multiple\Backend\Controllers' => '../apps/backend/controllers/',
'Multiple\Backend\Models' => '../apps/backend/models/',
]
);
$loader->register();
}
/**
* 注册模块的特定服务
*/
public function registerServices(DiInterface $di)
{
// 注册调度器
$di->set(
'dispatcher',
function () {
$dispatcher = new Dispatcher();
$dispatcher->setDefaultNamespace('Multiple\Backend\Controllers');
return $dispatcher;
}
);
// 注册视图组件
$di->set(
'view',
function () {
$view = new View();
$view->setViewsDir('../apps/backend/views/');
return $view;
}
);
}
}
```
加载多模块MVC架构需要特殊的引导程序文件:
```php
<?php
use Phalcon\Mvc\Router;
use Phalcon\Mvc\Application;
use Phalcon\Di\FactoryDefault;
$di = new FactoryDefault();
// 指定模块的路由
$di->set(
'router',
function () {
$router = new Router();
$router->setDefaultModule('frontend');
$router->add(
'/login',
[
'module' => 'backend',
'controller' => 'login',
'action' => 'index',
]
);
$router->add(
'/admin/products/:action',
[
'module' => 'backend',
'controller' => 'products',
'action' => 1,
]
);
$router->add(
'/products/:action',
[
'controller' => 'products',
'action' => 1,
]
);
return $router;
}
);
// 创建一个应用
$application = new Application($di);
// 注册已安装的模块
$application->registerModules(
[
'frontend' => [
'className' => 'Multiple\Frontend\Module',
'path' => '../apps/frontend/Module.php',
],
'backend' => [
'className' => 'Multiple\Backend\Module',
'path' => '../apps/backend/Module.php',
]
]
);
try {
// 处理请求
$response = $application->handle();
$response->send();
} catch (\Exception $e) {
echo $e->getMessage();
}
```
如果要在引导文件中维护模块配置,可以使用匿名函数注册模块:
```php
<?php
use Phalcon\Mvc\View;
// 创建一个视图组件
$view = new View();
// 给视图组件设置参数
// ...
// 注册已安装的模块
$application->registerModules(
[
'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/backend/views/');
return $view;
}
);
}
]
);
```
当`Phalcon\Mvc\Application`注册了模块时,每个匹配的路由都必须返回一个有效的模块。每个注册的模块都有一个关联的类,它提供了设置模块本身的功能。每个模块类定义必须实现两个方法:`registerAutoloaders()`和`registerServices()`,它们将由`Phalcon\Mvc\Application`根据要执行的模块调用。
## 应用事件
`Phalcon\Mvc\Application` 能够将事件发送到EventsManager(如果存在)。使用类型`application`触发事件。支持以下事件:
| 事件名称 | Triggered |
| --------------------- | -------------------------------- |
| `boot` | 在应用程序处理其第一个请求时执行 |
| `beforeStartModule` | 在初始化模块之前,仅在注册模块时 |
| `afterStartModule` | 在初始化模块之后,仅在注册模块时 |
| `beforeHandleRequest` | 在执行调度循环之前 |
| `afterHandleRequest` | 在执行调度循环之后 |
以下示例演示如何将侦听器附加到此组件:
```php
<?php
use Phalcon\Events\Event;
use Phalcon\Events\Manager as EventsManager;
$eventsManager = new EventsManager();
$application->setEventsManager($eventsManager);
$eventsManager->attach(
'application',
function (Event $event, $application) {
// ...
}
);
```
## 外部资源
* [MVC examples on Github](https://github.com/phalcon/mvc)
- 常规
- Welcome
- 贡献
- 生成回溯
- 测试重现
- 单元测试
- 入门
- 安装
- Web服务器设置
- WAMP
- XAMPP
- 教程
- 基础教程
- 教程:创建一个简单的REST API
- 教程:Vökuró
- 提升性能
- 教程:INVO
- 开发环境
- Phalcon Compose (Docker)
- Nanobox
- Phalcon Box (Vagrant)
- 开发工具
- Phalcon开发者工具的安装
- Phalcon开发者工具的使用
- 调试应用程序
- 核心
- MVC应用
- 微应用
- 创建命令行(CLI)应用程序
- 依赖注入与服务定位
- MVC架构
- 服务
- 使用缓存提高性能
- 读取配置
- 上下文转义
- 类加载器
- 使用命名空间
- 日志
- 队列
- 数据库
- 数据库抽象层
- Phalcon查询语言(PHQL)
- ODM(对象文档映射器)
- 使用模型
- 模型行为
- ORM缓存
- 模型事件
- 模型元数据
- 模型关系
- 模型事务
- 验证模型
- 数据库迁移
- 分页
- 前端
- Assets管理
- 闪存消息
- 表单
- 图像
- 视图助手(标签)
- 使用视图
- Volt:模板引擎
- 业务逻辑
- 访问控制列表(ACL)
- 注解解析器
- 控制器
- 调度控制器
- 事件管理器
- 过滤与清理
- 路由
- 在session中存储数据
- 生成URL和路径
- 验证
- HTTP
- Cookies管理
- 请求环境
- 返回响应
- 安全
- 加密/解密
- 安全
- 国际化
- 国际化
- 多语言支持