本文目录导读:

在ThinkPHP框架中,模板布局继承是一个非常强大的功能,可以帮助你避免重复编写公共的HTML结构(如头部、底部、导航栏等),以下是关于ThinkPHP模板布局继承的详细说明:
模板继承的基本概念
ThinkPHP的模板继承允许你创建一个基础的"布局"模板,然后在子模板中通过继承来覆盖特定的区块(block)。
基础布局模板的创建
创建一个基础布局文件,通常放在 application/view/layout.html 或项目的公共视图目录中:
<!-- application/view/layout.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">{block name="title"}默认标题{/block}</title>
<!-- 公共的CSS文件 -->
<link rel="stylesheet" href="/static/css/common.css">
{block name="css"}{/block}
</head>
<body>
<!-- 公共的头部导航栏 -->
<header>
<nav>
<!-- 导航代码 -->
<div class="logo">我的网站</div>
<ul>
<li><a href="/">首页</a></li>
<li><a href="/about">关于我们</a></li>
<li><a href="/contact">联系我们</a></li>
</ul>
</nav>
</header>
<!-- 主要内容区域,子模板可覆盖 -->
<div class="container">
{block name="content"}
<!-- 默认内容 -->
这里是默认内容
{/block}
</div>
<!-- 公共的底部 -->
<footer>
<p>© 2024 我的网站. 保留所有权利.</p>
{block name="footer"}{/block}
</footer>
<!-- 公共的JS文件 -->
<script src="/static/js/jquery.min.js"></script>
<script src="/static/js/common.js"></script>
{block name="js"}{/block}
</body>
</html>
子模板的使用
基本的继承方式
<!-- application/view/user/index.html -->
{extend name="layout" /}
{block name="title"}用户列表{/block}
{block name="content"}
<h1>用户列表</h1>
<table>
<tr>
<th>ID</th>
<th>用户名</th>
</tr>
{volist name="users" id="user"}
<tr>
<td>{$user.id}</td>
<td>{$user.username}</td>
</tr>
{/volist}
</table>
{/block}
{block name="css"}
<style>
table { width: 100%; border-collapse: collapse; }
table th, table td { padding: 10px; border: 1px solid #ddd; }
</style>
{/block}
多级继承
你可以创建更复杂的基础布局:
<!-- application/view/single.html -->
{extend name="layout" /}
{block name="content"}
<main>
{block name="main_content"}{/block}
</main>
{/block}
然后在子模板中继承 single.html:
<!-- application/view/blog/detail.html -->
{extend name="single" /}
{block name="title"}文章详情{/block}
{block name="main_content"}
<article>
<h1>{$article.title}</h1>
<p>{$article.content}</p>
</article>
{/block}
在控制器中的使用
在控制器中,你只需要返回对应的模板即可:
<?php
namespace app\index\controller;
use think\Controller;
class Blog extends Controller
{
public function detail()
{
// 获取文章数据
$article = db('article')->where('id', input('id'))->find();
// 直接返回视图,系统会自动加载对应模板
// 模板文件:application/view/blog/detail.html
return $this->fetch('detail', ['article' => $article]);
}
}
高级用法
定义多个父模板
<!-- 在子模板中指定要继承的父模板 -->
{extend name="layout_mobile" /}
<!-- 或者从控制器动态指定 -->
// 控制器中动态指定布局模板
$this->view->layout('layout_admin');
数据的传递
父模板中的变量可以通过控制器或标签库传递:
<!-- 首页:application/view/index.html -->
{extend name="layout" /}
<!-- content区块 -->
{block name="content"}
<!-- 循环输出的数据 -->
{volist name="products" id="product"}
<div class="product">
<h3>{$product.name}</h3>
<p>{$product.description}</p>
</div>
{/volist}
{/block}
// Index控制器
class Index extends Controller
{
public function index()
{
$products = db('product')->select();
return $this->fetch('', ['products' => $products]);
}
}
模板嵌套
在使用继承的同时,可以通过 include 进行局部组件复用:
{extend name="layout" /}
{block name="content"}
<!-- 引入公共的侧边栏组件 -->
{include file="public/sidebar" /}
<div class="main-content">
{block name="main_content"}{/block}
</div>
{/block}
注意事项
- 文件路径:模板路径从
application/view/开始,使用点号 代替目录分隔符。 - 同名区块覆盖:如果多个同名区块,后定义的覆盖先定义的。
- 区块命名:区块名称建议使用英文小写和下划线。
- 继承生效:必须使用
{extend}标签指定继承的布局文件。 - 调试技巧:当继承不生效时,检查是否有语法错误或文件路径是否正确。
源码示例
完整的示例项目结构:
application/
├── view/
│ ├── layout.html # 基础布局
│ ├── layout_admin.html # 管理员布局(继承基础布局)
│ ├── user/
│ │ └── index.html # 用户列表(继承基础布局)
│ └── admin/
│ └── dashboard.html # 后台首页(继承admin布局)
通过合理使用模板继承,你可以大大提高开发效率,保持代码的一致性和可维护性,记得在实际开发中根据项目需求灵活调整布局结构。