媒体库 Pro:Vue、React 和 Blade 组件,用于处理上传(赞助)
发布时间 作者: Freek Van der Herten
我很自豪地宣布 媒体库 Pro 现已推出。媒体库 Pro 是 我们免费的媒体库基础包 的附加软件包。它包含一组 Blade、Vue 和 React 组件,可以轻松地将文件上传到媒体库,并管理媒体库集合中的文件。
在本博文中,我想向大家介绍媒体库 Pro。
了解 Laravel 媒体库
在开始了解 Pro 组件之前,让我们先了解一下 免费版媒体库 可以为您做什么。如果您已经熟悉免费版媒体库,可以跳过此部分。
简而言之,媒体库可以将文件与 Eloquent 模型关联。例如,您可以将图像与博客文章模型关联。
$blogPost ->addMedia($pathToFile) ->toMediaCollection('images');
在您的 Blade 视图中,您可以检索与关联图像的 URL。
@foreach($blogPost->getMedia('images') as $mediaItem) <img src="{{ $mediaItem->getUrl() }}" alt="my image" />@endforeach
媒体库还可以生成各种转换。使用博客文章示例,您可能不希望在博客文章列表中显示原始图像。您更有可能希望在 such a list 上显示图像的较小版本(缩略图)。
您可以通过在模型上定义转换来让媒体库生成转换后的图像。以下是在 BlogPost
模型中可以添加的转换。
// somehwere in the BlogPost model public function registerMediaConversions(Media $media = null): void{ $this->addMediaConversion('thumb') ->width(300) ->height(300) ->sharpen(10);}
有了这些,媒体库将生成一个适合 300×300 方格的缩略图。图像也会略微锐化,因此看起来很清晰。当然,该缩略图将比原始图像小很多。您可以使用转换的名称作为 getUrl
的参数来获取转换的 URL。
@foreach($blogPost->getMedia('images') as $mediaItem) <img src="{{ $mediaItem->getUrl('thumb') }}" alt="my thumbnail" />@endforeach
在上面的示例中,我们定义了一个 thumb 转换,但您可以在模型中添加任意数量的转换。
媒体库还可以做更多事情。它可以 处理多个集合、使用多个文件系统、动态创建压缩包以下载多个文件、使用 自定义目录结构、使用响应式图像节省带宽等等。
在这两段视频中,我向大家展示了 Laravel 媒体库的基础知识。
想观看更多类似的视频吗?查看我们的 关于如何使用 Laravel 媒体库的免费视频课程。
传统上传的问题
在探索媒体库 Pro 之前,让我们先解释一下我们为什么要构建它。以下是传统上传表单可能的样子。它使用一个常规的 input
类型为 file
。
以下是渲染该表单的 Blade 视图。它取自 此演示应用程序
<form method="POST" enctype="multipart/form-data"> <x-grid> @csrf <x-field label="name"> <x-input id="name" name="name" placeholder="Your first name" /> </x-field> <x-field label="file"> <input type="file" name="file"> @error('file') {{ $message }} @enderror </x-field> <x-button dusk="submit">Submit</x-button> </x-grid></form>
此标准上传元素存在两个主要问题。
首先,上传过程仅在提交表单时开始。对于小型表单中的小型文件,这可能不是问题。但想象一下,您要在一个表单中上传一个多 MB 的文件。提交表单时,您现在必须等待上传完成才能看到提交结果。
第二个问题是,长期以来一直困扰着我。想象一下,输入字段是表单的一部分,该表单的一些字段是必需的。您正在选择一个文件,提交表单,留下一些必需字段为空。您被重定向回表单,现在显示了错误消息。您之前的文件选择消失了,您需要再次选择文件。多年来,每次发生这种情况时,我都会说很多脏话。
我敢肯定,作为一名开发人员,您可能在调试上传时浪费了时间,因为您忘记了在表单中添加 enctype="multipart/form-data"
。
在本视频中,您将看到所有这些问题的演示。
让我们看看 媒体库 Pro 如何解决所有这些问题。
介绍媒体库 Pro
媒体库 Pro 是一个付费的附加软件包,它提供 Blade、Vue 和 React 组件,用于将文件上传到您的应用程序。它附带两个组件。第一个是附件组件。它旨在用于面向公众的页面,您希望用户在该页面上上传一个或多个文件。
第二个称为集合组件。该组件可以管理现有集合中的文件。它旨在用于应用程序的管理部分。
这两个组件都提供 Vue、React 和 Blade 组件。在幕后,Blade 组件由 Caleb 的出色 Livewire 软件包 提供支持。
这些组件安装简单,并且 文档齐全。
让我们看看 Attachment
和 Collection
组件。在博文的剩余部分,我将使用 Blade 版本的示例,但请放心,所有显示的内容也可以使用 Vue 和 React 对应部分完成。
附件组件
如果您想快速演示附件组件,请查看此视频。
您可以在 GitHub 上的此仓库 中找到视频中使用的代码。所有后续的代码示例都取自该应用程序。
要开始使用 Attachment
Blade 组件,您需要在 您的视图 中使用 x-media-library-attachment
。
<form method="POST"> @csrf <input id="name" name="name"> <x-media-library-attachment name="avatar"/> <button type="submit">Submit</button></form>
以下是我们在选择文件但未提交表单之前的样子。
x-media-library-attachment
已经处理了上传。该文件现在存储为临时上传。如果提交表单时出现验证错误,x-media-library-attachment
将在您被重定向回表单时显示临时上传。用户无需再次上传文件。
以下是 用于验证上传的表单请求。
namespace App\Http\Requests\Blade; use Illuminate\Foundation\Http\FormRequest;use Spatie\MediaLibraryPro\Rules\Concerns\ValidatesMedia; class StoreBladeAttachmentRequest extends FormRequest{ use ValidatesMedia; public function rules() { return [ 'name' => 'required', 'media' => ['required', $this->validateSingleMedia() ->maxItemSizeInKb(3000), ], ]; }}
通过应用 ValidatesMedia
特性,您可以访问 validateSingleMedia
,它允许您验证上传。您可以链接多个验证方法,这些方法在 此处 有文档记录。
在您的控制器中,您可以将上传文件与您想要的任何模型关联。
$formSubmission ->addFromMediaLibraryRequest($request->media) ->toMediaCollection('images');
这就是您需要做的全部!
附件组件也可以用于处理多个上传。在本视频中,您将看到如何操作。
集合组件
您可以使用 `x-media-library-collection` 组件管理媒体库集合的全部内容。此组件旨在用于管理部分。
以下是一个示例,我们将管理 `$formSubmission` 模型的 `images` 集合。
<form method="POST"> @csrf <x-field label="name"> <x-input id="name" name="name" autocomplete="off" placeholder="Your name" value="{{ old('name', $formSubmission->name) }}"/> </x-field> <x-field label="Images"> <x-media-library-collection name="images" :model="$formSubmission" collection="images" max-items="3" rules="mimes:png,jpeg" /> </x-field> <x-button dusk="submit" type="submit">Submit</x-button></form>
以下是该组件的示例:
此组件将显示整个集合的内容。可以添加、删除、更新和重新排序文件。
在这个视频中,您将看到集合组件的实际应用。
为了验证表单的响应,可以使用这样的表单请求:
namespace App\Http\Requests\Blade; use Illuminate\Foundation\Http\FormRequest;use Spatie\MediaLibraryPro\Rules\Concerns\ValidatesMedia; class StoreBladeCollectionRequest extends FormRequest{ use ValidatesMedia; public function rules() { return [ 'name' => 'required', 'images' => [$this->validateMultipleMedia() ->maxItems(3) ->itemName('required'), ], ]; }}
同样,您需要使用 `ValidatesMedia` 特性。这次应该使用 `validateMultipleMedia`。您可以在其他验证方法上进行链接,这些方法在 此处 有文档记录。
在控制器中,您可以使用 `syncFromMediaLibraryRequest` 方法将集合组件中的媒体与您的模型关联起来。
以下是在 演示应用程序的控制器 中的相关代码。
$formSubmission ->syncFromMediaLibraryRequest($request->images) ->toMediaCollection('images');
添加自定义属性
使用集合组件时,您可能希望添加一些额外的字段以供显示。我们已经让这件事变得非常简单。
在下面的屏幕截图中,我们添加了 `Extra field` 字段。
您可以通过将 blade 视图传递到 `x-media-library-collection` 的 `fields-view` 属性 来实现这一点。
<x-media-library-collection name="images" :model="$formSubmission" collection="images" max-items="3" rules="mimes:png,jpeg" fields-view="uploads.blade.partials.custom-properties"/>
在该 `custom-properties` 视图中,您可以放置任何应该在 `collection component` 右半部分显示的内容。
以下是 该 `custom-properties` 视图 的内容。
@include('media-library::livewire.partials.collection.fields') <div class="media-library-field"> <label class="media-library-label">Extra field</label> <input dusk="media-library-extra-field" class="media-library-input" type="text" {{ $mediaItem->customPropertyAttributes('extra_field') }} /> @error($mediaItem->customPropertyErrorName('extra_field')) <span class="media-library-text-error"> {{ $message }} </span> @enderror</div>
在 表单请求 中,您可以使用 `customProperty` 来验证任何额外的自定义属性。该函数的第二个参数可以接受 Laravel 中的任何验证器。
namespace App\Http\Requests\Blade; use Illuminate\Foundation\Http\FormRequest;use Spatie\MediaLibraryPro\Rules\Concerns\ValidatesMedia; class StoreBladeCollectionCustomPropertyRequest extends FormRequest{ use ValidatesMedia; public function rules() { return [ 'name' => 'required', 'images' => [$this->validateMultipleMedia() ->maxItems(3) ->itemName('required|max:30') ->customProperty('extra_field', 'required|max:30'), ], ]; }}
在 处理表单提交的控制器 中,您应该使用 `withCustomProperties` 方法来白名单您想要与媒体同步的任何额外属性。
$formSubmission ->syncFromMediaLibraryRequest($request->images) ->withCustomProperties('extra_field') ->toMediaCollection('images');
以下是一个视频,您将在其中看到所有这些操作的实际应用。
自定义外观和感觉
默认情况下,`Attachment` 和 `Collection` 组件看起来都很好。您可能希望调整它们以匹配应用程序的外观。
幸运的是,这很容易做到。Media Library Pro 附带的样式可以通过导入或链接 `dist/styles.css` 来使用。这些样式是用默认的 `tailwind.config.js` 构建的。
您可以通过导入 `src/styles.css` 并运行每个 `@apply` 规则来自定义样式,这些规则通过您自己的 `tailwind.config.js` 运行。
/* app.css */ @tailwind base; @tailwind components; @tailwind utilities; @import "src/styles.css"; …
要查看此操作的实际应用,请观看此视频。
临时文件的使用方式
为了实现上传文件在表单验证错误发生时仍然保留的行为,我们使用临时上传。在这个视频中,我解释了它是如何工作的。
测试组件
在 私有的 spatie/laravel-medialibrary-pro 仓库 中,有很多测试来确保后端集成以及 Vue、React 和 Blade 前端组件按预期工作。
我们还希望进行浏览器测试,以确保前端组件与后端完美配合,反之亦然。这就是我们在演示应用程序中添加 Dusk 测试的原因。您可以在 此处 查看它们。
让我们看一下 其中之一
/** * @test * * @dataProvider routeNames */public function it_can_handle_a_single_upload(string $routeName){ $this->browse(function (Browser $browser) use ($routeName) { $browser ->visit(route($routeName)) ->type('name', 'My name') ->attach('@main-uploader', $this->getStubPath('space.png')) ->waitForText('Remove') ->waitUntilMissing('.media-library-progress-wrap.media-library-progress-wrap-loading') ->press('@submit') ->assertSee('Your form has been submitted'); $this->assertCount(1, FormSubmission::get()); $this->assertEquals('space.png', FormSubmission::first()->getFirstMedia('images')->file_name); });}
此测试将上传一个文件,并确保在提交表单后该文件与模型关联起来。
这里要注意的是 `@dataProvider` 属性。这将使 PHPUnit 对 `routeNames` 函数返回的每个结果运行测试,该函数在同一文件中的 定义。
public function routeNames(): array{ return [ ['vue.attachment'], ['react.attachment'], ['blade.attachment'], ];}
您可以看到,与 `routeNames` 函数结合使用,`it_can_handle_a_single_upload` 将针对 `vue.attachment`、`react.attachment` 和 `blade.attachment` 路由运行。访问这些路由将分别显示使用 Vue、React 或 Blade 组件的表单。因此,此测试涵盖了许多逻辑。它确保该组件使用任何技术都可以正常工作。这让我们对所有组件都正常工作充满信心。
另一个值得注意的是,Dusk 测试也在 GitHub Actions 上运行。以下是仓库中包含的 工作流。
最后
在我看来,这些前端组件是媒体库体验中缺失的最后一块拼图。我很高兴它们最终的效果以及现在在 Laravel 应用程序中上传和管理媒体变得多么容易。
由于我们在使这些组件完美无缺方面投入了相当多的时间,我们决定将 spatie/laravel-media-library-pro 作为付费软件包。您可以在我们的网站上 购买许可证。如前所述,该软件包包含 Blade、Vue 和 React 组件。您将在此处找到详细的文档。
购买许可证后,您将立即获得访问 私有的 spatie/laravel-medialibrary-pro 仓库 的权限。即使您没有购买强大的上传组件的计划,购买它们仍然可能值得:源代码包含许多您可以从中学习的有趣内容。
在撰写本文时,我们正在进行发布促销活动。在 购买 Media Library Pro 时使用此优惠券代码,可享受 20% 的折扣。
MEDIA-LIBRARY-PRO-IS-HERE
我们的整个团队都对这些组件提出了意见,因此我认为这是团队合作的结果。我的同事 Adriaan 编写了大部分 JavaScript 代码。 Willem 总是让一切看起来都很漂亮。
对于那些想知道的人来说,基础媒体库软件包 仍然是免费的,我们也会永远保持免费。
务必查看 我们其他付费产品 和 我们丰富的免费开源软件包集合。