处理Phalcon控制器中的视图

时间:2017-12-07 02:32:35

标签: php model-view-controller phalcon

我正在开发一个新创建的Phalcon项目,我真的不知道如何实际使用多个视图。

什么是切入点?我真的不知道控制器中的每个方法何时被调用,在哪种情况下等等。

控制流程定义在哪里?它是基于视图的名称?或者有一个地方可以注册吗?

2 个答案:

答案 0 :(得分:2)

Phalcon与其他众所周知的PHP框架略有不同,因为默认情况下预配置或预先构建的框架并不多。它松散耦合。因此,您必须决定控制流的工作位置和方式。这意味着您需要深入挖掘文档,并且可能有不同的方法来实现相同的目标。

我将引导您完成一个简单的示例并提供参考资料,以便您了解更多信息。

1)首先定义一个定义路由或入口点的引导文件(或多个文件),然后设置并创建应用程序。此引导文件可以由index.php文件调用,该文件是Web服务器提供的默认文件。下面是一个示例,说明这样的引导程序文件将如何定义路由或入口点(注意:这些只是片段,并不代表引导程序文件应该执行的所有操作):

use Phalcon\Di\FactoryDefault;

// initializes the dependency injector of Phalcon framework
$injector = new FactoryDefault();

// defines the routes
$injector->setShared('router', function () {
    return require_once('some/path/routes.php');
});

然后是routes.php文件:

use Phalcon\Mvc\Router;
use Phalcon\Mvc\Router\Group as RouterGroup;

// instantiates the router
$router = new Router(false);
// defines routes for the 'users' controller
$user_routes = new RouterGroup(['controller' => 'users']);
$user_routes->setPrefix('/users');
$user_routes->addGet('/show/{id:[0-9]{1,9}}', ['action' => 'show']);
$router->mount($user_routes);
return $router;

我通过定义路线组以另一种方式定义路线。我发现按资源或控制器组织路由更容易。

2)当您输入网址example.com/users/show/123时,上面的路线会将其与控制器users和操作show相匹配。这是由代码块['controller' => 'users']setPrefix('/users')'/show/{id:[0-9]{1,9}}', ['action' => 'show']

指定的

3)所以现在你创建了控制器。您可以创建一个文件,例如controllers/UsersController.php。然后你创造它的行动;记下您在路线中使用的名称(show)和后缀Action

public function showAction(int $id) {
    // ... do all you need to do...

    // fetch data
    $user = UserModel::findFirst(blah blah);

    // pass data to view
    $this->view->setVar('user', $user);

    // Phalcon automatically calls the view; from the manual:
    /*
    Phalcon automatically passes the execution to the view component as soon as a particular
    controller has completed its cycle. The view component will look in the views folder for
    a folder named as the same name of the last controller executed and then for a file named
    as the last action executed.
    */

    // but in case you would need to specify a different one
    $this->view->render('users', 'another_view');
}

还有更多与视图相关的内容;请参阅手册。

请注意,您需要在bootstrap文件中注册这样的控制器(我还包括如何注册其他内容的示例):

use Phalcon\Loader;
// registers namespaces and other classes
$loader = new Loader();
$loader->registerNamespaces([
    'MyNameSpace\Controllers' => 'path/controllers/',
    'MyNameSpace\Models' => 'path/models/',
    'MyNameSpace\Views' => 'path/views/'
]);
$loader->register();

4)您还需要为视图注册一些内容。在引导程序文件中

use Phalcon\Mvc\View;

$injector->setShared('view', function () {
    $view = new View();
    $view->setViewsDir('path/views/');
    return $view;
});

这一点,以及您需要做的其他事情,特别是在引导过程中,将使您开始向控制器发送请求以及路由中定义的操作/视图。

那是基本的例子。还有更多你需要学习的东西,因为我只给你一些东西让你开始。所以这里有一些链接可以解释更多。请记住,在Phalcon中有几种不同的方法可以实现相同的目的。

自举:

https://docs.phalconphp.com/en/3.2/di

https://docs.phalconphp.com/en/3.2/loader

https://docs.phalconphp.com/en/3.2/dispatcher

路由:https://docs.phalconphp.com/en/3.2/routing

控制器:https://docs.phalconphp.com/en/3.2/controllers

有关视图的更多信息(从注册到将数据传递给它们,模板化等等):https://docs.phalconphp.com/en/3.2/views

一个简单的教程,教你一些基本的东西:https://docs.phalconphp.com/en/3.2/tutorial-rest

答案 1 :(得分:1)

应用程序从路由阶段开始。从那里你从路由器获取控制器和动作,并将其提供给调度员。您设置视图然后调用执行调度程序,以便它访问您的控制器的操作。从那里创建一个新的响应对象并将其内容设置为等于视图请求,最后将响应发送到客户端的浏览器 - 包括内容和标题。通过Phalcon做到这一点是个好主意,而不是直接回应或使用PHP的标题(),所以只有在你调用$response->send();时才这样做。这是最好的做法,因为它允许你创建测试,例如在phpunit中,这样你可以测试标题或内容的存在,同时移动到下一个响应和标题,而不实际发送任何东西,所以你可以测试东西。在代码中使用exit;的相同想法最好避免,因此您可以编写测试并继续进行下一个测试,而不会因为退出存在而在第一次测试中中止测试。

