命名插槽变量(如$header)未传时默认不存在,直接使用{{ $header }}会报undefined variable错误;必须用@isset($header)或{{ $header ?? '' }}判断或提供默认值,而$slot始终存在且为对象,不可用empty()判空。

Blade 组件里直接用 $header 报错:变量未定义
这是最常见的情况——组件模板中写了 {{ $header }},但父级调用时没传 <x-slot name="header"></x-slot>,PHP 就会抛出 Undefined variable: header。Laravel 不会自动声明命名插槽变量,它们默认是 null,但直接 echo null 不报错,而访问未声明变量才报错。
解决方式只有一条铁律:所有命名插槽变量必须显式判断存在性或提供默认值。
- 用
@isset($header)包裹渲染逻辑,安全且语义清晰 - 用空合并运算符
{{ $footer ?? '' }},适合纯内容输出场景 - 别写
{{ $header }}或{{ $header->title }}这类裸用,99% 会崩 - 组件顶部加
@props(['header' => ''])可设默认值,但仅对通过x-bind传的属性有效,不适用于插槽
$slot 看似简单,其实也有坑
$slot 是 Blade 组件唯一自动注入的变量,但它不是字符串,而是 Illuminate\View\ComponentSlot 实例。直接 {{ $slot }} 没问题,但一旦你写成 {{ $slot() }}(旧版 Laravel 写法)、strlen($slot) 或 empty($slot),就可能触发错误或逻辑异常。
-
{{ $slot }}✅ 正确:自动调用__toString()渲染内容 -
{{ $slot() }}❌ 已废弃:Laravel 9+ 移除该调用方式,报Call to undefined method -
@empty($slot)❌ 不可靠:因为$slot是对象,empty()始终返回false;改用@if($slot->isNotEmpty())或@unless($slot->isEmpty()) - 若需判断是否为空再套结构,推荐
@if($slot->isNotEmpty()) <div class="body">{{ $slot }}</div> @endif
调试时 dd(get_defined_vars()) 为什么没看到 $header
在组件 Blade 文件开头写 {{ dd(get_defined_vars()) }},发现输出数组里根本没有 header 键——这说明父级根本没传递这个命名插槽,或者传递方式有误。
- 检查父级是否用了正确语法:
<x-slot name="header"></x-slot>或<header></header>,不能拼错name值 - 确认插槽内容没被意外包在其他标签里(比如
<div><header>...</header></div>会导致插槽失效) - 注意作用域:插槽内容只能在
<x-xxx>...</x-xxx>标签直接子级生效,嵌套层级过深会丢失 - 如果用了
@props定义了header,那它和插槽$header是两回事,不会互相覆盖或合并
组件里混用 $slot 和 $footer,但没传 $footer,为何 $slot 也变空?
不会。这是个误解。$slot 和命名插槽变量(如 $footer)完全独立:一个缺失不影响另一个。但容易混淆的是——当父级只传了命名插槽、没传默认内容时,$slot 是一个空的 ComponentSlot 实例($slot->isEmpty() 返回 true),看起来像“没内容”,但不是 null 或未定义。
-
$slot永远存在,永远是对象,永远不会报Undefined variable -
$footer等命名插槽变量,不传就是未声明,直接读取就报错 - 所以安全模式只有一种:对所有命名插槽用
@isset或??,对$slot用->isEmpty()判断 - 最简兜底写法:
{{ $header ?? '' }} {{ $slot }} {{ $footer ?? '' }}
@isset,上线后某个页面少传一个插槽,整个组件就挂掉。











