0

0

如何优雅地管理Laravel模型状态历史?Spatie/Laravel-Model-Status轻松搞定!

王林

王林

发布时间:2025-07-11 14:32:16

|

613人浏览过

|

来源于php中文网

原创

可以通过一下地址学习composer学习地址

引言:状态管理的“甜蜜”与“烦恼”

在日常的 web 应用开发中,为模型(model)添加状态几乎是不可避免的需求。想象一下,一个电商平台中的订单,从用户下单到商品送达,会经历“待支付”、“已支付”、“备货中”、“已发货”、“已完成”、“已取消”等一系列状态。最初,我们可能会简单地在 orders 表中添加一个 status 字段来记录当前状态。

// Order.php
class Order extends Model
{
    // ...
    protected $fillable = ['status'];
}

// 设置状态
$order->status = 'paid';
$order->save();

这种方法在需求简单时确实“甜蜜”又高效。然而,随着业务的深入,新的“烦恼”接踵而至:

  1. 历史追溯困难: 如果一个订单从“待支付”变为“已取消”,再变为“已退款”,我们如何知道它曾经经历过哪些状态?什么时候变更的?
  2. 变更原因记录: 订单被取消的原因是什么?是用户主动取消,还是库存不足导致?仅仅一个状态字段无法承载这些额外信息。
  3. 复杂查询: 如何查询所有“曾经”处于“待支付”状态的订单?或者查询所有“当前”处于“待审核”但“从未”被拒绝的用户?

面对这些挑战,传统的单字段方案捉襟见肘。我们可能需要手动创建 order_statuses 这样的关联表,记录 order_idstatus_namereasoncreated_at 等字段,并手动编写复杂的逻辑来维护这些数据和执行查询。这不仅增加了开发成本,也使得代码变得臃肿且难以维护。

Spatie/Laravel-Model-Status:优雅的解决方案

幸运的是,Laravel 生态系统中有许多优秀的包可以帮助我们解决这类问题。今天我们要介绍的 spatie/laravel-model-status 就是其中一颗璀璨的明珠。它由知名的 Spatie 团队开发,提供了一种优雅、可扩展的方式来为 Eloquent 模型管理状态及其历史。

这个包的核心思想是:将模型的状态变更作为一个独立的实体进行记录,每个状态记录都可以包含名称、原因以及时间戳。这样,你不仅能轻松获取模型的当前状态,还能追溯其完整的状态变更历史,并记录每次变更的详细原因。

安装与配置

使用 Composer 安装 spatie/laravel-model-status 包非常简单:

composer require spatie/laravel-model-status

安装完成后,你需要发布并运行迁移文件,以创建存储状态信息的 statuses 表:

php artisan vendor:publish --provider="Spatie\ModelStatus\ModelStatusServiceProvider" --tag="migrations"
php artisan migrate

你还可以选择发布配置文件 config/model-status.php,以便自定义状态模型或关联字段名,不过通常默认配置已经足够使用:

php artisan vendor:publish --provider="Spatie\ModelStatus\ModelStatusServiceProvider" --tag="config"

核心功能与实践

要让你的 Eloquent 模型拥有状态管理能力,只需在其模型类中引入 Spatie\ModelStatus\HasStatuses Trait:

// app/Models/Order.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Spatie\ModelStatus\HasStatuses; // 引入 Trait

class Order extends Model
{
    use HasStatuses; // 使用 Trait

    protected $fillable = ['name', 'amount']; // 示例字段
    // ...
}

现在,你的 Order 模型就具备了强大的状态管理能力!

1. 设置新状态

你可以轻松地为模型设置新状态,并可选地附带一个变更原因:

$order = Order::create(['name' => '商品A', 'amount' => 100]);

// 设置初始状态
$order->setStatus('pending_payment'); // 订单待支付

// 订单已支付
$order->setStatus('paid');

// 订单已取消,并记录原因
$order->setStatus('cancelled', '用户主动取消');

// 订单已退款,并记录原因
$order->setStatus('refunded', '商品缺货导致退款');

每一次 setStatus 调用都会在 statuses 表中新增一条记录,完美地记录了状态变更的历史和原因。

Copysmith
Copysmith

