自定义 Blade 指令是编译期字符串替换,需在 AppServiceProvider::boot() 中用 Blade::directive() 注册,返回合法 PHP 片段(不加分号),@role/@endrole 等区块指令必须成对注册且语法配对,修改后须执行 php artisan view:clear。

自定义 Blade 指令不是运行时执行的函数,而是编译期字符串替换——这意味着你写的回调返回的必须是合法、可直接插入 PHP 文件的代码片段,Blade 不会帮你补分号、不处理缩进、不解析变量。
Blade::directive() 的注册时机和限制
必须在 AppServiceProvider::boot() 中注册;重复调用同名指令(比如两次 Blade::directive('log', ...))会静默覆盖前一个,不会报错但行为不可预期。指令名只接受字母开头的字母数字下划线组合:@myLog ✅,@log-v2 ❌,@2nd ❌。
常见错误现象:
- 指令在模板里不生效,检查是否写在
register()而非boot() - 本地有效、上线失效,大概率是缓存没清:
php artisan view:clear - 指令名含连字符或数字开头,编译时报
Unexpected token "@..."
@datetime 这类单参数指令怎么写才安全
$expression 是原始括号内字符串,未被解析、未被转义。例如 @datetime($post->created_at) 传入的是字面量 $post->created_at,不是它的值。
正确做法是把它当表达式拼进 PHP 字符串中,并确保类型安全:
- 用
(? $expression : null)防空指针,避免Call to a member function format() on null - 别写
echo $expression->format(...)—— 如果$expression是字符串字面量(如'2025-01-01'),会报错 - 推荐封装成辅助函数再调用,比如
return "<?php echo format_datetime({$expression}); ?>";,并在helpers.php里定义format_datetime()
示例(带空值防护):
Blade::directive('datetime', function ($expression) {
return "<?php echo ({$expression}) ? ({$expression})->format('Y-m-d H:i') : ''; ?>";
});
@role/@endrole 这类区块指令为什么不能只注册一个
Blade 编译器靠栈机制匹配起始/结束标签,@role 和 @endrole 是两个独立指令,必须都注册,且生成的 PHP 片段语法要严格配对。
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
常见错误:
- 只注册了
@role,忘了@endrole→ 编译失败,提示Undefined directive 'endrole' -
@role返回<?php if (...) { ?>,但@endrole返回<?php } ?>→ 缺少endif,PHP 解析报错 - 误用
Blade::if()替代@role→@endrole完全被忽略,模板直接中断渲染
正确写法(精简版):
Blade::directive('role', function ($expression) {
return "<?php if (auth()->check() && auth()->user()->hasRole({$expression})): ?>";
});
Blade::directive('endrole', function () {
return '<?php endif; ?>';
});
@json 为什么不能用 json_encode() 替代
@json 是 Laravel 内置指令,它不只是调用 json_encode(),还会做三件事:自动 HTML 实体转义防止 XSS、强制输出双引号包裹的合法 JSON、对 null/true/false 等类型做标准化处理。
手动写 {{ json_encode($user) }} 的后果:
- 输出内容被 Blade 自动 HTML 转义,变成
{"id":1},JS 里const u = {{ json_encode($user) }};直接语法错误 - 如果
$user含用户输入字段(如 bio),json_encode()不过滤 XSS,而@json会自动 escape -
@json($user ?? [])可安全兜底,json_encode($user ?? [])在模板里写起来冗长且易漏
Vue 组件传值时,务必用 :prop-name="@json($data)",而不是 prop-name="{{ json_encode($data) }}" —— 后者因 HTML 属性值编码导致解析失败。
最易被忽略的一点:自定义指令里若要嵌套其他 Blade 指令(比如你在 Blade::extend() 里捕获的内容中写了 @if),必须手动调用 Blade::compileString() 二次编译,否则那些内置指令不会生效。

















