为 ICanBoogie 提供视图支持

v0.10.0 2022-04-13 21:05 UTC

This package is auto-updated.

Last update: 2024-08-30 01:20:02 UTC


README

Release Code Quality Code Coverage Downloads

icanboogie/view 包提供了模型-视图-控制器 (MVC) 架构模式中的视图部分。它扩展了 icanboogie/routing 包的功能——更准确地说,是其控制器——与 icanboogie/render 包一起,帮助将表现层与逻辑层分离。

安装

composer require icanboogie/<name>

入门

在开始之前,您需要定义一些原型方法来将一些 render 组件绑定到 View 实例,并将 View 实例绑定到使用它们的 Controller 实例。

如果您使用 ICanBoogieicanboogie/view 包,您可以简单地 require icanboogie/bind-view 包,并让它处理绑定。

以下代码演示了如何绑定 Controller 实例的 view 原型属性。绑定由 ControllerBindings 特性定义。

<?php

use ICanBoogie\Prototype;
use ICanBoogie\Routing\Controller;
use ICanBoogie\View\View;

use function ICanBoogie\Render\get_renderer;

Prototype::bind([

	Controller::class => [

		'lazy_get_view' => function(Controller $controller) {

			$view = new View($controller, get_renderer());

			new View\AlterEvent($view);

			return $view;

		}

	]

]);

视图和控制器

视图通过惰性获取器 view 与控制器相关联,因此只需 $this->view 就可以在控制器内部启动视图。然后视图等待 Controller::action 事件,以执行其渲染。

以下示例演示了如何将一些文章的查询设置为视图内容,并在视图变量中添加一个标题

<?php

use ICanBoogie\Routing\Controller;
use ICanBoogie\Module\ControllerBindings as ModuleBindings;
use ICanBoogie\View\ControllerBindings as ViewBindings;

class ArticlesController extends Controller
{
	use Controller\ActionTrait, ViewBindings, ModuleBindings;

	protected function action_index()
	{
		$this->view->content = $this->model->visible->ordered->limit(10);
		$this->view['title'] = "Last ten articles";
	}
}

注意: model 获取器由 icanboogie/module 包提供,并且仅在路由有 module 属性时才可用,对于由模块定义的路由是自动的。

可以使用 assign() 方法在单个调用中将多个值分配给视图

<?php

$content = new SignupForm;
$title = "Sign up";
$params = $_POST;

$this->view->assign(compact('content', 'title', 'params'));

在返回到控制器之前修改视图

当通过 view 获取器创建实例时,会触发类 View\AlterEventView::alter 事件。事件钩子可以使用此事件在将视图返回给控制器之前修改视图。

以下示例演示了如何修改在返回给控制器之前可以修改视图。如果路由有 module 属性,则将模块的 "template" 目录添加到模板解析器中

<?php

use ICanBoogie\PropertyNotDefined;
use ICanBoogie\View\View;

$app->events->attach(function(View\AlterEvent $event, View $view) use ($app) {

	try
	{
		$module_id = $view->controller->route->module;
	}
	catch (PropertyNotDefined $e)
	{
		// if the property is not defined we just return

		return;
	}

	// adding a template path
	$view->template_resolver->add_path($app->modules[$module_id]->path . 'templates');

	// adding a variable
	$view['log'] = $app->log->messages;

	// altering the layout
	if ($app->is_mobile)
	{
		$view->layout .= '.mobile';
	}

});

渲染视图

视图使用 模板布局 进行渲染。模板渲染视图的内容,而布局则装饰模板。例如,使用 "articles/list" 模板来渲染文章集合,而使用 "page" 布局来用网站的布局装饰渲染后的集合。

用于呈现视图内容的模板按以下方式解析

  • 从视图的 template 属性。
  • 从路由的 template 属性。
  • 从控制器的 template 属性。
  • 从控制器的名称和动作来看,如果控制器具有 action 属性,例如 "articles/show"。

用于装饰模板的布局解决方式如下

  • 来自视图的 layout 属性。
  • 来自路由的 layout 属性。
  • 来自控制器的 layout 属性。
  • 如果路由的标识符以 "admin:" 开头,则使用 "admin"。
  • 如果路由的模式为 "/" 且模板存在,则使用 "home"。
  • 如果模板存在,则使用 "page"。
  • 否则使用 "default"。

由于 templatelayout 属性是延迟创建的,您可以定义它们而不是让 View 查找正确的模板名称。以下示例演示了如何 取消 模板并定义 "admin" 作为布局

<?php

use ICanBoogie\Routing\Controller;
use ICanBoogie\View\ControllerBindings as ViewBindings;