Copysmith是一款面向企业的 AI 内容创建解决方案

下载

2. 获取状态信息

你可以通过多种方式获取模型的状态:

  • 获取当前状态名称(字符串):

    echo $order->status; // 输出:refunded
  • 获取当前状态对象(包含更多信息):

    $currentStatus = $order->status(); // 返回 Spatie\ModelStatus\Status 实例
    echo $currentStatus->name;   // 输出:refunded
    echo $currentStatus->reason; // 输出:商品缺货导致退款

    $order->latestStatus() 方法与 $order->status() 效果相同。

  • 获取特定名称的最新状态: 如果你想知道订单最近一次被取消的原因,可以这样做:

    $cancelledStatus = $order->latestStatus('cancelled');
    echo $cancelledStatus->reason; // 输出:用户主动取消
  • 获取所有状态变更历史:

    $allStatuses = $order->statuses; // 返回所有关联的 Spatie\ModelStatus\Status 集合
    foreach ($allStatuses as $status) {
        echo "状态: {$status->name}, 原因: {$status->reason}, 时间: {$status->created_at}\n";
    }

3. 查询模型(Scope)

包还提供了强大的查询 Scope,让你能轻松地根据状态筛选模型:

  • 查询当前处于特定状态的模型:

    // 查询所有当前状态为 'pending_payment' 的订单
    $pendingOrders = Order::currentStatus('pending_payment')->get();
    
    // 查询当前状态为 'paid' 或 'refunded' 的订单
    $processedOrders = Order::currentStatus(['paid', 'refunded'])->get();
  • 查询当前不处于特定状态的模型:

    // 查询所有当前状态不是 'cancelled' 的订单
    $activeOrders = Order::otherCurrentStatus('cancelled')->get();
  • 检查模型是否“曾经”或“从未”拥有某个状态:

    $order->setStatus('pending');
    $order->setStatus('processing');
    
    echo $order->hasEverHadStatus('pending') ? 'Yes' : 'No'; // 输出:Yes
    echo $order->hasEverHadStatus('completed') ? 'Yes' : 'No'; // 输出:No
    
    echo $order->hasNeverHadStatus('completed') ? 'Yes' : 'No'; // 输出:Yes

为什么选择 Spatie/Laravel-Model-Status?

  1. 开箱即用: 简单的 Composer 安装和 Trait 引入,即可获得强大的状态管理能力。
  2. 历史可追溯: 自动记录所有状态变更,方便审计和问题排查。
  3. 附带原因: 允许为每次状态变更添加详细理由,增强数据上下文。
  4. 强大查询: 内置的 Scope 使得基于状态的复杂查询变得异常简单。
  5. 代码整洁: 将状态管理逻辑从业务模型中解耦,保持模型代码的简洁性。
  6. Spatie 品质保证: Spatie 团队以其高质量、高维护性的开源包而闻名,使用他们的包通常意味着更少的坑和更好的支持。

总结

spatie/laravel-model-status 包是 Laravel 项目中处理模型状态管理的绝佳选择。它将一个看似简单却容易变得复杂的业务需求,通过优雅的设计和强大的功能,变得易于实现和维护。如果你在项目中遇到了需要跟踪状态历史、记录变更原因或进行复杂状态查询的场景,那么这个包无疑是你的救星。它不仅能帮助你写出更清晰、更健壮的代码,还能显著提升你的开发效率。赶快在你的下一个 Laravel 项目中尝试一下吧!

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

1880

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1238

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1130

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

948

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1398

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1229

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1439

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1303

2023.11.13

俄罗斯搜索引擎Yandex最新官方入口网址
俄罗斯搜索引擎Yandex最新官方入口网址

Yandex官方入口网址是https://yandex.com;用户可通过网页端直连或移动端浏览器直接访问,无需登录即可使用搜索、图片、新闻、地图等全部基础功能,并支持多语种检索与静态资源精准筛选。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1

2025.12.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
第二十四期_PHP8编程
第二十四期_PHP8编程

共86课时 | 3.4万人学习

成为PHP架构师-自制PHP框架
成为PHP架构师-自制PHP框架

共28课时 | 2.4万人学习

第二十三期_PHP编程
第二十三期_PHP编程

共93课时 | 6.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号