Laravel 13.35 更新笔记:QUERY 路由、defaults() 与百分比内存限制
Route::query():为 HTTP QUERY 方法注册路由
Joel Butcher 提交的 Route::query() 为 HTTP QUERY 方法注册路由。QUERY 是一种安全方法,但允许携带请求体,适合筛选条件太长、塞不进 query string 的搜索接口:
Route::query('/products/search', SearchProductsController::class);
QUERY 已加入路由器的动词列表,因此 Route::any() 与 Route::redirect() 也会匹配它。它不在 Registrar contract 中,而 CSRF 保护对 QUERY 请求的校验与 POST 一致:位于 web 中间件组里的 QUERY 路由需要 CSRF token,或者把该路由加入 except 列表。见 PR #61797。
Model defaults():用 HasDefaultAttributes 提供默认值
Wes Hooper 带来的 defaults() 是 $attributes 属性的方法版本,默认值因此可以来自 config、feature flag 或当前日期。在 Laravel 13 中,模型需要显式使用 HasDefaultAttributes trait:
use Illuminate\Database\Eloquent\Concerns\HasDefaultAttributes;
class Subscription extends Model
{
use HasDefaultAttributes;
protected function defaults(): array
{
return [
'cancelled' => false,
'trial_days' => Feature::active('extended-trials') ? 30 : 14,
];
}
}
通过 trait 引入,可以避免影响已经存在名为 defaults() 方法的模型。defaults() 返回的值优先于 $attributes,并且是原始值,会跳过 cast 与 mutator。见 PR #61813。
Fake 断言支持属性数组
Jack Bayliss 让 Queue、Bus、Event 和 Notification 的 fake 在原本接受回调的位置,也可以接受一个预期属性值数组:
Queue::assertPushed(ProcessPodcast::class, [
'podcast' => $podcast,
'user' => $user,
'status' => 'pending',
]);
每个值都按严格相等比较,Eloquent 模型例外,按 is() 比较。参与比较的属性需要是 public。见 PR #61770。
queue:work --memory 支持百分比
--memory 选项现在接受 PHP memory_limit 的百分比:
php artisan queue:work --memory=60%
当 memory_limit 为 512M 时,worker 在某个任务结束后占用约 307 MB 就会停止。如果 memory_limit 为 -1(PHP CLI 下常见),百分比会解析为负数,worker 永远不会因内存而停止。使用百分比时,需要为 worker 进程设置 memory_limit。见 PR #61753。
Schedule::alwaysOnOneServer()
Jack Bayliss 新增的 Schedule::alwaysOnOneServer() 会对每个计划任务应用 onOneServer():
// in AppServiceProvider::boot()
Schedule::alwaysOnOneServer();
没有名字的闭包任务会被跳过,因为 onOneServer() 需要名字来构建锁。该功能依赖所有服务器共享的 cache store。见 PR #61789。
部署时中断长时间运行的调度命令
cyppe 将 schedule:interrupt 改为存储时间戳(与 queue:restart 类似),并新增 Schedule::hasBeenInterruptedSince(),让长时间运行的命令可以在安全位置主动停止:
public function handle(Schedule $schedule)
{
$startedAt = now();
foreach ($this->batches() as $batch) {
if ($schedule->hasBeenInterruptedSince($startedAt)) {
return;
}
$this->process($batch);
}
}
见 PR #61764。
response()->markdown()
Ashot Gharakeshishyan 新增的 response()->markdown() 与请求侧的 wantsMarkdown() 配套:
return $request->wantsMarkdown()
? response()->markdown($post->markdown)
: view('posts.show', ['post' => $post]);
它返回一个普通响应,content type 为 text/markdown。见 PR #61800。
local 磁盘的 lazy_root_creation
Jamie York 为 local 磁盘增加 'lazy_root_creation' => true,把根目录的创建推迟到第一次写入文件时:
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app/private'),
'lazy_root_creation' => true,
],
],
见 PR #61799。