简体   繁体   English

在Phalcon控制器中处理视图

[英]Dealing with Views in Phalcon Controllers

I am working on a newly created Phalcon project, and I don't really know how to actually use multiples views. 我正在研究一个新创建的Phalcon项目,我真的不知道如何实际使用多重视图。

What is the entry point? 切入点是什么? I don't really know when each method in the controller is called, under which conditions, etc. 我真的不知道何时调用控制器中的每个方法,在什么条件下等等。

Where is the control flow defined? 控制流在哪里定义? is it based in the name of the view? 它基于视图的名称吗? or is there a place where you can register them? 还是有一个可以注册的地方?

Phalcon is a bit different than other well-known PHP frameworks, in that not much is pre-configured or pre-built by default. Phalcon与其他知名的PHP框架有所不同,因为默认情况下没有多少是预配置或预构建的。 It's quite loosely-coupled. 它是松散耦合的。 So you have to decide where and how your control flow will work. 因此,您必须决定控制流程在何处以及如何工作。 This means that you will need to dig deeper in the documentation and also that there could be different way to achieve the same thing. 这意味着您将需要对文档进行更深入的研究,并且可能会有不同的方法来实现同一目标。

I'm going to walk you through a simple example and provide references, so you can understand it more. 我将引导您通过一个简单的示例并提供参考,以便您可以进一步了解它。

1) You would start by defining a bootstrap file (or files) that will define the routes, or entry points, and will setup and create the application. 1)您将从定义一个或多个引导文件开始,该文件将定义路由或入口点,并设置和创建应用程序。 This bootstrap file could be called by an index.php file that is the default file served by the web server. 该引导文件可以由index.php文件调用,该文件是Web服务器提供的默认文件。 Here is an example of how such bootstrap file will define the routes or entry points (note: these are just fragments and do not represent all the things that a bootstrap file should do): 这是一个这样的引导文件如何定义路由或入口点的示例(注意:这些只是片段,并不代表引导文件应做的所有事情):

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');
});

Then it the routes.php file: 然后,它是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;

Im defining routes in an alternate way, by defining routes groups. 我通过定义路由组以另一种方式定义路由。 I find it to be more easy to organize routes by resource or controller. 我发现按资源或控制器组织路由更容易。

2) When you enter the url example.com/users/show/123 , the routes above will match this to the controller users and action show . 2)当您输入网址example.com/users/show/123 ,以上路由会将其与控制器users和操作show匹配。 This is specified by the chunks of code ['controller' => 'users'] , setPrefix('/users') and '/show/{id:[0-9]{1,9}}', ['action' => 'show'] 这由代码['controller' => 'users']setPrefix('/users')'/show/{id:[0-9]{1,9}}', ['action' => 'show']

3) So now you create the controller. 3)现在,您创建了控制器。 You create a file in, let's say, controllers/UsersController.php . 您可以在controllers/UsersController.php创建一个文件。 And then you create its action; 然后创建它的动作; note the name that you used in the route ( show ) and the suffix of Action : 请注意您在路线( 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');
}

There is much more stuff related to views; 还有更多与视图相关的内容; consult the manual. 请查阅手册。

Note that you will need to register such controller in the bootstrap file like (Im also including examples on how to register other things): 请注意,您将需要在引导文件中注册此类控制器(例如,Im还包括有关如何注册其他内容的示例):

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) You will also need to register a few things for the views. 4)您还需要为视图注册一些内容。 In the bootstrap file 在引导文件中

use Phalcon\Mvc\View;

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

And this, together with other things you will need to do, particularly in the bootstrap process, will get you started in sending requests to the controller and action/view defined in the routes. 这以及您将需要做的其他事情,特别是在引导过程中,将使您开始将请求发送到控制器以及路由中定义的操作/视图。


Those were basic examples. 这些是基本示例。 There is much more that you will need to learn, because I only gave you a few pieces to get you started. 您还需要学习更多东西,因为我只给了您几篇入门。 So here are some links that can explain more. 因此,这里有一些链接可以解释更多。 Remember, there are several different ways to achieve the same thing in Phalcon. 请记住,在Phalcon中,有几种不同的方法可以实现相同的目的。

Bootstrapping: 引导程序:

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

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

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

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

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

More on Views (from registering to passing data to them, to templating and more): https://docs.phalconphp.com/en/3.2/views 有关View的更多信息(从注册到向其传递数据,再到模板等等): https : //docs.phalconphp.com/zh/3.2/views

And a simple tutorial to teach you some basic things: https://docs.phalconphp.com/en/3.2/tutorial-rest 还有一个简单的教程可以教您一些基本知识: https : //docs.phalconphp.com/en/3.2/tutorial-rest

