处理 Phalcon 控制器中的视图
Dealing with Views in Phalcon Controllers
我正在处理一个新创建的 Phalcon 项目,但我真的不知道如何实际使用多个视图。
切入点是什么?不太清楚controller中的每个方法是什么时候调用的,在什么条件下调用的等等
控制流在哪里定义的?它是基于视图的名称吗?或者有没有可以注册的地方?
应用程序从路由阶段开始。从那里,您从路由器获取控制器和操作,并将其提供给调度程序。您设置视图然后调用执行调度程序,以便它访问您的控制器的操作。从那里您创建一个新的响应 object 并将其内容设置为与查看请求相同,最后将响应发送到客户端的浏览器——包括内容和 header。通过 Phalcon 而不是直接回显或使用 PHP 的 header() 是个好主意,所以它只在你调用 $response->send();
的那一刻完成这是最佳实践,因为它允许您创建测试,例如在 phpunit 中,因此您可以测试 header 或内容的存在,同时移动到下一个响应和 header 而无需实际发送任何内容,因此您可以测试东西。与代码中的 exit;
相同的想法,最好避免,这样您就可以编写测试并继续进行下一个测试,而不会因为存在退出而在第一个测试中中止测试。
至于 Phalcon 应用程序的工作方式,以及在哪些步骤中,通过查看手动引导来遵循流程要容易得多:
https://docs.phalconphp.com/en/3.2/application#manual-bootstrapping
Phalcon 的核心是 DI,依赖注入容器。这允许您创建服务,并将它们存储在 DI 上,以便服务可以相互访问。您可以创建自己的服务并将它们以您自己的名字存储在 DI 上,使用的名称没有什么特别之处。然而,根据您使用的 Phalcon 区域,DI 上的某些服务被假定为 "db" 用于与您的数据库交互。注释服务可以在 DI 上设置为共享或不共享。 Shared 意味着它实现单例并保持 object 对之后的所有调用保持活动状态。如果您使用 getShared,即使它最初不是共享服务,它也会做类似的事情。 getShared 方法被认为是不好的做法,Phalcon 团队正在讨论在未来的 Phalcon 版本中删除该方法。请改用 setShared。
关于多个视图,您可以从控制器中的 $this->view->disable();
开始。这允许您禁用视图,这样您就不会从控制器中获取任何生成的内容,这样您就可以在控制器中了解视图是如何工作的。
Phalcon 假设每个控制器在 /someController/someView
下都有一个匹配的视图,然后是您在视图上注册的任何扩展,默认为 .volt
但也可以设置为使用 .phtml
或.php
。
这两个对应于:
Phalcon\Mvc\View\Engine\Php
和 Phalcon\Mvc\View\Engine\Volt
请注意,您在查找要呈现的模板时不要指定扩展名,Phalcon 会为您添加这个
Phalcon 还使用根视图模板 index.volt
,如果它存在,用于与视图的所有交互,因此您可以对所有响应使用相同的文档类型,让您的生活更轻松。
Phalcon 还为您提供部分内容,因此您可以在视图中呈现部分内容,例如面包屑,或者 header 或页脚,否则您会在每个模板中呈现 copy-pasting。这使您可以管理来自同一模板的所有页面,因此您不会重复自己。
就您在 Phalcon 中使用的视图 class 而言,有两个主要选择:
Phalcon\Mvc\View
和 Phalcon\Mvc\View\Simple
虽然类似,Phalcon\Mvc\View
为您提供了一个多级层次结构,如前所述,带有一个主模板,一个基于 controller-action 的模板以及一些其他奇特的功能。就 Phalcon\Mvc\View\Simple
而言,它更轻巧,并且是单层的。
你应该熟悉分层渲染:
https://docs.phalconphp.com/en/3.2/views#hierarchical-rendering
Phalcon\Mvc\View
的想法是您有一个主布局(如果此模板存在)通常存储在 /views/index.volt
中,每个页面都会使用它,因此您可以在文档类型中使用,标题(您将使用传入的视图变量设置)等。您将有一个控制器布局,它将存储在 /views/layouts.myController.volt
下并用于控制器内的每个操作(如果此模板存在),最后,您将拥有用于 /views/myController/myAction.volt
中控制器特定操作的 Action Layout。
有多种方法可以打破 Phalcon 的默认行为。您可以执行前面所述的 $this->view->disable();
这样您就可以自己手动执行所有操作,这样 Phalcon 就不会对视图模板做出任何假设。如果它与 运行 中的控制器和操作不同,您还可以使用 ->pick
选择要使用的模板。
您还可以从控制器中 return 响应 object 并且 Phalcon 不会尝试呈现模板并使用响应 object 代替。
例如你可能想做:
return $this->response->redirect('index/index');
这会将用户的浏览器重定向到所述页面。你也可以做一个 forward
而不是在 Phalcon 内部使用它来访问不同的控制器 and/or 动作。
您可以配置视图的存储目录setViewsDir
。您也可以从控制器本身执行此操作,或者甚至在你想要的视图中延迟,如果你有一些异常,因为一个愚蠢的目录结构。
您可以使用 $this->view->setTemplateBefore('common')
或 $this->view->setTemplateAfter('common');
等操作,这样您就可以获得中间模板。
视图层次结构的核心是 <?php echo $this->getContent(); ?>
或 {{ content() }}
(如果您使用的是 Volt)。即使您使用的是 Volt,它也会被 Phalcon 解析并生成带有 $this->getContent()
的 PHP 版本,在执行之前将其存储在您的 /cache/
目录中。
"template before" 的想法是,如果您在主模板和控制器模板之间需要另一层层次结构,则它是可选的。与 "template after" 等相同的想法。我建议不要在之前和之后使用模板,因为它们令人困惑,部分更适合该任务。
这完全取决于您希望如何组织应用程序结构。
请注意,如果您需要交换任何主要模板,您也可以在主模板与另一个主模板之间交换。您也可以将 "if" 语句放入您的主模板中,以根据某些条件等决定要做什么。
综上所述,您应该能够阅读文档并更好地理解如何使用它:
https://docs.phalconphp.com/en/3.2/api/Phalcon_Mvc_View
Phalcon 与其他著名的 PHP 框架有点不同,默认情况下没有太多预配置或预构建。它是相当松耦合的。所以你必须决定你的控制流在哪里以及如何工作。这意味着您将需要更深入地研究文档,并且可能有不同的方法来实现相同的目标。
我将通过一个简单的示例向您介绍并提供参考资料,以便您更好地理解它。
1) 您将从定义一个 bootstrap 文件(或多个文件)开始,该文件将定义路由或入口点,并将设置和创建应用程序。此 bootstrap 文件可以由 index.php 文件调用,该文件是 Web 服务器提供的默认文件。这是一个 bootstrap 文件如何定义路由或入口点的示例(注意:这些只是片段,并不代表 bootstrap 文件应该做的所有事情):
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)当你输入urlexample.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) 您还需要为视图注册一些内容。在 bootstrap 文件中
use Phalcon\Mvc\View;
$injector->setShared('view', function () {
$view = new View();
$view->setViewsDir('path/views/');
return $view;
});
这与您需要做的其他事情一起,特别是在 bootstrap 过程中,将使您开始向路由中定义的控制器和 action/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
我正在处理一个新创建的 Phalcon 项目,但我真的不知道如何实际使用多个视图。
切入点是什么?不太清楚controller中的每个方法是什么时候调用的,在什么条件下调用的等等
控制流在哪里定义的?它是基于视图的名称吗?或者有没有可以注册的地方?
应用程序从路由阶段开始。从那里,您从路由器获取控制器和操作,并将其提供给调度程序。您设置视图然后调用执行调度程序,以便它访问您的控制器的操作。从那里您创建一个新的响应 object 并将其内容设置为与查看请求相同,最后将响应发送到客户端的浏览器——包括内容和 header。通过 Phalcon 而不是直接回显或使用 PHP 的 header() 是个好主意,所以它只在你调用 $response->send();
的那一刻完成这是最佳实践,因为它允许您创建测试,例如在 phpunit 中,因此您可以测试 header 或内容的存在,同时移动到下一个响应和 header 而无需实际发送任何内容,因此您可以测试东西。与代码中的 exit;
相同的想法,最好避免,这样您就可以编写测试并继续进行下一个测试,而不会因为存在退出而在第一个测试中中止测试。
至于 Phalcon 应用程序的工作方式,以及在哪些步骤中,通过查看手动引导来遵循流程要容易得多: https://docs.phalconphp.com/en/3.2/application#manual-bootstrapping
Phalcon 的核心是 DI,依赖注入容器。这允许您创建服务,并将它们存储在 DI 上,以便服务可以相互访问。您可以创建自己的服务并将它们以您自己的名字存储在 DI 上,使用的名称没有什么特别之处。然而,根据您使用的 Phalcon 区域,DI 上的某些服务被假定为 "db" 用于与您的数据库交互。注释服务可以在 DI 上设置为共享或不共享。 Shared 意味着它实现单例并保持 object 对之后的所有调用保持活动状态。如果您使用 getShared,即使它最初不是共享服务,它也会做类似的事情。 getShared 方法被认为是不好的做法,Phalcon 团队正在讨论在未来的 Phalcon 版本中删除该方法。请改用 setShared。
关于多个视图,您可以从控制器中的 $this->view->disable();
开始。这允许您禁用视图,这样您就不会从控制器中获取任何生成的内容,这样您就可以在控制器中了解视图是如何工作的。
Phalcon 假设每个控制器在 /someController/someView
下都有一个匹配的视图,然后是您在视图上注册的任何扩展,默认为 .volt
但也可以设置为使用 .phtml
或.php
。
这两个对应于:
Phalcon\Mvc\View\Engine\Php
和 Phalcon\Mvc\View\Engine\Volt
请注意,您在查找要呈现的模板时不要指定扩展名,Phalcon 会为您添加这个
Phalcon 还使用根视图模板 index.volt
,如果它存在,用于与视图的所有交互,因此您可以对所有响应使用相同的文档类型,让您的生活更轻松。
Phalcon 还为您提供部分内容,因此您可以在视图中呈现部分内容,例如面包屑,或者 header 或页脚,否则您会在每个模板中呈现 copy-pasting。这使您可以管理来自同一模板的所有页面,因此您不会重复自己。
就您在 Phalcon 中使用的视图 class 而言,有两个主要选择:
Phalcon\Mvc\View
和 Phalcon\Mvc\View\Simple
虽然类似,Phalcon\Mvc\View
为您提供了一个多级层次结构,如前所述,带有一个主模板,一个基于 controller-action 的模板以及一些其他奇特的功能。就 Phalcon\Mvc\View\Simple
而言,它更轻巧,并且是单层的。
你应该熟悉分层渲染:
https://docs.phalconphp.com/en/3.2/views#hierarchical-rendering
Phalcon\Mvc\View
的想法是您有一个主布局(如果此模板存在)通常存储在 /views/index.volt
中,每个页面都会使用它,因此您可以在文档类型中使用,标题(您将使用传入的视图变量设置)等。您将有一个控制器布局,它将存储在 /views/layouts.myController.volt
下并用于控制器内的每个操作(如果此模板存在),最后,您将拥有用于 /views/myController/myAction.volt
中控制器特定操作的 Action Layout。
有多种方法可以打破 Phalcon 的默认行为。您可以执行前面所述的 $this->view->disable();
这样您就可以自己手动执行所有操作,这样 Phalcon 就不会对视图模板做出任何假设。如果它与 运行 中的控制器和操作不同,您还可以使用 ->pick
选择要使用的模板。
您还可以从控制器中 return 响应 object 并且 Phalcon 不会尝试呈现模板并使用响应 object 代替。
例如你可能想做:
return $this->response->redirect('index/index');
这会将用户的浏览器重定向到所述页面。你也可以做一个 forward
而不是在 Phalcon 内部使用它来访问不同的控制器 and/or 动作。
您可以配置视图的存储目录setViewsDir
。您也可以从控制器本身执行此操作,或者甚至在你想要的视图中延迟,如果你有一些异常,因为一个愚蠢的目录结构。
您可以使用 $this->view->setTemplateBefore('common')
或 $this->view->setTemplateAfter('common');
等操作,这样您就可以获得中间模板。
视图层次结构的核心是 <?php echo $this->getContent(); ?>
或 {{ content() }}
(如果您使用的是 Volt)。即使您使用的是 Volt,它也会被 Phalcon 解析并生成带有 $this->getContent()
的 PHP 版本,在执行之前将其存储在您的 /cache/
目录中。
"template before" 的想法是,如果您在主模板和控制器模板之间需要另一层层次结构,则它是可选的。与 "template after" 等相同的想法。我建议不要在之前和之后使用模板,因为它们令人困惑,部分更适合该任务。
这完全取决于您希望如何组织应用程序结构。
请注意,如果您需要交换任何主要模板,您也可以在主模板与另一个主模板之间交换。您也可以将 "if" 语句放入您的主模板中,以根据某些条件等决定要做什么。
综上所述,您应该能够阅读文档并更好地理解如何使用它:
https://docs.phalconphp.com/en/3.2/api/Phalcon_Mvc_View
Phalcon 与其他著名的 PHP 框架有点不同,默认情况下没有太多预配置或预构建。它是相当松耦合的。所以你必须决定你的控制流在哪里以及如何工作。这意味着您将需要更深入地研究文档,并且可能有不同的方法来实现相同的目标。
我将通过一个简单的示例向您介绍并提供参考资料,以便您更好地理解它。
1) 您将从定义一个 bootstrap 文件(或多个文件)开始,该文件将定义路由或入口点,并将设置和创建应用程序。此 bootstrap 文件可以由 index.php 文件调用,该文件是 Web 服务器提供的默认文件。这是一个 bootstrap 文件如何定义路由或入口点的示例(注意:这些只是片段,并不代表 bootstrap 文件应该做的所有事情):
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)当你输入urlexample.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) 您还需要为视图注册一些内容。在 bootstrap 文件中
use Phalcon\Mvc\View;
$injector->setShared('view', function () {
$view = new View();
$view->setViewsDir('path/views/');
return $view;
});
这与您需要做的其他事情一起,特别是在 bootstrap 过程中,将使您开始向路由中定义的控制器和 action/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