@include 用于模块化拼装独立组件,@extends 用于布局继承;混用会导致 @yield 找不到或内容错位,二者语义与用途截然不同。

Blade 中 @include 和 @extends 到底该用哪个?
子视图复用不等于模板继承——@include 是模块化拼装,@extends 是布局继承,混用会直接导致 @yield 找不到或内容错位。比如在 dashboard.blade.php 里想插入一个独立的用户头像卡片,它不依赖父级 @section,那就必须用 @include('components.avatar'),而不是试图让它 @extend 主布局。
常见错误现象:Undefined variable: $slot 或空白渲染,往往是因为把本该 @include 的组件误写成 @component 却没传参;或者在 @include 里用了 @yield 却没配 @section 上下文。
-
@include只做「文件包含 + 变量透传」,无上下文隔离,被包含文件直接访问父级所有变量 - 若需作用域隔离(比如防止变量名冲突),改用
@includeWhen或封装为@component - 路径不加
.blade.php后缀,且不能含/开头(即不支持绝对路径,只认resources/views/下的相对路径)
怎么传参给 Blade 子视图才安全?
直接写 @include('forms.input', ['name' => 'email', 'value' => old('email')]) 最稳妥。Blade 不支持解构赋值或默认参数语法,所有变量必须显式传入,否则子视图里读到的是 undefined(PHP 层面是 Notice: Undefined variable)。
使用场景:表单字段、列表项、状态徽章这类高复用 UI 块。例如 @include('alerts.success', ['message' => '保存成功']),子视图里直接用 {{ $message }}。
立即学习“PHP免费学习笔记(深入)”;
- 传数组比传对象更安全,避免子视图中意外调用未定义方法
- 避免在
@include参数里写复杂表达式(如@include('x', ['data' => $user->posts()->latest()->first()])),逻辑应前置到控制器 - 如果参数多于 3 个,建议改用
@component并定义public $data属性,提升可维护性
@includeIf 和 @includeWhen 的真实用途是什么?
它们不是为了“省代码”,而是规避「变量未定义」导致的渲染中断。@includeIf('partials.nav', $navItems) 会在 $navItems 为 null 或 false 时跳过包含,不报错;而 @includeWhen($user->is_admin, 'admin.menu') 是条件开关,比 @if + @include 少一层嵌套,也避免空 @section 被渲染出来。
性能影响几乎为零,但兼容性要注意:Laravel 5.6+ 才支持 @includeWhen,老项目强行用会报 Directive not supported 错误。
-
@includeIf检查文件是否存在,适合动态组件路径(如@includeIf('themes.'.$theme.'.header')) -
@includeWhen检查布尔值,适合权限控制类场景,但别把它当业务逻辑入口——判断仍应在控制器完成 - 两者都不支持 else 分支,需要 else 逻辑请退回
@if/@else结构
为什么子视图里用 @push 有时不生效?
因为 @push 的目标栈(如 @stack('scripts'))必须在父布局中已声明,且 @push 必须出现在 @extends 之后、@yield 之前。如果在 @include 的子视图里写 @push('scripts'),而父布局没定义对应 @stack,内容就丢了,不会报错也不会警告。
容易踩的坑:在 resources/views/components/modal.blade.php 里写了 @push('scripts')...@endpush,但主布局忘了加 @stack('scripts'),结果 JS 初始化失败,控制台静默无输出。
- 检查顺序:父布局先有
@stack('xxx')→ 子视图用@push('xxx')→ 渲染时按顺序合并 -
@push不支持嵌套,即不能在@include的子视图里再@include一个也带@push的文件(除非父布局预留了足够深的栈) - 调试技巧:在父布局末尾加
{{ json_encode($__env->getStack('scripts')) }}查看实际推入的内容
@include 都是文本拼接,所以变量污染和 @push 丢失比想象中更隐蔽。



















