yassinedabbous/laravel-file-cast

轻松将上传文件与数据库列关联

v1.3.0 2024-09-21 20:58 UTC

This package is auto-updated.

Last update: 2024-09-26 15:51:26 UTC


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),
];