如何在Laravel Lighthouse的GraphQL服务端Mutation Schema中设置当前时间戳?
好问题!在Laravel Lighthouse里,你没法直接在GraphQL Schema的默认参数里写current_timestamp这种数据库函数——因为Schema的默认值是在解析阶段处理的,不是直接传递给数据库执行的。不过有几种靠谱的方式能实现你要的服务端时间戳效果,我给你拆解下:
方法一:Field Middleware(推荐,复用性高)
这种方式适合需要在多个Mutation里复用“自动填充服务端时间”的场景,逻辑集中且易维护。
- 首先生成一个自定义中间件:
php artisan make:middleware SetCurrentTimestamp
- 修改中间件的处理逻辑,自动填充
canceled_at参数:
<?php namespace App\Http\Middleware; use Closure; use Carbon\Carbon; use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; class SetCurrentTimestamp { public function handle($root, array $args, GraphQLContext $context, Closure $next) { // 如果客户端没传canceled_at,就用服务端当前时间填充 if (!isset($args['canceled_at'])) { $args['canceled_at'] = Carbon::now(); } return $next($root, $args, $context); } }
- 在
config/lighthouse.php的middleware数组里注册这个中间件:
'middleware' => [ // ... 其他已注册的中间件 'setCurrentTimestamp' => \App\Http\Middleware\SetCurrentTimestamp::class, ],
- 最后更新你的GraphQL Schema,给Mutation绑定这个中间件:
type Mutation { cancelOrder(id: ID!, canceled_at: DateTime): Order @update @middleware(name: "setCurrentTimestamp") }
现在客户端调用cancelOrder时,可传可不传canceled_at:不传的话会自动用服务端时间,传了则优先使用传入的值,非常灵活。
方法二:自定义Resolver(适合复杂业务场景)
如果你的取消订单操作还有其他自定义逻辑(比如权限校验、状态校验),直接写自定义Resolver会更直观。
- 创建Resolver类:
app/GraphQL/Mutations/CancelOrder.php
<?php namespace App\GraphQL\Mutations; use App\Models\Order; use Carbon\Carbon; use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; class CancelOrder { public function resolve($root, array $args, GraphQLContext $context) { $order = Order::findOrFail($args['id']); // 优先使用客户端传入的canceled_at,否则用服务端当前时间 $order->canceled_at = $args['canceled_at'] ?? Carbon::now(); $order->save(); // 这里还可以加其他业务逻辑,比如发送取消通知、更新关联数据等 return $order; } }
- 更新Schema,指定使用这个自定义Resolver:
type Mutation { cancelOrder(id: ID!, canceled_at: DateTime): Order @field(resolver: "App\\GraphQL\\Mutations\\CancelOrder@resolve") }
方法三:数据库层面默认值(最简单,适合无额外逻辑场景)
如果你的canceled_at字段只需要在取消时自动填充当前时间,也可以直接在数据库层面配置默认值:
- 修改Order模型的迁移文件,给
canceled_at设置数据库默认值:
Schema::table('orders', function (Blueprint $table) { // MySQL用CURRENT_TIMESTAMP,PostgreSQL用CURRENT_TIMESTAMP或NOW() $table->timestamp('canceled_at')->nullable()->default(\DB::raw('CURRENT_TIMESTAMP')); });
- 更新Schema,把
canceled_at设为可选参数,@update指令会自动忽略未传入的字段,让数据库用默认值:
type Mutation { cancelOrder(id: ID!, canceled_at: DateTime): Order @update }
⚠️ 注意:如果客户端传入null,会覆盖数据库的默认值,所以如果要防止这种情况,建议搭配模型的属性修改器或者上面的中间件方式使用。
内容的提问来源于stack exchange,提问作者Wald
相关产品推荐
相关产品推荐

