MVC应用
最后更新于:2022-04-02 05:13:44
[TOC]
# MVC 应用
在Phalcon中编排MVC操作的所有艰苦工作通常由`Phalcon\Mvc\Application`完成。该组件封装了后台所需的所有复杂操作,实例化了所需的每个组件并将其与项目集成,以允许MVC模式按需运行。
以下引导代码是Phalcon应用程序的典型代码:
```php
handle();
$response->send();
} catch (\Exception $e) {
echo 'Exception: ', $e->getMessage();
}
```
调用`handle()`时是控制器的所有工作的核心:
```php
handle();
```
## 手动引导
如果您不想使用`Phalcon\Mvc\Application`,可以按如下方式更改上面的代码:
```php
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
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
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
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
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
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
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
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
setEventsManager($eventsManager);
$eventsManager->attach(
'application',
function (Event $event, $application) {
// ...
}
);
```
## 外部资源
* [MVC examples on Github](https://github.com/phalcon/mvc)
';