发布于 2015-08-21 15:17:10 | 345 次阅读 | 评论: 0 | 来源: 网络整理
在Phalcon,策划MVC操作背后的全部困难工作通常都可以 通过 PhalconMvcApplication 做到。这个组件封装了全部后端所需要的复杂 操作,实例化每一个需要用到的组件并与项目整合在一起,从而使得MVC模式可以如期地运行。
通过这个组件,你可以运行各式各样的MVC结构:
单一的MVC应用仅仅包含了一个模块。可以使用命名空间,但不是必需的。 这样类型的应用可能会有以下文件目录结构:
single/
app/
controllers/
models/
views/
public/
css/
img/
js/
如果未使用命名空间,以下的启动文件可用于编排MVC工作流:
<?php
use PhalconLoader;
use PhalconMvcView;
use PhalconMvcApplication;
use PhalconDIFactoryDefault;
$loader = new Loader();
$loader->registerDirs(
array(
'../apps/controllers/',
'../apps/models/'
)
)->register();
$di = new FactoryDefault();
// 注册视图组件
$di->set('view', function () {
$view = new View();
$view->setViewsDir('../apps/views/');
return $view;
});
try {
$application = new Application($di);
echo $application->handle()->getContent();
} catch (Exception $e) {
echo $e->getMessage();
}
如果使用了命名空间,则可以使用以下启动文件(译者注:主要区别在于使用$loader的方式):
<?php
use PhalconLoader;
use PhalconMvcView;
use PhalconMvcDispatcher;
use PhalconMvcApplication;
use PhalconDIFactoryDefault;
$loader = new Loader();
// 根据命名空间前缀加载
$loader->registerNamespaces(
array(
'SingleControllers' => '../apps/controllers/',
'SingleModels' => '../apps/models/',
)
)->register();
$di = new FactoryDefault();
// 注册调度器,并设置控制器的默认命名空间
$di->set('dispatcher', function () {
$dispatcher = new Dispatcher();
$dispatcher->setDefaultNamespace('SingleControllers');
return $dispatcher;
});
// 注册视图组件
$di->set('view', function () {
$view = new View();
$view->setViewsDir('../apps/views/');
return $view;
});
try {
$application = new Application($di);
echo $application->handle()->getContent();
} catch (Exception $e) {
echo $e->getMessage();
}
多模块的应用使用了相同的文档根目录但拥有多个模块。在这种情况下,可以使用以下的文件目录结构:
multiple/
apps/
frontend/
controllers/
models/
views/
Module.php
backend/
controllers/
models/
views/
Module.php
public/
css/
img/
js/
在apps/下的每一个目录都有自己的MVC结构。Module.php文件代表了各个模块不同的配置,如自动加载器和自定义服务:
<?php
namespace MultipleBackend;
use PhalconLoader;
use PhalconMvcView;
use PhalconMvcDispatcher;
use PhalconMvcModuleDefinitionInterface;
class Module implements ModuleDefinitionInterface
{
/**
* 注册自定义加载器
*/
public function registerAutoloaders()
{
$loader = new Loader();
$loader->registerNamespaces(
array(
'MultipleBackendControllers' => '../apps/backend/controllers/',
'MultipleBackendModels' => '../apps/backend/models/',
)
);
$loader->register();
}
/**
* 注册自定义服务
*/
public function registerServices($di)
{
// Registering a dispatcher
$di->set('dispatcher', function () {
$dispatcher = new Dispatcher();
$dispatcher->setDefaultNamespace("MultipleBackendControllers");
return $dispatcher;
});
// Registering the view component
$di->set('view', function () {
$view = new View();
$view->setViewsDir('../apps/backend/views/');
return $view;
});
}
}
还需要一个指定的启动文件来加载多模块的MVC架构:
<?php
use PhalconMvcRouter;
use PhalconMvcApplication;
use PhalconDIFactoryDefault;
$di = new FactoryDefault();
// 自定义路由
$di->set('router', function () {
$router = new 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 {
// 创建应用
$application = new Application($di);
// 注册模块
$application->registerModules(
array(
'frontend' => array(
'className' => 'MultipleFrontendModule',
'path' => '../apps/frontend/Module.php',
),
'backend' => array(
'className' => 'MultipleBackendModule',
'path' => '../apps/backend/Module.php',
)
)
);
// 处理请求
echo $application->handle()->getContent();
} catch (Exception $e) {
echo $e->getMessage();
}
如果你想在启动文件保持模块的配置,你可以使用匿名函数来注册对应的模块:
<?php
use PhalconMvcView;
// 创建视图组件
$view = new 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/backend/views/');
return $view;
});
}
)
);
当 PhalconMvcApplication 有多个模块注册时,通常 每个都是需要的,以便每一个被匹配到的路由都能返回一个有效的模块。每个已经注册的模块都有一个相关的类来提供建立和启动自身的函数。 而每个模块定义的类都必须实现registerAutoloaders()和registerServices()这两个方法,这两个函数会在模块即被执行时被
如果你已经看过了 tutorial 或者已经通过 Phalcon Devtools 生成了代码, 你将很容易识别以下的启动文件:
<?php
try {
// 注册自动加载器
// ...
// 注册服务
// ...
// 处理请求
$application = new PhalconMvcApplication($di);
echo $application->handle()->getContent();
} catch (Exception $e) {
echo "Exception: ", $e->getMessage();
}
控制器中全部核心的工作都会在handle()被回调时触发执行。
<?php
echo $application->handle()->getContent();
如果你不想使用 PhalconMvcApplication ,以上的代码可以改成这样:
<?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->sendHeaders();
// 输出响应内容
echo $response->getContent();
以下代码替换了 PhalconMvcApplication ,虽然缺少了视图组件, 但却更适合Rest风格的API接口:
<?php
// 获取 '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();
// 判断结果是否是 'response' 对象
if ($response instanceof PhalconHttpResponseInterface) {
// 发送响应
$response->send();
}
另外一个修改就是在分发器中对抛出异常的捕捉可以将请求转发到其他的操作:
<?php
// 获取 '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) {
// An exception has occurred, dispatch some controller/action aimed for that
// Pass the processed router parameters to the dispatcher
$dispatcher->setControllerName('errors');
$dispatcher->setActionName('action503');
// Dispatch the request
$dispatcher->dispatch();
}
// 获取最后的返回结果
$response = $dispatcher->getReturnedValue();
// 判断结果是否是 'response' 对象
if ($response instanceof PhalconHttpResponseInterface) {
// 发送响应
$response->send();
}
尽管上面的代码比使用 PhalconMvcApplication 而需要的代码远远要累赘得很, 但它为启动你的应用提供了一个可修改、可定制化的途径。 因为根据你的项目需要,你可以想对实例什么和不实例化什么进行完全的控制,或者想用你自己的组件来替代那些确定和必须的组件从而扩展默认的功能。
PhalconMvcApplication 可以把事件发送到 EventsManager (如果它激活的话)。 事件将被当作”application”类型被消费掉。目前已支持的事件如下:
事件名称 | 消费于 |
---|---|
boot | 当应用处理它首个请求时被执行 |
beforeStartModule | 在初始化模块之前,仅当模块被注册时 |
afterStartModule | 在初始化模块之后,仅当模块被注册时 |
beforeHandleRequest | 在执行分发环前 |
afterHandleRequest | 在执行分发环后 |
以下示例演示了如何将侦听器绑定到组件:
<?php
use PhalconEventsManager as EventsManager;
$eventsManager = new EventsManager();
$application->setEventsManager($eventsManager);
$eventsManager->attach(
"application",
function ($event, $application) {
// ...
}
);