Session
#[Session] 属性将属性值持久化到用户的 session 中,使其在页面刷新和导航后仍能保持。
基本用法
将 #[Session] 属性应用到任何应在 session 中持久化的属性上:
php
<?php // resources/views/components/post/⚡index.blade.php
use Livewire\Attributes\Session;
use Livewire\Attributes\Computed;
use Livewire\Component;
use App\Models\Post;
new class extends Component {
#[Session] // [tl! highlight]
public $search = '';
#[Computed]
public function posts()
{
return $this->search === ''
? Post::all()
: Post::where('title', 'like', "%{$this->search}%")->get();
}
};
?>
<div>
<input type="text" wire:model.live="search" placeholder="Search posts...">
@foreach($this->posts as $post)
<div wire:key="{{ $post->id }}">{{ $post->title }}</div>
@endforeach
</div>用户输入搜索值后,可以刷新页面或离开再返回——搜索值会被保留。
工作原理
每次属性变化时,Livewire 都会将其新值存入用户的 session。组件加载时,Livewire 从 session 获取该值并用其初始化属性。
这在不修改 URL 的情况下创建了持久化的用户体验。
Session 与 URL
#[Session] 和 #[Url] 都会持久化属性值,但各有取舍:
| 特性 | #[Session] | #[Url] |
|---|---|---|
| 刷新后保持 | ✅ | ✅ |
| 分享 URL 时保持 | ❌ | ✅ |
| 保持 URL 整洁 | ✅ | ❌ |
| 对用户可见 | ❌ | ✅ |
| 可分享的状态 | ❌ | ✅ |
当你希望持久化而又不弄乱 URL,或状态不应可分享时,使用 #[Session]。
自定义 session 键
默认情况下,Livewire 使用组件名和属性名生成 session 键。你可以自定义:
php
<?php // resources/views/components/post/⚡index.blade.php
use Livewire\Attributes\Session;
use Livewire\Component;
new class extends Component {
#[Session(key: 'post_search')] // [tl! highlight]
public $search = '';
};该属性将使用键 post_search 存储在 session 中。
动态 session 键
你可以使用其他属性动态生成键:
php
<?php // resources/views/components/post/⚡index.blade.php
use Livewire\Attributes\Session;
use Livewire\Component;
use App\Models\Author;
new class extends Component {
public Author $author;
#[Session(key: 'search-{author.id}')] // [tl! highlight]
public $search = '';
};若 $author->id 为 4,session 键变为 search-4。这允许每位作者有不同的 session 值。
何时使用
在以下情况使用 #[Session]:
- 持久化用户偏好(主题、语言、侧边栏状态)
- 在页面导航间保持筛选/搜索状态
- 存储表单数据以防止刷新丢失
- 将 UI 状态保持为用户私有
- 避免查询参数弄乱 URL
示例:仪表盘筛选器
下面是一个持久化仪表盘筛选器的实用示例:
php
<?php // resources/views/pages/⚡dashboard.blade.php
use Livewire\Attributes\Session;
use Livewire\Attributes\Computed;
use Livewire\Component;
use App\Models\Transaction;
new class extends Component {
#[Session]
public $dateRange = '30days';
#[Session]
public $category = 'all';
#[Session]
public $sortBy = 'date';
#[Computed]
public function transactions()
{
return Transaction::query()
->when($this->dateRange === '30days', fn($q) => $q->where('created_at', '>=', now()->subDays(30)))
->when($this->category !== 'all', fn($q) => $q->where('category', $this->category))
->orderBy($this->sortBy)
->get();
}
};
?>
<div>
<select wire:model.live="dateRange">
<option value="7days">Last 7 days</option>
<option value="30days">Last 30 days</option>
<option value="year">This year</option>
</select>
<select wire:model.live="category">
<option value="all">All categories</option>
<option value="income">Income</option>
<option value="expense">Expense</option>
</select>
<select wire:model.live="sortBy">
<option value="date">Date</option>
<option value="amount">Amount</option>
</select>
@foreach($this->transactions as $transaction)
<div wire:key="{{ $transaction->id }}">{{ $transaction->description }}</div>
@endforeach
</div>用户可以设置偏好的筛选条件,它们会在会话、页面刷新和导航之间保持。
性能考量
WARNING
不要存储大量数据
Laravel 的 session 会在每次请求时加载到内存中。在用户的 session 中存储过多内容会拖慢该用户的整个应用。避免存储大型集合或对象。
适合的用法:
- 简单值(字符串、数字、布尔值)
- 小型数组(筛选选项、偏好设置)
- 模型 ID(而非整个模型)
不适合的用法:
- 大型集合
- 完整的 Eloquent 模型
- 二进制数据或文件内容
TIP
替代方案:URL 持久化
若你希望状态可通过 URL 分享或收藏,可考虑使用 #[Url] 属性 而非 #[Session]。URL 参数在地址栏中持久化状态,而 session 属性保持 URL 整洁。
参考
php
#[Session(
?string $key = null,
)]| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
$key | ?string | null | 自定义 session 键(未提供时自动生成) |