就Phalcon应用程序的工作方式以及步骤而言,通过查看手动引导来跟踪流程要容易得多: https://docs.phalconphp.com/en/3.2/application#manual-bootstrapping

Phalcon的核心是DI,即依赖注入容器。这允许您创建服务,并将它们存储在DI上,以便服务可以相互访问。您可以创建自己的服务并在DI上以您自己的名义存储它们,所使用的名称没有什么特别之处。但是,根据您使用的Phalcon的区域,DI上的某些服务被假定为" db"用于与数据库交互。注释服务可以设置为共享或不在DI上共享。共享意味着它实现单例并在之后为所有调用保持对象处于活动状态。如果你使用getShared,它就会做类似的事情,即使它最初不是共享服务。 getShared方法被认为是不好的做法,Phalcon团队正在讨论在未来的Phalcon版本中删除该方法。请改为依赖setShared。

关于多个视图,您可以从控制器中的$this->view->disable();开始。这允许您禁用视图,这样您就不会从控制器中获取任何内容,因此您可以在控制器中了解视图的工作方式。

Phalcon假设每个控制器在/someController/someView下都有匹配的视图,后跟您在视图上注册的任何扩展名,默认为.volt,但也可以设置为使用.phtml或{{ 1}}。

这两个对应于:
.phpPhalcon\Mvc\View\Engine\Php

请注意,在查找要渲染的模板时,您不要指定扩展名,Phalcon会为您添加

Phalcon还使用根视图模板Phalcon\Mvc\View\Engine\Volt(如果存在)与视图进行所有交互,这样您就可以对所有响应使用相同的doctype,从而使您的生活更轻松。

Phalcon还为您提供了局部视图,因此您可以在视图中渲染部分像面包屑或页眉或页脚,否则您将复制粘贴到每个模板中。这使您可以管理同一模板中的所有页面,因此您不会重复自己。

至于你在Phalcon中使用哪个视图类,有两个主要选择:
index.voltPhalcon\Mvc\View
虽然类似,但Phalcon\Mvc\View\Simple为您提供了一个多级层次结构,如前所述,主模板,基于控制器动作的模板以及其他一些奇特的功能。至于Phalcon\Mvc\View,它的重量更轻,是一个单一级别。

您应该熟悉分层渲染:
https://docs.phalconphp.com/en/3.2/views#hierarchical-rendering

我的想法是Phalcon\Mvc\View\Simple你有一个主要版面(如果这个模板存在),通常存储在Phalcon\Mvc\View中,每个页面都使用它,所以你可以投入你的文档类型,标题(您将使用传入视图的变量设置,等等。您将拥有一个控制器布局,它将存储在/views/index.volt下并用于控制器内的每个操作(如果此模板存在),最后,您将拥有Action Layout,用于/views/layouts.myController.volt中控制器的特定操作。

您可以通过各种方式摆脱Phalcon的默认行为。您可以执行前面提到的/views/myController/myAction.volt,这样您就可以自己手动完成所有操作,因此Phalcon不会假设有关视图模板的任何内容。您还可以使用$this->view->disable();选择要使用的模板,如果它与控制器及其运行的操作不同。

您还可以从控制器中返回响应对象,Phalcon不会尝试渲染模板并改为使用响应对象。

例如,您可能想要这样做:

->pick

这会将用户的浏览器重定向到所述页面。你也可以做一个return $this->response->redirect('index/index'); ,而不是在Phalcon内部使用它来访问不同的控制器和/或动作。

您可以使用forward配置存储视图的目录。如果由于愚蠢的目录结构而有一些例外,您也可以在控制器本身内,甚至在视图中尽可能晚地执行此操作。

您可以执行使用setViewsDir$this->view->setTemplateBefore('common')之类的操作,以便拥有中间模板。

如果您正在使用Volt,则视图层次结构的核心是$this->view->setTemplateAfter('common');<?php echo $this->getContent(); ?>。即使您正在使用Volt,它也会被Phalcon解析并生成带有{{ content() }}的PHP版本,并在执行之前将其存储在$this->getContent()目录中。

使用&#34;模板之前的想法&#34;如果您需要在主模板和控制器模板之间使用另一层层次结构,那么它是可选的。与&#34;模板相同的想法&#34;我建议不要使用模板之前和之后,因为它们会让人感到困惑,而且部分更适合这项任务。

这完全取决于您希望如何组织应用程序结构。

注意,如果您需要更换任何主要模板,也可以在主模板与另一个主模板之间切换。你也可以只是投入一个&#34; if&#34;声明进入主模板,根据某些条件决定做什么等。

尽管如此,您应该能够阅读文档并更好地了解如何使用它:
https://docs.phalconphp.com/en/3.2/api/Phalcon_Mvc_View