tecdiary / laravel-attachments
将文件附加到您的模型中,可以通过键、组名或使用 Eloquent 关系进行检索。
Requires
- php: >=8.0.2
- bnbwebexpertise/php-uuid: >=0.0.2
- doctrine/dbal: ^3.0
- illuminate/console: >=8.37
- illuminate/database: >=8.37
- illuminate/encryption: >=8.37
- illuminate/routing: >=8.37
- illuminate/support: >=8.37
- nesbot/carbon: ^1.20 || ^2.0
Requires (Dev)
- laravel/framework: >=8.37
This package is auto-updated.
Last update: 2024-09-24 12:00:18 UTC
README
此仓库是 B&N Web Expertise 的
bnbwebexpertise/laravel-attachments的分支。
此软件包允许您快速将文件附加到模型中,可以通过键、组名或使用 Eloquent 关系进行检索。
安装
您可以通过 composer 安装此软件包。
composer require tecdiary/laravel-attachments
配置
您可以通过发布配置文件来自定义此软件包的行为
php artisan vendor:publish --provider='Tecdiary\Laravel\Attachments\AttachmentsServiceProvider' --tag="config"
迁移
此软件包将加载迁移,但如果您不想,可以通过软件包调用 AttachmentsServiceProvider::ignoreMigrations() 来发布迁移并停止加载迁移。
php artisan vendor:publish --provider="Tecdiary\Laravel\Attachments\AttachmentsServiceProvider" --tag="migrations"
php artisan migrate
在 AppServiceProvider 的 register 方法中添加以下行
\Tecdiary\Laravel\Attachments\AttachmentsServiceProvider::ignoreMigrations();
将附件添加到模型类中
将 HasAttachment 特性添加到您的模型类中
<?php namespace App; use Tecdiary\Laravel\Attachments\HasAttachment; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable, HasAttachment; // ... }
然后使用它将文件绑定到一个实例上
$user = App\User::create([ 'name' => 'name', 'email' => 'email@foo.bar', 'password' => 'password', ]); // Bind a local file $attachment = $user->attach('local/path/to/file.txt'); // Bind an uploaded file $attachment = $user->attach(\Request::file('uploaded_file')); // Bind an uploaded file with options $attachment = $user->attach(\Request::file('uploaded_file'), [ 'disk' => 's3', 'title' => \Request::input('attachment_title'), 'description' => \Request::input('attachment_description'), 'key' => \Request::input('attachment_key'), ]);
检索模型的附件
$user = App\User::first(); $allAttachments = $user->attachments()->get(); $attachmentByKey = $user->attachment('myKey'); // Attachment public URL $publicUrl = $attachmentByKey->url;
重新分组模型的附件
group 属性允许分组附件。由 HasAttachment 特性提供的 attachmentsGroup 方法返回具有给定 group 值的所有附件。
$user = App\User::first(); $user->attach($somefile, [' 'group' => 'album', ']); $user->attach($otherfile, [' 'group' => 'album', ']); $attachmentsByGroup = $user->attachmentsGroup('album');
删除附件
在附件模型实例上调用 delete() 方法将删除数据库行和文件。可以通过在配置中将 behaviors.cascade_delete 设置为 false 来禁用文件的删除。
注意,在
query()语句上调用delete()不会级联到文件系统,因为它不会调用Attachment模型类的delete()方法。
$user = App\User::first(); $attachmentByKey = $user->attachment('myKey'); $attachmentByKey->delete(); // Will also delete the file on the storage by default
钩子文件输出
Tecdiary\Laravel\Attachments\Attachment 模型类提供了一个可观察的 outputting 事件。
在应用程序服务提供程序中,您可以编写例如
<?php use Tecdiary\Laravel\Attachments\Attachment; class AppServiceProvider extends ServiceProvider { // ... public function boot() { // ... Attachment::outputting(function ($attachment) { /** @var Attachment $attachment */ // Get the related model $model = $attachment->model; if (empty($model)) { // Deny output for attachments not linked to a model return false; } if ($model instanceof \App\User) { // Check if current user is granted and owner $user = \Auth::user(); return $user && $user->can('download-file') && $user->id == $model->id; } }); // ... } // ... }
Dropzone
上传
此软件包通过 attachments.dropzone 路由别名提供了用于 Dropzone.js 或等效的服务器端点。
它以 JSON 响应返回附件 uuid 以及其他字段。此值可以在稍后发送回服务器以将其绑定到模型实例(延迟保存)。
表单
<form action="{{ route('attachments.dropzone') }}" class="dropzone" id="my-dropzone" > {{ csrf_field() }} </form>
响应
{
"title": "b39ffd84524b",
"filename": "readme.md",
"filesize": 2906,
"filetype": "text/html",
"uuid": "f5a8eec2-d860-4e53-8451-b39ffd84524b",
"key": "58ac52e90db938.72105394",
"url": "http://laravel.dev:8888/attachments/f5a8eec2-d860-4e53-8451-b39ffd84524b/readme.md"
}
稍后发送
<form action="/upload" method="post"> {{ csrf_field() }} <input type="hidden" name="attachment_id" id="attachment_id" /> <button type="submit">Save</button> </form> <!-- Where attachment_id is populated on success --> <script> Dropzone.options.myDropzone = { init: function () { this.on("success", function (file, response) { document.getElementById("attachment_id").value = response.uuid; }); }, }; </script>
稍后绑定值
<?php Route::post('/upload', function () { $model = App\User::first(); Tecdiary\Laravel\Attachments\Attachment::attach(Request::input('attachment_id'), $model); return redirect('/dropzone'); });
删除
可以通过 HTTP DELETE 调用 attachments.dropzone.delete 路由。必须提供附件 ID 作为参数。
此路由提供的删除操作 仅适用于挂起的附件(未绑定到模型)。
为了避免删除其他用户的文件,当前 CSRF 令牌在上传通过 dropzone 端点时保存,并且在调用 dropzone 删除端点时必须相同。此行为可以通过配置或环境键(见 config/attachments.php)来禁用。
使用示例
<script> var MyDropzone = { url: "{{ route('attachments.dropzone.delete', ['id' => ':id']) }}" // ... deletedfile: function (file) { axios.delete(this.url.replace(/:id/, file.id)).then(function () { //... }); } //... } </script>
事件
由 dropzone 端点控制器触发两个事件
attachments.dropzone.uploading,参数为$request : Requestattachments.dropzone.deleting函数,带有参数$request : Request和$file : Attachement
如果任何一个监听器返回 false,则操作将被中止。
public function boot() { Event::listen('attachments.dropzone.uploading', function ($request) { return $this->isAllowedToUploadFile($request); }); Event::listen('attachments.dropzone.deleting', function ($request, $file) { return $this->canDeletePendingFile($request, $file); }); }
临时 URL
可以通过附件模型的 getTemporaryUrl 方法生成一个唯一的临时 URL,用于下载附件,主要用于分享。该方法有一个参数:一个 Carbon 日期,在此之后链接将不再有效。
默认生成的 URL 形式为:http://example.com/attachments/shared/<一个非常长的字符串>。分享路径可以在配置文件中通过 shared_pattern 键进行修改。
清理命令
提供了一个命令来清理未绑定到模型的附件(当 model_type 和 model_id 为 null 时)。
php artisan attachment:cleanup
可以使用 -s(或 --since=[timeInMinutes])选项来设置另一个时间限制(以分钟为单位):只有超过指定年龄的未绑定文件将被删除。默认值为 1440。
迁移命令
将所有附件从一个源磁盘迁移到另一个磁盘
php artisan attachments:migrate public s3
如果文件在目标磁盘上成功保存,则从源磁盘删除文件。
自定义
为模型设置自定义数据库连接名称
您可以通过以下方式自定义数据库连接名称:
- 为
ATTACHMENTS_DATABASE_CONNECTION添加一个.env变量(推荐)或者 - 在
config/attachments.php中更改配置选项attachments.database.connection。
扩展附件模型列
配置定义了在 attachment.attributes 键中可填充的附件属性列表。
这允许您创建迁移,在附件表中添加新列,并在 config/attachments.php 的发布配置中声明它们。
自定义附件存储目录前缀
您可以通过以下方式轻松自定义存储新附件的文件夹/前缀:
- 为
ATTACHMENTS_STORAGE_DIRECTORY_PREFIX添加一个.env变量(推荐)或者 - 在
config/attachments.php中更改配置选项attachments.storage_directory.prefix。
默认值为 attachments,任何尾随的 / 将自动删除。
自定义附件存储文件路径
如果您不想使用默认的存储文件路径生成,可以提供 filepath 选项(相对于存储磁盘的根目录)。它必须包含目录和文件名。确保提供的文件路径不与另一个文件冲突是您的责任。
$model->attach('/foo/bar/pdf.pdf', ['filepath' => 'foo/bar/test.pdf']);
此操作不适用于通过集成 DropZone 控制器上传的附件。仅适用于显式附件。
扩展附件模型类
这有助于向附件模型添加一些关系。
创建一个扩展 Tecdiary\Laravel\Attachments\Attachment 的自定义模型
<?php namespace App; class MyAttachment extends Tecdiary\Laravel\Attachments\Attachment { // ... public function someCustomRelation() { // ... } // ... }
要配置您的自定义模型类,可以使用以下可能性之一:
- 发布配置并更新
attachment_model值 - 设置
ATTACHMENTS_MODEL环境值 - 在服务提供者中将您的模型绑定到
Tecdiary\Laravel\Attachments\Contracts\AttachmentContract接口
示例
<?php return [ // ... 'attachment_model' => \App\MyAttachment::class, // .. ];
# ... ATTACHMENTS_MODEL=\App\MyAttachment # ...
<?php // ... class AppServiceProvider extends ServiceProvider { // ... public function register() { // ... $this->app->bind( \Tecdiary\Laravel\Attachments\Contracts\AttachmentContract::class, \App\MyAttachment::class ); // ... } // ... }