Laravel 13.20 引入图片处理
Laravel 13.20.0 为框架添加了第一方图像处理,并提供了一个不可变的、基于驱动的 API,用于转换来自上传、存储、URL 或原始字节的图像。该版本还带来了 WithoutMiddleware 控制器属性、Redis 的专用会话前缀以及一批 Eloquent 和队列附加功能。
- 新增 Image facade 用于图片处理
- 新增 #[WithoutMiddleware] 控制器注解
- 配置了一个 Redis 专用会话前缀
- Eloquent 模型的静默递增及递减
- 枚举作为
WithoutOverlapping队列键被接受 - 等等
新增
图像处理
Laravel 13.20 引入了 Illuminate\Image 组件,用于在无需借助第三方工具的情况下处理图像大小、剪切、格式化转换以及存储。
原图不可变:每次转换都返回新的实例,并且当你请求结果时,队列转换方才应用。
最常见的路径是上传。
Request::image() 返回特定文件键名的 Image 实例,如果该键名下没有对应的文件,则返回 null:
$request->image('avatar')
->cover(200, 200)
->toWebp()
->store('avatars');你也可以从路径、URL 、二进制码、base64 或者磁盘中创建文件:
Image::fromPath('/path/to/photo.jpg');
Image::fromUrl('https://example.com/photo.jpg');
Image::fromBytes($bytes);
Image::fromStorage('photos/avatar.jpg', 's3');
Storage::disk('s3')->image('photos/avatar.jpg');转换、输出选项和检查方法都可以在实例上使用:
// Transformations...
$image->cover(200, 200);
$image->contain(800, 600);
$image->crop(200, 200);
$image->resize(1024, 768);
$image->scale(1200, 800);
$image->rotate(90);
$image->blur(10);
$image->sharpen(10);
$image->grayscale();
$image->flip();
$image->flop();
$image->orient(); // Applies EXIF rotation...
// Output format and quality...
$image->toWebp();
$image->toJpg()->quality(80);
$image->optimize(); // WebP at quality 70...
$image->optimize('jpg', 85);
// Reading and inspecting...
$image->toBytes();
$image->toBase64();
$image->toDataUri();
$image->width();
$image->height();
$image->dimensions();
$image->mimeType();
$image->extension();由于原图实例是不可变的,你可以从源图像中生成多个不同分支:
$image = $request->image('photo');
$image->cover(200, 200)->toWebp()->store('thumbnails');
$image->grayscale()->toWebp()->store('grayscale');该组件随带两个驱动,均由 Intervention Image v4 支持:GD 和 Imagick。你可以根据每个图像选择一个驱动,Image Facade 允许你重写驱动程序处理给定转换的方式:
use Illuminate\Image\Transformations\Sharpen;
// Pick a driver per image...
$image->using('imagick');
$image->usingGd();
$image->usingImagick();
// Override how a driver handles a transformation...
Image::transformUsing('gd', Sharpen::class, function ($image, Sharpen $sharpen) {
// Custom sharpen handling for the GD driver...
return $image;
});Intervention Image 是推荐使用的依赖,但不是必需的,你可以根据自己需要安装:
composer require intervention/image#[WithoutMiddleware] 控制器注解
路由注解获得了 #[Middleware] 的对应项。当后者将中间件附加到控制器类或方法时,#[WithoutMiddleware] 会将其排除在外,从而在注解级别为你提供路由组的“排除中间件”行为:
use App\Http\Middleware\EnsureTokenIsValid;
use Illuminate\Routing\Controllers\Attributes\Middleware;
use Illuminate\Routing\Controllers\Attributes\WithoutMiddleware;
#[Middleware(EnsureTokenIsValid::class)]
class UserController
{
public function index()
{
// Middleware applies here...
}
#[WithoutMiddleware(EnsureTokenIsValid::class)]
public function profile()
{
// ...but not here.
}
}使用 ReflectionAttribute::IS_INSTANCEOF 匹配,以便 中间件的子类也排除掉。See #60709.
Redis 会话前缀
指向 Redis 上的 SESSION_DRIVER 和 CACHE_STORE 的应用程序直到现在都有会话继承缓存前缀,这使得在清理或调试共享密钥库时很难找出会话密钥。 config/session.php 中的一个新前缀选项允许你设置一个单独的前缀:
'prefix' => env('SESSION_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-session-'),
The cache store is cloned before the session prefix is applied, so setting it does not affect cache keys. The option is opt-in and mirrors the existing session.connection setting. See #60700.
Eloquent 静默批量递增
Eloquent 已经有用于单列的 incrementQuietly() 和 decrementQuietly()。此次发布添加了incrementEachQuietly() 和 decrementEachQuietly(),填补了压制模型事件时,一次性更新多条记录的空白:
$user->incrementEachQuietly(['posts_count' => 1, 'points' => 10]);
$user->decrementEachQuietly(['credits' => 3, 'tokens' => 2]);See #60720 and the follow-up fix for dynamic calls in #60737.
Enums as Queue Overlap Keys
WithoutOverlapping 任务中间件现在接受 PHP枚举作为其键,因此,以枚举值为键不再需要手动转换为字符串:
class UpdateCategory implements ShouldQueue
{
use Queueable;
public function __construct(protected Category $category) {}
public function middleware(): array
{
return [new WithoutOverlapping($this->category)];
}
}The change is backward compatible with existing string keys. See #60722.
其他修复和改进
- beforePushing() and afterPushing() callbacks on QueueFake (#60689), and MailFake::assertQueuedTimes() is now public (#60710)
- assertEmpty() added to the Storage facade (#60658), and memory usage reported on the WorkerStopping event (#60613)
- make:migration now generates collision-free, ordered timestamp prefixes (#60771)
- #[SensitiveParameter] applied to parameters carrying secrets, keeping them out of stack traces (#60753)
- A capitalize parameter for Stringable::initials() (#60741)
- Str::containsAll() no longer returns true for an empty needles array (#60746), and Number::forHumans() and abbreviate() no longer return -0 for tiny negative values (#60736, #60768)
- Fixes for BelongsToMany::touch() when the related key is not id (#60708), TrustProxies with at:* and multiple proxies (#60726), and providesTemporaryUploadUrls() on the S3 driver (#60755)