class ArticlesController extends Controller
{
	use Controller\ActionTrait;
	use ViewBindings;

	// …

	protected function action_index()
	{
		$this->view->content = $this->model->visible->ordered->limit(10);
		$this->view->template = null;
		$this->view->layout = "admin";
	}

	// …
}

模板和布局通常指定为 名称,例如 "page" 或 "articles/show",而不是路径,例如 "/path/to/my/template.phtml"。模板解析器和引擎集合用于将这些名称解析为路径名,并使用引擎集合使用适当的引擎渲染模板。这样做的原因是模板通常在您的应用程序中定义为层次结构,并且使用这个层次结构可以更好地满足您的应用程序。

例如,框架 ICanBoogie 装饰默认模板解析器以添加附加功能,并还将应用程序目录添加到模板解析器中。

请参阅 icanboogie/render 包以获取有关模板解析器和引擎集合的更多详细信息。

提供缓存的输出结果

在渲染视图之前,将触发类 View\BeforeRenderEventView::render:before 事件。事件钩子可以使用此事件提供缓存的输出结果并节省渲染成本。

以下示例演示了事件钩子如何提供先前渲染的视图的缓存输出结果。由于视图实例的 JSON 包含其模板、布局和变量,其哈希值是完美的缓存键。

<?php

use ICanBoogie\View\View;

/* @var $storage \ICanBoogie\Storage\Storage */

$app->events->attach(function(View\BeforeRenderEvent $event, View $view) use ($storage) {

	$hash = hash('sha256', json_encode($view));
	$result = $storage->retrieve($hash);

	if ($result !== null)
	{
		$event->result = $result;

		return;
	}

	$event->result = $result = $view->render();
	$storage->store($hash, $result);
	$event->stop();

});

渲染 JSON 和其他内容

视图通常用于渲染 HTML,但它们也可以渲染 JSON、XML 等其他内容,而且由于只需根据您要渲染的内容更改控制器的 Response 实例,所以这相当简单。这不是 View 功能,但这是您需要注意的事情。

以下示例演示了如何更改响应以适应 JSON 响应。

<?php

// templates/json.php

/* @var $content mixed */

echo json_encode($content);
<?php

	// …

	protected function action_any_json()
	{
		$this->view->content = $this->model->one;
		$this->view->template = 'json';
		$this->response->content_type = "application/json";
	}

	// …

取消视图

当您需要返回不同的结果或想要取消其渲染时,可以 取消 视图。当控制器返回结果时,视图会自动取消。还可以通过将控制器的 view 属性设置为 null 来取消视图。

以下示例演示了如何使用这些方法取消视图。

<?php

use ICanBoogie\Routing\Controller;
use ICanBoogie\View\ControllerBindings as ViewBindings;
use ICanBoogie\Module\ControllerBindings as ModuleBindings;

class ArticlesController extends Controller
{
	use Controller\ActionTrait, ViewBindings, ModuleBindings;

	protected function action_any_index()
	{
		$this->view->content = $this->model->visible->ordered->limit(10);
		$this->view['title'] = "Last ten articles";
	}

	protected function action_any_json()
	{
		$this->action_any_index();
		$this->response->content_type = "application/json";
		// The view is cancelled to return JSON text
		return json_encode($this->view->content);
	}

	protected function action_head_index()
	{
		$this->action_any_index();
		// The view is cancelled although no result is returned
		$this->view = null;
	}
}

渲染部分

partial() 方法使用视图的渲染器渲染部分。

请记住,视图包含在传递给模板的变量中。

<?php

$view->partial('articles/overview', [ 'article' => $article ]);

原型方法

以下原型方法被使用。可以使用 ControllerBindings 特性来帮助提示代码。

  • ICanBoogie\Routing\Controller::lazy_get_view:返回与控制器关联的 View 实例,并启动视图 魔法

事件

  • ICanBoogie\View\View::alter 类的 View\AlterEvent:当实例由 Controller::view 属性创建时触发。事件钩子可以使用此事件在返回给控制器之前修改视图。

  • ICanBoogie\View\View::render:before 类的 View\BeforeRenderEvent:在渲染视图之前触发。事件钩子可以使用此事件提供缓存结果。

持续集成

该项目由 GitHub actions 持续测试。

Tests Static Analysis Code Style

行为准则

本项目遵循 贡献者行为准则。参与本项目及其社区时,您应遵守此准则。

贡献

请参阅 CONTRIBUTING 获取详细信息。

许可证

icanboogie/view 采用 BSD-3-Clause 许可证发布。