akatekno/attachable

为Laravel的简单附件扩展

1.0.1 2024-04-14 20:26 UTC

This package is not auto-updated.

Last update: 2024-09-29 22:29:28 UTC


README

这是一个实现模型中多个附件的简单包。因为这个包是基于我不停地创建相同模型和迁移的烦恼而创建的,所以这就是我创建Attachable包的原因。

安装

在你的Laravel应用中,运行composer require akatekno/attachable,然后运行php artisan migrate来创建attachments表。

用法

目前有两个类型的Attachable可用

  1. AttachableOne如果你只想在每个模型中实现一个附件。例如,用户的个人资料图片或用户的身份证。
  2. AttachableMany如果你想在每个模型中实现多个附件。例如,博客的相册图片或报告的附件。

AttachableOne

代码实现相当简单

  1. 实现接口AttachableOne和特质AttachableOne
<?php

namespace App\Models;

use Akatekno\Attachable\Interfaces\AttachableOne;
use Akatekno\Attachable\Traits\AttachableOne as TraitsAttachableOne;

class User implements AttachableOne
{
    use TraitsAttachableOne;

    // ... the rest of the code
}
  1. 要获取附件数据,使用以下示例
<?php

use App\Models\User;

class Controller
{
    public function index()
    {
        return User::first()->attachment;
    }
}

这将返回以下数据

{
    "id": "9b94845b-c357-4248-93cf-8ce10d7c249f",
    "attachable_type": "App\\Models\\User",
    "attachable_id": 1,
    "name": "pdf-example.pdf",
    "path": "2024-03-16/Ifd5GkgoyAvcLihEMz7i7SSLC46rEj2aFO9HGJwz.pdf",
    "mime_type": "application/pdf",
    "extension": "pdf",
    "size": 36115,
    "type": null,
    "created_at": "2024-03-16T20:43:00.000000Z",
    "updated_at": "2024-03-16T20:43:00.000000Z",
    "deleted_at": null
}
  1. 要将数据存储到附件中,使用以下示例
<?php

use App\Models\User;
use Illuminate\Support\Facades\Route;

Route::post('attach', function (Request $request) {
    $file = $request->file('file');

    $user = User::first();

    $user->attachments()->create([
        'name' => $file->getClientOriginalName(),
        'path' => $file->store(date('Y-m-d')),
        'mime_type' => $file->getClientMimeType(),
        'extension' => $file->getClientOriginalExtension(),
        'size' => $file->getSize(),
        'type' => null,
    ]);
});

AttachableMany

这个实现与AttachableOne类似,不同之处在于将attachment变为复数attachments的使用。

  1. 实现接口AttachableMany和特质AttachableMany
<?php

namespace App\Models;

use Akatekno\Attachable\Interfaces\AttachableMany;
use Akatekno\Attachable\Traits\AttachableMany as TraitsAttachableMany;

class User implements AttachableMany
{
    use TraitsAttachableMany;

    // ... the rest of the code
}
  1. 要获取附件数据,使用以下示例
<?php

use App\Models\User;

class Controller
{
    public function index()
    {
        return User::first()->attachments;
    }
}

这将返回以下数据

[
    {
        "id": "9b94845b-c357-4248-93cf-8ce10d7c249f",
        "attachable_type": "App\\Models\\User",
        "attachable_id": 1,
        "name": "pdf-example.pdf",
        "path": "2024-03-16/Ifd5GkgoyAvcLihEMz7i7SSLC46rEj2aFO9HGJwz.pdf",
        "mime_type": "application/pdf",
        "extension": "pdf",
        "size": 36115,
        "type": null,
        "created_at": "2024-03-16T20:43:00.000000Z",
        "updated_at": "2024-03-16T20:43:00.000000Z",
        "deleted_at": null
    },
    {
        "id": "9b948473-7ea7-40b1-b83e-253d30913eea",
        "attachable_type": "App\\Models\\User",
        "attachable_id": 1,
        "name": "pdf-example.pdf",
        "path": "2024-03-16/69HDlwDFPZ5kKa7OTO3x2OfSeejx3gkHXwFzqBmC.pdf",
        "mime_type": "application/pdf",
        "extension": "pdf",
        "size": 36115,
        "type": null,
        "created_at": "2024-03-16T20:43:16.000000Z",
        "updated_at": "2024-03-16T20:43:16.000000Z",
        "deleted_at": null
    }
]
  1. 要将数据存储到附件中,使用以下示例
<?php

use App\Models\User;
use Illuminate\Support\Facades\Route;

Route::post('attach', function (Request $request) {
    $files = $request->allFiles();

    $user = User::first();

    /** @var \Illuminate\Http\UploadedFile $file */
    foreach ($files as $file) {
        $user->attachments()->create([
            'name' => $file->getClientOriginalName(),
            'path' => $file->store(date('Y-m-d')),
            'mime_type' => $file->getClientMimeType(),
            'extension' => $file->getClientOriginalExtension(),
            'size' => $file->getSize(),
            'type' => null,
        ]);
    }
});

自定义关系名称

因为这个包简化了MorphOneMorphMany代码的使用,你可以随时修改关系名称,例如

<?php

namespace App\Models;

use Akatekno\Attachable\Models\Attachment;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;

class Reservation extends Model
{
    // ...

    public function visit_request_letter(): MorphOne
    {
        return $this->morphOne(Attachment::class, 'attachable')
            ->where('type', 'visit-request-letter');
    }

    public function hotel_booking_invoice(): MorphOne
    {
        return $this->morphOne(Attachment::class, 'attachable')
            ->where('type', 'hotel-booking-invoice');
    }

    public function other_attachments(): MorphMany
    {
        return $this->morphMany(Attachment::class, 'attachable')
            ->where('type', 'other-attachment');
    }

    // ...
}

现在,你在同一个attachment表中有了3种不同的附件类型。要获取上述示例中的每个关系的数据,只需调用$reservation->visit_request_letter$reservation->hotel_booking_invoice$reservation->other_attachments

要附加文件,只需指定列的type

<?php

// Visit Request Letter
$reservation->visit_request_letter()->create([
    'name' => $file->getClientOriginalName(),
    'path' => $file->store(date('Y-m-d')),
    'mime_type' => $file->getClientMimeType(),
    'extension' => $file->getClientOriginalExtension(),
    'size' => $file->getSize(),
    'type' => 'visit-request-letter',
]);

// Hotel Booking Invoice
$reservation->hotel_booking_invoice()->create([
    'name' => $file->getClientOriginalName(),
    'path' => $file->store(date('Y-m-d')),
    'mime_type' => $file->getClientMimeType(),
    'extension' => $file->getClientOriginalExtension(),
    'size' => $file->getSize(),
    'type' => 'hotel-booking-invoice',
]);

// Other Attachments
$reservation->other_attachments()->create([
    'name' => $file->getClientOriginalName(),
    'path' => $file->store(date('Y-m-d')),
    'mime_type' => $file->getClientMimeType(),
    'extension' => $file->getClientOriginalExtension(),
    'size' => $file->getSize(),
    'type' => 'other-attachment',
]);

待办事项

我们需要有人愿意花时间修复这些问题

  • 表名固定为attachments,如果你有相同的表名,这可能会破坏你的应用程序。
  • 当前支持的Morphable使用UUID作为其主键,我们需要更多类型的ID,如ULID和自增ID。

在修复上述问题后,我们将制作一个配置文件,以便你可以根据个人喜好调整包。