Skip to content

#[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 都会将其新值存储在用户的会话中。当组件加载时,Livewire 从会话中获取值并用它初始化属性。

这创造了持久的用户体验而无需修改 URL。

Session vs URL

#[Session]#[Url] 都可以持久化属性值,但有不同的权衡:

特性#[Session]#[Url]
跨刷新持久化
分享 URL 时持久化
保持 URL 简洁
对用户可见
可共享状态

当你想要持久化而不混乱 URL 或当状态不应该是可共享的时使用 #[Session]

自定义会话键

默认情况下,Livewire 使用组件和属性名称生成会话键。你可以自定义它:

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 存储在会话中。

动态会话键

你可以使用其他属性动态生成键:

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->id4,会话键变为 search-4。这允许每个作者有不同的会话值。

何时使用

在以下情况使用 #[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>

用户可以设置他们偏好的过滤器,这些将在会话、页面刷新和导航之间持久化。

性能注意事项

不要存储大量数据

Laravel 会话在每个请求期间都会加载到内存中。在用户会话中存储太多内容可能会减慢该用户的整个应用程序。避免存储大型集合或对象。

好的用法:

  • 简单值(字符串、数字、布尔值)
  • 小数组(过滤选项、偏好设置)
  • 模型 ID(不是整个模型)

不好的用法:

  • 大型集合
  • 完整的 Eloquent 模型
  • 二进制数据或文件内容

替代方案:URL 持久化

如果你希望状态可以通过 URL 共享或收藏,考虑使用 #[Url] 属性 而不是 #[Session]。URL 参数在地址栏中持久化状态,而会话属性保持 URL 简洁。

参考

php
#[Session(
    ?string $key = null,
)]
参数类型默认值描述
$key?stringnull自定义会话键(如果未提供则自动生成)