路由链接 Url
{url} 是 DouPHP 模板生成链接的标准方式,也是最常用的核心标签。它把「点分路由键 + 参数」编译为全局 route() 调用,自动拼出符合当前站点 URL 规则(含伪静态 / 多语言前缀)的完整链接。
你在默认主题里随处可见它,例如搜索表单(theme/default/inc/header.tpl):
<form method="get" action="{url link='search'}">
一、语法
{url link="路由键" [params=$数组] [page=$页码] [options=$选项] [nofilter] k1=$v1 k2=$v2 ...}
二、保留属性
| 属性 | 必需 | 说明 |
|---|---|---|
link |
是 | 点分路由键,如 'article.show'、'admin.user.edit' |
params |
否 | 路由参数数组(与内联属性合并) |
page |
否 | 分页页码,并入 options.page |
options |
否 | 路由选项数组(如 query、lang) |
nofilter |
否 | 裸词标志(或 nofilter=true),关闭自动 HTML 转义 |
三、编译行为(重点)
{url} 由 UrlTagCompiler 编译为对全局 route() 的调用,其签名为:
route($route, array $params = array(), array $options = array())
编译规则逐条如下:
link必需:缺失时编译期报missing 'link' attribute in url tag;link作为route()的第一个参数(强制转字符串)。page并入 options:若写了page=...,会被放进options['page']。- 非保留内联属性合并进 params:除
link/params/page/options/nofilter五个保留属性外,其余内联属性会被array_merge进params,作为路由参数。 - 自动转义:开启
escapeHtml且未加nofilter时,对route()结果再做一次htmlspecialchars;否则直接输出。
举例,下面两个写法等价:
{url link='article.show' id=$article.id}
{url link='article.show' params=['id' => $article.id]}
前者把内联属性 id 自动并入 params,更简洁,是推荐写法。
四、路由键约定表
link 是一个点分的路由键,常见约定如下(具体以站点已启用的模块为准):
| 页面类型 | 路由键形式 | 典型参数 | 示例 |
|---|---|---|---|
| 模块列表页 | 模块 |
— | {url link='article'} |
| 内容详情页 | 模块.show |
id |
{url link='article.show' id=$article.id} |
| 分类列表页 | 模块.category |
category_id |
{url link='article.category' category_id=$cat.cat_id} |
| 单页详情 | page.show / page.detail |
slug |
{url link='page.detail' slug='agreement'} |
| 功能动作 | 模块.动作 |
视动作而定 | {url link='search'}、{url link='captcha'} |
| 多级动作 | 模块.子域.动作 |
视动作而定 | {url link='order.cart.store'} |
| 后台链接 | admin.模块.动作 |
id / page 等 |
{url link='admin.user.edit' id=$user.id} |
五、真实示例(取自默认主题与现网)
{* 基础:模块列表页、搜索、验证码 *}
<a href="{url link='article'}">更多文章</a>
<form method="get" action="{url link='search'}">
<img src="{url link='captcha'}" alt="验证码">
{* 带路径 / 查询参数(内联属性自动并入 params) *}
<a href="{url link='article.show' id=$article.id}">{$article.title}</a>
<a href="{url link='order.user.show' order_sn=$order.order_sn}">{$order.order_sn}</a>
{* 单页:用 slug 定位 *}
<a href="{url link='page.detail' slug='agreement'}">用户协议</a>
{* 带分页:page 并入 options *}
<a href="{url link='admin.weixin.media.subscribe' id=$media.id page=$page}">订阅</a>
{* 裸词参数值(非变量) *}
<a href="{url link='admin.ai.daily_stats' date_range=today}">今日</a>
{* 在 JS / onclick 中拼接 *}
<a href="javascript:;" onclick="douConfirm('{url link='order.user.cancel' order_sn=$order.order_sn token=$token}', '确认取消?')">取消</a>
六、参数值的形态
内联属性的值可以是:
- 变量 / 属性路径:
id=$article.id、order_sn=$order.order_sn; - 带引号的字符串字面量:
slug='agreement'; - 裸词:
date_range=today(不带引号的字面值)。
七、自动转义与 nofilter
- 前台默认
escapeHtml = false,{url}结果原样输出; - 若开启了全局转义,
{url}结果会被htmlspecialchars(URL 中的&会被转成&,这在 HTML 属性里恰恰是正确的); - 需要原样输出(如拼进 JS 字符串且不希望被转义)时,追加
nofilter:
<script>var api = "{url link='favorites.user.store' nofilter}";</script>
八、与旧式 {$url.xxx} 的兼容
早期模板里常见 {$url.xxx} 形式的链接变量,由框架注入的兼容映射提供。新模板一律推荐用 {url link='...'} 标准写法:它不依赖预注入的变量、支持任意参数与分页、与路由系统保持一致。旧式写法仅作为存量模板的兼容保留。