The application begins with the routing stage. 该应用程序从路由阶段开始。 From there you grab the controller and action from the router, and feed it to the dispatcher. 从那里,您可以从路由器获取控制器和操作,并将其提供给调度程序。 You set the view then call the execute the dispatcher so it access your controller's action. 设置视图,然后调用执行调度程序,以便它访问控制器的操作。 From there you create a new response object and set its contents equal to the view requests, and finally send the response to the client's browser -- both the content and the headers. 在这里,您将创建一个新的响应对象,并将其内容设置为与视图请求相等,最后将响应发送到客户端的浏览器-内容和标头。 It's a good idea to do this through Phalcon rather than echoing directly or using PHP's header(), so it's only done at the moment you call $response->send(); 通过Phalcon而不是直接回显或使用PHP的header()来执行此操作是一个好主意,因此仅在调用$response->send();时才完成此操作$response->send(); This is best practice because it allows you to create tests, such as in phpunit, so you can test for the existence of headers, or content, while moving off to the next response and header without actually sending anything so you can test stuff. 这是最佳实践,因为它允许您创建测试(例如在phpunit中),因此您可以测试标头或内容的存在,同时转到下一个响应和标头,而无需实际发送任何内容,从而可以测试东西。 Same idea with exit; exit;相同的想法exit; in code, is best to avoid so you can write tests and move on to the next test without your tests aborting on the first test due to the existence of exit. 在代码中,最好避免这样做,因此您可以编写测试并继续进行下一个测试,而不会由于退出的存在而使测试在第一个测试中止。

As far as how the Phalcon application works, and in what steps, it's much easier to follow the flow by looking at manual bootstrapping: https://docs.phalconphp.com/en/3.2/application#manual-bootstrapping 至于Phalcon应用程序的工作方式和步骤,通过查看手动引导程序可以更轻松地遵循流程: https : //docs.phalconphp.com/en/3.2/application#manual-bootstrapping

At the heart of Phalcon is the DI, the Dependency Injection container. Phalcon的核心是依赖注入容器DI。 This allows you to create services, and store them on the DI so services can access each other. 这使您可以创建服务并将其存储在DI中,以便服务可以相互访问。 You can create your own services and store them under your own name on the DI, there's nothing special about the names used. 您可以创建自己的服务并将其以自己的名称存储在DI上,所使用的名称没有什么特别的。 However depending on the areas of Phalcon you used, certain services on the DI are assumed like "db" for interacting with your database. 但是,根据您使用的Phalcon的区域,DI上的某些服务被假定为“ db”,用于与数据库进行交互。 Note services can be set as either shared or not shared on the DI. 注释服务可以在DI上设置为共享或不共享。 Shared means it implements singleton and keeps the object alive for all calls afterwards. 共享表示它实现单例,并在以后的所有调用中使该对象保持活动状态。 If you use getShared, it does a similar thing even if it wasn't initially a shared service. 如果使用getShared,即使最初不是共享服务,它也会执行类似的操作。 The getShared method is considered bad practice and the Phalcon team is talking about removing the method in future Phalcon versions. getShared方法被认为是不好的做法,Phalcon团队正在讨论在将来的Phalcon版本中删除该方法。 Please rely on setShared instead. 请改用setShared。

Regarding multiple views, you can start with $this->view->disable(); 关于多个视图,可以从$this->view->disable(); from within the controller. 从控制器内部。 This allows you to disable a view so you don't get any content generated to begin with from within a controller so you can follow how views work from within controllers. 这允许您禁用视图,这样就不会从控制器内部开始生成任何内容,因此您可以从控制器内部跟踪视图的工作方式。

Phalcon assumes every controller has a matching view under /someController/someView followed by whatever extension you registered on the view, which defaults to .volt but can also be set to use .phtml or .php . Phalcon假定每个控制器在/someController/someView下都有一个匹配的视图,后跟您在视图上注册的任何扩展名,默认扩展名为.volt但也可以设置为使用.phtml.php

These two correspond to: 这两个对应于:
Phalcon\\Mvc\\View\\Engine\\Php and Phalcon\\Mvc\\View\\Engine\\Volt Phalcon\\Mvc\\View\\Engine\\PhpPhalcon\\Mvc\\View\\Engine\\Volt

Note that you DON'T specify the extension when looking for a template to render, Phalcon adds this for you 请注意,在寻找要渲染的模板时不要指定扩展名,Phalcon会为您添加扩展名

Phalcon also uses a root view template index.volt , if it exists, for all interactions with the view so you can use things like the same doctype for all responses, making your life easier. Phalcon还使用根视图模板index.volt (如果存在)与视图进行所有交互,因此您可以对所有响应使用相同doctype之类的东西,从而使您的工作更加轻松。

Phalcon also offers you partials, so from within a view you can render a partial like breadcrumbs, or a header or footer which you'd otherwise be copy-pasting into each template. Phalcon还为您提供了局部视图,因此您可以在视图内渲染局部视图,例如面包屑,页眉或页脚,否则您可以将其复制粘贴到每个模板中。 This allows you to manage all pages from the same template so you're not repeating yourself. 这使您可以管理同一模板中的所有页面,因此您无需重复自己。

