Laravel 团队发布了 v13.42.0 版本,为请求输入添加了 uuid() 和 ulid() 方法、MigrationFailed 事件、跳过计划任务的理由、检测数据库连接丢失的闭包钩子等:

  • 请求和其他 InteractsWithData 类上的 uuid() 和 ulid()
  • MigrationFailed 事件
  • ScheduledTaskSkipped 事件中的跳过理由
  • schedule:list --json 报告每个任务自己的时区
  • LostConnectionDetector::detectUsing()
  • Uri::origin()
  • PendingProcess 上的宏
  • 支持 ably/pubsub-server 包

UUID 和 ULID 请求输入

Pawel 在现有的 date() 和 enum() 辅助函数旁边添加了 uuid() 和 ulid()。它们返回类型化对象而不是字符串:

$request->uuid('order_id'); // Ramsey\Uuid\UuidInterface|null
$request->ulid('order_id'); // Symfony\Component\Uid\Ulid|null

$request->safe()->uuid('order_id');

缺失或空的输入返回 null。无效的输入会抛出异常。这些方法来自 InteractsWithData 特性,因此它们也适用于 Fluent、验证后的输入、Uri 查询字符串、组件属性和命令输入。

ulid() 方法仅接受真实的 ULID 字符串。传递给它的 UUID 会抛出异常,而不会被转换为不同的 ULID。

MigrationFailed 事件

Jack Bayliss 添加了一个 MigrationFailed 事件,当迁移抛出异常时会触发。该事件具有与其他迁移事件相同的 migration、method 和 name 属性,以及 exception。事件触发后仍会抛出异常。

在 MySQL 上,如果迁移中后面的语句失败,像 ALTER TABLE 这样的架构更改不会回滚。您可以使用该事件通知您的团队或在用户遇到部分应用的架构之前将应用下线:

use Illuminate\Database\Events\MigrationFailed;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Log;

Event::listen(function (MigrationFailed $event) {
    Artisan::call('down');

    Log::channel('slack')->critical("Migration [{$event->name}] failed", [
        'exception' => $event->exception->getMessage(),
    ]);
});

调度器跳过理由和 JSON 时区

Jack Bayliss 还在 ScheduledTaskSkipped 事件中添加了 reason 属性。它包含一个 ScheduledTaskSkipReason 枚举,有三个情况:ConditionNotMet、Paused 和 RanOnAnotherServer。

Event::listen(function (ScheduledTaskSkipped $event) {
    Log::info('Scheduled task skipped', [
        'task' => $event->task->getSummaryForDisplay(),
        'reason' => $event->reason?->value,
    ]);
});

Francisco Madeira 修改了 schedule:list --json,使其返回每个任务自己的 cron 表达式和时区。在此之前,所有表达式都会被转换为应用时区,因此在 DST 变更后存储的输出会相差一小时。传递 --timezone 仍然会将所有任务转换为该时区。如果您解析此 JSON,请检查设置了自己 timezone() 的任务,因为它们的 expression、timezone 和 next_due_date 值会发生变化。

自定义连接丢失检测

当异常匹配已知连接丢失消息列表时,Laravel 会重新连接到数据库。新的 LostConnectionDetector::detectUsing() 方法(同样来自 Jack Bayliss)允许您添加自己的检查,而无需绑定自定义检测器:

use Illuminate\Database\LostConnectionDetector;

LostConnectionDetector::detectUsing(function (Throwable $e) {
    return str_contains($e->getMessage(), 'vttablet: rpc error');
});

当回调返回 false 时,Laravel 会检查内置消息。

Uri::origin()

Naoya Miyagawa 在 Uri 类中添加了 origin()。它返回方案、主机和端口,并对它们进行规范化,因此 https://App.example.com:443 变为 https://app.example.com:

use Illuminate\Support\Uri;

$sameOrigin = Uri::of($first)->origin() === Uri::of($second)->origin();

框架现在要求使用 league/uri 7.6 或更高版本。

PendingProcess 宏

Richard van Baarsen 使 PendingProcess 可宏化。在此之前,Process 工厂上的宏仅在链式调用中作为第一个调用时才有效:

use Illuminate\Process\PendingProcess;
use Illuminate\Support\Facades\Process;

PendingProcess::macro('withHerd', function () {
    return $this->env(['PATH' => $herdBin.':'.getenv('PATH')]);
});

Process::tty()->withHerd()->run('composer global install');

Ably 包重命名

Ably PHP SDK 已从 ably/ably-php 重命名为 ably/pubsub-server。Mior Muhammad Zaki 添加了对新版本 2 的支持,现在 php artisan install:broadcasting --ably 将安装 ably/pubsub-server。ably/ably-php 1.x 上的应用程序仍可正常工作。

其他修复

  • cursor() 现在尊重 Model::preventLazyLoading() 
  • TokenGuard::validate() 在守卫启用哈希时对令牌进行哈希处理。在此之前,对于有效的令牌它返回 false 
  • 因连接丢失而失败的提交现在会丢弃 PDO,因此 PostgreSQL 连接会重新连接,而不是导致后续所有事务失败 
  • foreignIdFor() 为具有 $keyType = 'integer' 的模型创建 bigint 列,而不是 char(36) 列
  • JSON:API 复合文档仅包含一次相同的 BelongsToMany 资源
  • dispatch()->afterResponse() 报告异常,而不是尝试渲染它们