概述
用模板对页面进行渲染,这是比较经典的一种设计方式了。主要目的是在服务器端进行页面渲染,以使客户端浏览器可以直接拿到页面 html 的代码,这样对搜索引擎对网站的收录比较友好。如果是前后端分离的形式,由于前后端交互是用 js 进行,搜索引擎无法对页面渲染后进行 js 代码的执行,导致无法获取最终的 html 页面结构。所以这种方式对网站的 seo 很不友好,对主要依赖自然搜索流量的站点来说,不要采取前后端分离方式。
Swoft 的这个 View 组件,就是针对服务器端渲染的一个组件。可以自定义网页公共模板,布局文件。对页面拆分提供帮助。
详细说明
@View 注解
-
template:用来标注访问路由和view 模板的绑定关系
标注了绑定关系,在 Controller/action 执行结束后,才会找此控制器对应的模板,如果 RequestMapping 绑定的 class/method 和 View 组件绑定的模板路径是同一个,则会自动解析此模板。
-
layout:指定的模板路径,如果不设置,则会使用 view 组件的默认模板
控制器配置模板
/*** @RequestMapping(route="[/|index.html]", method={"GET"})* @View("home/index")** @param Request $request* @param Response $response* @return Response*/
配置了 @view 注解后,无需在 Controller 的方法中在手动进行 render,方法执行完后,会自动进行页面渲染。
这个机制是通过自定义的 Middleware 实现的。具体可以参见 vendor/swoft/view/src/Middleware
中的 ViewMiddleware.php
查看源代码。只要在项目中引入了这个中间件,在处理客户端请求时候,就会实现 view 的自动加载。
配置 ViewMiddleware
配置 ViewMiddleware 主要有以下几种方式:
全局配置
可以在 bean.php 定义文件中,配置 httpServer 的 httpDispatcher 全局 Middleware。
所谓全局配置,也就是说,请求没有异常,所有的请求都会执行完所有的全局配置中间件。
以下这种配置方式,可以看到,会在用户自定义 UserMiddleware::class
执行后执行 ViewMiddleware,具体,可以参见之前的教程:Middlewares 优先级,里面有关于中间件配置优先级的详细说明,所有的规则都是来自于对源代码的了解。
'httpDispatcher' => ['middlewares' => [\Swoft\Http\Session\SessionMiddleware::class,\Swoft\Http\Server\Middleware\ValidatorMiddleware::class,],'afterMiddlewares' => [\Swoft\View\Middleware\ViewMiddleware::class,]],
通过 @Middleware 注解进行配置 ViewMiddleware 中间件
首先我们知道 @Middleware 注解的可配置对象为:“CLASS”, “METHOD”, “ANNOTATION”,如下源码:
/*** Class Middleware** @since 2.0** @Annotation* @Target({"CLASS", "METHOD", "ANNOTATION"})* @Attributes({* @Attribute("name", type="string"),* })*/
final class Middleware
配置类注解
也就是说,这个注解可以配置针对一个类的所有方法,比如配置到 TestController 类注解上,表示 TestController 中的任何一个方法执行时候,都会在 UserMiddleware::class
级别自动将指定的中间件动态添加(详见 Middlewares 优先级说明)。这样,只有访问到这个控制器的请求才会执行到对应的中间件。
配置方法注解
如题,将 @Middleware 注解配置到方法上,只有请求指定控制器的绑定了 @Middleware 注解的方法,才会执行对应的中间件逻辑。
配置注解的注解
/*** Class AuthRoleController** @since 2.0* @Controller("auth/role")* @Middlewares({* @Middleware(ViewMiddleware::class),* @Middleware(AuthMiddleware::class)* })*/
@Middleware 注解可以配置到 @Middlewares 注解之中。@Middlewares 注解,如其名字,就是可以绑定多个中间件,执行顺序按照绑定的顺序从上往下执行。
模板代码使用
当指定的方法或者类已经绑定了 ViewMiddleware::class
中间件,一旦控制器中的逻辑执行完毕,后续就会自动执行当前方法绑定的模板页面。
以下示例中这个方法就是访问网站首页时候,会在 resource/views
(默认模板存放路径)下寻找 home/index.php
,如果有这个文件,就会执行渲染。
/*** @RequestMapping(route="[/|index.html]", method={"GET"})* @View("home/index")** @param Request $request* @param Response $response* @return Response*/
代码渲染类 Renderder::class
// 此段代码摘自 ViewMiddleware 中间件 process 方法中
$actionId = $route->getHandler();
if (!$info = ViewRegister::findBindView($actionId)) {return $response;
}// Get layout and template
[$template, $layout] = $info;// Accept list
$allowedAccepts = $request->getHeader('accept');
$currentAccept = current($allowedAccepts);
$contentType = ContentType::HTML;if ($template && false !== strpos($currentAccept, $contentType)) {$data = $response->getData();if (is_object($data) && $data instanceof Arrayable) {$data = $data->toArray();}/* @var Renderer $view */$renderer = bean('view'); // 此处为获取模板渲染的对象$content = $renderer->render($template, $data, $layout);return $response->withContent($content)->withContentType($contentType);
}
由以上代码可见,最终调用了 Renderer::class->render
渲染的模板。模板中使用的为控制器传递过来的 data 参数数组。
// 在控制器执行完毕时候,将要渲染的变量传递给模板,这里的 data 就是渲染到模板中的参数集合。
$data = ['test' => 'this is a test.'
];
return $response->withData($data);
在模板中使用 $this
变量是可以的,这个指向了 Renderer 对象实例。使用参数时候可以直接调用 $data['test']
中的参数。也可以直接使用 $data
变量中的一级键名作为变量名(也就是直接用 $test
)。因为在模板渲染时候,render 方法中使用了以下代码:
protected function protectedIncludeScope($file, array $data): void
{extract($data, EXTR_OVERWRITE);include $file; // 特别注意:千万不要在 data 中放入 file 键,会将此处模板名给覆盖掉。
}
剩下的就是在模板中进行 php html 混编了,这个都是基础,不在赘述。
PHP Swoft2 开源框架系列教程专栏推荐
Swoft2 框架精华教程:Validator 校验器详解
Swoft 框架精华教程:Devtool 详解
Swoft2 框架精华教程:Controller 组件解析,使用说明
Swoft2 框架精华教程:Config 配置解析,使用说明
Swoft2 框架精华教程:CLog 使用篇
Swoft2 框架精华教程:数据库 Migration
Swoft2 框架精华教程:数据库操作
Swoft2 框架精华教程: Swoft 组件开发单元测试
Swoft2 框架精华教程:面向切面编程(Aspect)
Swoft2 框架精华教程:Annotation 注解机制详解
Swoft 框架精华教程:Bean 定义的实例化
Swoft2 框架精华教程:Swoft 的视图组件
Swoft2 框架精华教程:Swoft 的启动过程与核心源代码解析
Swoft2 框架精华教程:Middlewares 优先级