As far as which view class you use within Phalcon, there's two main choices: 至于您在Phalcon中使用哪种视图类,有两个主要选择:
Phalcon\\Mvc\\View and Phalcon\\Mvc\\View\\Simple Phalcon\\Mvc\\ViewPhalcon\\Mvc\\View\\Simple
While similar, Phalcon\\Mvc\\View gives you a multiple level hierarchy as described before with a main template, and a controller-action based template as well as some other fancy features. 虽然类似,但Phalcon\\Mvc\\View为您提供了如前所述的多级层次结构,其中包含一个主模板,一个基于控制器操作的模板以及一些其他高级功能。 As far as Phalcon\\Mvc\\View\\Simple , it's much more lightweight and is a single level. Phalcon\\Mvc\\View\\Simple ,它轻巧得多,并且是单个级别。

You should be familiar with hierarchical rendering: 您应该熟悉分层渲染:
https://docs.phalconphp.com/en/3.2/views#hierarchical-rendering https://docs.phalconphp.com/cn/3.2/views#hierarchical-rendering

The idea is with Phalcon\\Mvc\\View that you have a Main Layout (if this template exists) usually stored in /views/index.volt , which is used on every page so you can toss in your doctypes, the title (which you would set with a variable the view passed in), etc. You'd have a Controller Layout, which would be stored under /views/layouts.myController.volt and used for every action within a controller (if this template exists), finally you'd have the Action Layout which is used for the specific action of the controller in /views/myController/myAction.volt . 使用Phalcon\\Mvc\\View的想法是,您有一个主布局(如果存在此模板)通常存储在/views/index.volt ,该布局在每个页面上都使用,因此您可以将自己的文档类型(标题(将使用传入的视图变量设置),等等。您将拥有一个控制器布局,该布局将存储在/views/layouts.myController.volt下,并用于控制器中的每个操作(如果存在此模板),最后您将在/views/myController/myAction.volt拥有用于控制器特定操作的操作布局。

There are all types of ways you can break from Phalcon's default behavior. 您可以通过各种方式打破Phalcon的默认行为。 You can do the earlier stated $this->view->disable(); 您可以执行前面所述的$this->view->disable(); so you can do everything manually yourself so Phalcon doesn't assume anything about the view template. 因此您可以自己手动完成所有操作,因此Phalcon不会承担任何有关视图模板的事情。 You can also use ->pick to pick which template to use if it's going to be different than the controller and action it's ran in. 如果要与运行的控制器和动作不同,还可以使用->pick选择要使用的模板。

You can also return a response object from within a controller and Phalcon will not try to render the templates and use the response object instead. 您也可以从控制器内部返回响应对象,Phalcon不会尝试渲染模板,而是使用响应对象。

For example you might want to do: 例如,您可能想做:

return $this->response->redirect('index/index');

This would redirect the user's browser to said page. 这会将用户的浏览器重定向到所述页面。 You could also do a forward instead which would be used internally within Phalcon to access a different controller and/or action. 您也可以执行forward ,该操作将在Phalcon内部使用,以访问其他控制器和/或操作。

You can config the directory the views are stored with setViewsDir . 您可以使用setViewsDir配置视图存储的目录。 You can also do this from within the controller itself, or even within the view as late as you want, if you have some exceptions due to a goofy directory structure. 如果由于愚蠢的目录结构而有一些例外情况,也可以在控制器本身内部甚至在视图内部进行此操作。

You can do things like use $this->view->setTemplateBefore('common') or $this->view->setTemplateAfter('common'); 您可以使用$this->view->setTemplateBefore('common')$this->view->setTemplateAfter('common'); so you can have intermediate templates. 因此您可以拥有中间模板。

At the heart of the view hierarchy is <?php echo $this->getContent(); ?> 视图层次结构的核心是<?php echo $this->getContent(); ?> <?php echo $this->getContent(); ?> or {{ content() }} if you're using Volt. <?php echo $this->getContent(); ?>{{ content() }}如果您使用的是Volt。 Even if you're using Volt, it gets parsed by Phalcon and generates the PHP version with $this->getContent() , storing it in your /cache/ directory, before it is executed. 即使您正在使用Volt,它也会被Phalcon解析并使用$this->getContent()生成PHP版本,然后在执行之前将其存储在/cache/目录中。

The idea with "template before" is that it's optional if you need another layer of hierarchy between your main template and your controller template. “之前有模板”的想法是,如果您需要在主模板和控制器模板之间建立另一层层次结构,则它是可选的。 Same idea with "template after" etc. I would advise against using template before and after as they are confusing and partials are better suited for the task. 与“模板之后”等概念相同。我建议不要在模板之前和之后使用模板,因为它们会造成混淆,并且局部函数更适合该任务。

It all depends on how you want to organize your application structure. 这完全取决于您要如何组织应用程序结构。

Note you can also swap between your main template to another main template if you need to swap anything major. 请注意,如果需要交换任何主要内容,也可以在主模板与另一个主模板之间交换。 You could also just toss in an "if" statement into your main template to decide what to do based on some condition, etc. 您也可以只在主模板中输入“ if”语句,以根据某些条件等决定要做什么。

With all that said, you should be able to read the documentation and make better sense of how to utilize it: 综上所述,您应该能够阅读文档并更好地理解其用法:
https://docs.phalconphp.com/en/3.2/api/Phalcon_Mvc_View https://docs.phalconphp.com/zh/3.2/api/Phalcon_Mvc_View

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM