phoenixfire296/laravel-attachments

Laravel包,利用Eloquent SoftDelete将文件附件链接到模型

安装: 287

依赖者: 0

建议者: 0

安全: 0

星标: 0

关注者: 1

分支: 28

类型:package

1.0.7.2 2019-02-13 22:48 UTC

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_typemodel_idnull时)。

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
        );
        // ...
    }