yassinedabbous / laravel-file-cast
轻松将上传文件与数据库列关联
v1.3.0
2024-09-21 20:58 UTC
Requires
- php: >=7.4
- laravel/framework: ^5.5|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0
Requires (Dev)
- orchestra/testbench: ^9.0
README
Laravel 文件转换
轻松将上传文件与表列关联
目录
✨ 功能
- 轻松将上传文件从 请求 映射到 模型。
- 处理 多种数据格式(文件实例、本地路径、远程 URL、Base64 URI、数组值...)。
- 旧文件在更新和删除事件中会自动清理。
- 无需额外代码,无需媒体表!
🔻 安装
composer require yassinedabbous/laravel-file-cast
🧑💻 使用
只需将 FileCast::class 类用于任何表列,如下所示
use YassineDabbous\FileCast\FileCast; class User extends Model { # Laravel<11.x protected $casts = [ 'avatar' => FileCast::class, // use default disk 'avatar' => FileCast::class.':s3,photo.png', // use "S3" disk and "photo.png" as default value ]; # OR # Laravel >=11.x public function casts(): array { return [ 'avatar' => FileCast::class, // use default disk 'avatar' => FileCast::using(disk: 's3', default: 'photo.png'), // use S3 disk and "photo.png" as default value 'avatar' => FileCast::using(disk: $this->disk_column), // use column value as a disk name ]; } }
这将转换 avatar 列。
对于旧 Laravel 版本(< 11.x)
如果您想以动态值自定义磁盘,则应修改模型以包含一个返回包含每个列磁盘名称的数组的 public 方法
class Post extends Model { ... /** Set a disk for each column */ public function disks(): array { return [ 'photo' => $this->disk_column, # use column value as a disk 'video' => $migrated ? 's3' : 'public', # conditional disk ]; } ... }
🗃️ 支持的数据格式
• 上传文件
假设您的请求表单中有一个名为 "avatar" 的文件/图片,您可以将文件分配给它所在的列
$model->avatar = $request->avatar; $model->save();
或者用请求输入填充模型
Model::create( $request->validated() ); // or $model->update( $request->validated() );
它接受任何类型的文件,因此您也可以这样做
• 本地文件路径
$model->avatar = '/full/path/to/local/file.ext'; $model->avatar; // /disk/folder/file.ext
• 远程文件 URL
$model->avatar = 'https://via.placeholder.com/150/FF0000/FFFFFF'; $model->avatar; // /disk/folder/file.png
• Base64 URI
$model->avatar = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAAWSURBVBhXY/zPwABEDAxMIIKBgYEBAB8XAgIcVRdpAAAAAElFTkSuQmCC'; $model->avatar; // /disk/folder/file.png
• JSON 字符串
$model->avatar = '{"key1": "value1"}'; $model->avatar; // /disk/folder/file.json
• JSON 或 CSV 数组
# Store associative array as *json* file # => folder/file.json $model->avatar = ['key1' => 'value1', 'key2' => 'value2']; # Store multi list array as *csv* file # => folder/file.csv $model->avatar = [ ['value1', 'value2', 'value3'], ['value1', 'value2', 'value3'], ['value1', 'value2', 'value3'], ];
• NULL ?
空值将导致自动删除文件(可配置)
$model->avatar = null; # == $model->avatar->delete();
这从未如此简单!
🛠️ 功能
为了向文件转换器提供更多功能,此包使用名为 FileField 的包装类,该类充当 Storage 门面的代理,并具有一些附加方法。
• 存储代理
作为 Laravel Storage 门面的代理,您可以直接在文件字段上调用 Storage 中的任何方法,而无需提供文件路径
use Illuminate\Support\Facades\Storage; # using Laravel Storage Facade: Storage::disk('disk')->url(path: 'path.ext'); Storage::disk('disk')->json(path: 'path.ext'); Storage::disk('disk')->put(path: 'path.ext', contents: 'data'); Storage::disk('disk')->temporaryUrl(path: 'path.ext', expiration: now()->addMinutes(5)); ... # using File Cast $model->avatar->url(); $model->avatar->json(); $model->avatar->put(contents: 'data'); $model->avatar->temporaryUrl(expiration: now()->addMinutes(5)); ...
• 附加方法
除了 Storage 方法外,FileField 还提供了一些有用的方法
$model->avatar->toBase64(); # Base64 string: 'iVBORw0KGgoAAAANS...' $model->avatar->toBase64URI(); # Base64 URI: 'data:image/png;base64,iVBORw0KGgoAAAANS...' $model->avatar->toArray(); # returns *json* and *csv* file's content as array
• 文件操作
- 删除文件
当列值更新时,旧文件会自动清理。
$model->avatar; # 'old_file.png'; $model->avatar = $newFileUploaded; # 'old_file.png' deleted!
要自动在模型 deleted 事件上删除旧文件,请将 HasFileCast 特性添加到您的模型中。
use YassineDabbous\FileCast\HasFileCast; class User extends Model { use HasFileCast; ... }
要手动删除文件
$model->avatar = NULL; # Delete the file without updating table. $model->avatar->delete(); # Delete the file without updating table. $model->avatar->delete(persist: TRUE); # Delete the file & save changes to DB.
- 将文件移动到新路径
$model->avatar; # 'folder/old_file.png'; $model->avatar = '@new_folder/new_file.png'; # Move the file without updating table. (path should start with "@") $model->avatar->move(to: 'new_folder/new_file.png'); # Move the file without updating table. $model->avatar->move(to: 'new_folder/new_file.png', persist: TRUE); # Move the file & save changes to DB.
• 扩展
File Cast 是“可宏化”的,这使得您可以在运行时向 FileField 类添加额外的方法。FileField 类的宏方法接受一个闭包,当您的宏被调用时,将执行该闭包。宏闭包可以通过 $this 访问 FileField 的其他方法,就像它是一个 FileField 类的真正方法一样。例如,以下代码向 FileField 类添加了一个 resize 方法
use YassineDabbous\FileCast\FileField; FileField::macro('resize', function ($with, $height) { $image = imagecreatefrompng($this->path()); $imgResized = imagescale($image , $with, $height); imagejpeg($imgResized, $this->path()); return $this; }); # resize uploaded image $model->photo = $request->file('image'); $model->photo->resize(500, 500);
⚙️ 配置
您可以选择使用以下内容发布 配置文件
php artisan vendor:publish --tag=file-cast-config
这是默认配置文件的全部内容,将被发布
<?php return [ /** Default value when no file uploaded. */ 'default' => env('FILE_CAST_DEFAULT'), /** Default storage disk */ 'disk' => env('FILE_CAST_DISK'), /** Default storage folder. If NULL, the Model's table name will be used. */ 'folder' => env('FILE_CAST_FOLDER'), /** Automatically clean files on column value updated. */ 'auto_delete' => env('FILE_CAST_AUTO_DELETE', TRUE), ];