phoenixfire296 / laravel-attachments
Laravel包,利用Eloquent SoftDelete将文件附件链接到模型
Requires
- php: >=7.0
- bnbwebexpertise/php-uuid: >=0.0.2
- doctrine/dbal: ~2.5
- illuminate/console: 5.7.x|5.6.x|5.5.x
- illuminate/database: 5.7.x|5.6.x|5.5.x
- illuminate/encryption: 5.7.x|5.6.x|5.5.x
- illuminate/routing: 5.7.x|5.6.x|5.5.x
- illuminate/support: 5.7.x|5.6.x|5.5.x
- nesbot/carbon: ~1.20
Requires (Dev)
- laravel/framework: 5.7.x|5.6.x|5.5.x
README
此包允许快速将文件链接到模型。
也可以安装在Laravel 5.4上,见下文
安装
您可以通过composer安装此包。Laravel 5.5+会自动发现服务提供者。
composer require bnbwebexpertise/laravel-attachments
Laravel 5.4旧版本安装
为支持5.4,请安装版本0.0.16
composer require bnbwebexpertise/laravel-attachments:0.0.16
然后添加服务提供者到您的配置
'providers' => [ // ... Bnb\Laravel\Attachments\AttachmentsServiceProvider::class, // ... ],
配置
您可以通过发布配置文件来定制此包的行为
php artisan vendor:publish --provider='Bnb\Laravel\Attachments\AttachmentsServiceProvider'
将附件添加到模型类中
将HasAttachment
特质添加到您的模型类
<?php namespace App; use Bnb\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
文件输出钩子
Bnb\Laravel\Attachments\Attachment
模型类提供了一个outputting
事件,您可以观察它。
在应用程序服务提供者中,您可以写入例如
<?php use Bnb\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
上传
此包提供了一个服务器端点,用于Dropzone.js或等效的通过attachments.dropzone
路由别名。
它返回附件的uuid
以及其他字段作为JSON响应。此值可以稍后发送到服务器,以将其绑定到模型实例(延迟保存)。
表单
<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(); Bnb\Laravel\Attachments\Attachment::attach(Request::input('attachment_id'), $model); return redirect('/dropzone'); });
删除
可以通过HTTP DELETE
调用attachments.dropzone.delete
路由。必须提供附件ID作为参数。
此路由提供的删除操作**仅适用于挂起附件**(未绑定到模型)。
为了避免删除其他用户的文件,当通过dropzone端点上传时,当前CSRF令牌被保存,并且在调用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 : Request
attachments.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
您可以通过Attachment
模型的getTemporaryUrl
方法生成一个唯一的临时URL来下载附件,主要用于分享。getTemporaryUrl
方法有一个参数:一个Carbon
日期,在此日期之后,链接将不再有效。
默认生成的URL形式为:http://example.com/attachments/shared/<一个非常长的字符串>
。可以通过配置文件中的shared_pattern
键修改共享路径。
清理命令
提供了一个清理未绑定到模型的附件的命令(当model_type
和model_id
为null
时)。
php artisan attachment:cleanup
可以使用-s
(或--since=[timeInMinutes]
)选项来设置另一个时间限制(分钟):只有超过指定年龄的未绑定文件将被删除。默认值为1440
。
自定义
为模型设置自定义数据库连接名称
您可以通过以下方式自定义数据库连接名称:
- 为
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控制器上传的附件。仅适用于显式附件。
扩展附件模型类
这有助于向附件模型添加一些关系。
创建一个继承自Bnb\Laravel\Attachments\Attachment
的自定义模型
<?php namespace Foo\Models; MyAttachment extends Bnb\Laravel\Attachments\Attachment { public function someCustomRelation() { // } }
在服务提供者中将您的模型绑定到Bnb\Laravel\Attachments\Contracts\AttachmentContract
接口
public function register() { // ... $this->app->bind( \Bnb\Laravel\Attachments\Contracts\AttachmentContract::class, \Foo\Models\MyAttachment::class ); // ... }