You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅更新模型单个属性?基于Spatie Laravel Data的实现

基于spatie/laravel-data实现用户同意设置的更新逻辑

1. 定义请求Data类

首先创建继承自Spatie\LaravelData\Data的请求类,声明三个可空布尔类型的属性:

use Spatie\LaravelData\Data;

class UserConsentRequest extends Data
{
    public function __construct(
        public ?bool $newsLetters,
        public ?bool $sms,
        public ?bool $billEmail,
    ) {}
}

2. 添加单属性更新验证

为确保请求中最多只有一个非空的同意设置,提供两种实现方式:

方式一:在Data类内封装验证与属性提取

给Data类添加两个方法,分别处理验证逻辑和非空属性提取:

use Spatie\LaravelData\Data;
use Illuminate\Validation\ValidationException;

class UserConsentRequest extends Data
{
    public function __construct(
        public ?bool $newsLetters,
        public ?bool $sms,
        public ?bool $billEmail,
    ) {}

    // 验证是否仅提交了一项非空设置
    public function validateSingleConsent(): void
    {
        $nonNullCount = collect([$this->newsLetters, $this->sms, $this->billEmail])
            ->filter(fn($value) => !is_null($value))
            ->count();

        if ($nonNullCount > 1) {
            throw ValidationException::withMessages([
                'consent' => '只能同时更新一项用户同意设置'
            ]);
        }
    }

    // 提取所有非空的属性键值对
    public function getNonNullAttributes(): array
    {
        return collect([
            'newsLetters' => $this->newsLetters,
            'sms' => $this->sms,
            'billEmail' => $this->billEmail,
        ])->filter(fn($value) => !is_null($value))->toArray();
    }
}

方式二:利用laravel-data的验证规则

直接在Data类的rules()方法中添加自定义验证规则,让请求自动完成校验:

use Spatie\LaravelData\Data;

class UserConsentRequest extends Data
{
    public function __construct(
        public ?bool $newsLetters,
        public ?bool $sms,
        public ?bool $billEmail,
    ) {}

    public static function rules(): array
    {
        return [
            'newsLetters' => ['nullable', 'boolean'],
            'sms' => ['nullable', 'boolean'],
            'billEmail' => ['nullable', 'boolean'],
            // 自定义规则限制最多一个非空属性
            '*' => [
                function ($attribute, $value, $fail) {
                    $nonNullCount = collect(request()->only(['newsLetters', 'sms', 'billEmail']))
                        ->filter(fn($v) => !is_null($v))
                        ->count();

                    if ($nonNullCount > 1) {
                        $fail('只能同时提交一项用户同意设置的修改');
                    }
                },
            ],
        ];
    }
}

3. 在控制器中处理更新逻辑

在控制器中调用验证逻辑(方式一需要手动调用),提取非空属性并执行更新:

use App\Data\UserConsentRequest;
use Illuminate\Support\Facades\Auth;

class UserConsentController extends Controller
{
    public function update(UserConsentRequest $request)
    {
        // 方式一需要手动触发验证
        // $request->validateSingleConsent();

        // 获取非空属性(方式一)
        $attributes = $request->getNonNullAttributes();
        // 方式二可直接过滤数组:
        // $attributes = collect($request->toArray())->filter(fn($v) => !is_null($v))->toArray();

        // 仅当有非空属性时执行更新
        if (!empty($attributes)) {
            Auth::user()->update($attributes);
        }

        return response()->json(['message' => '用户同意设置更新成功']);
    }
}

最终实现效果:

  • 自动校验请求是否存在多个非空同意设置,不符合则抛出异常
  • 仅更新请求中提供的非空属性,忽略空值属性

内容的提问来源于stack exchange,提问作者Rokas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 04:45:32