farhanshares / laravel-mediaman
MediaMan - 为Laravel提供最优雅且功能强大的媒体管理包!
Requires
- php: ^8.0|^7.3
- illuminate/database: ^7.0|^8.0|^9.0|^10.0|^11.0
- illuminate/support: ^7.0|^8.0|^9.0|^10.0|^11.0
- illuminate/validation: ^7.0|^8.0|^9.0|^10.0|^11.0
- intervention/image: ^2.5
Requires (Dev)
- laravel/framework: ^7.0|^8.0|^9.0|^10.0|^10.0
- laravel/legacy-factories: ^1.3.9
- mockery/mockery: ^1.2.3
- orchestra/testbench: ^5.0|^6.0|^7.0|^8.0||^9.0
- dev-main
- v1.0.0-rc1
- v1.0.0-beta
- v0.9.0
- v0.8.1
- v0.8.0
- v0.7.0
- v0.6.0
- v0.5.1
- v0.5.0
- v0.4.0
- v0.3.0
- v0.2.0
- v0.1.4
- v0.1.3
- v0.1.2
- v0.1.1
- v0.1.0
- dev-dependabot/composer/intervention/image-3.2.1
- dev-dependabot/composer/orchestra/testbench-8.19.0
- dev-dependabot/composer/mockery/mockery-1.6.7
- dev-dependabot/github_actions/actions/cache-3.3.2
- dev-dependabot/github_actions/actions/checkout-4
This package is auto-updated.
Last update: 2024-09-15 17:24:07 UTC
README
Laravel MediaMan
MediaMan是一个优雅且功能强大的媒体管理包,适用于Laravel应用程序,支持无痛苦的上传器
、虚拟集合
和自动转换
,并提供与您的应用程序模型特定广播频道
的按需关联
。
MediaMan不依赖于UI,提供流畅的API来管理应用程序的媒体,这意味着您对媒体拥有完全控制权,包括外观、感觉和无忧的开发体验。它是您的应用程序或API服务器的完美选择。
着急?这里有一个快速示例
$media = MediaUploader::source($request->file->('file')) ->useCollection('Posts') ->upload(); $post = Post::find(1); $post->attachMedia($media, 'featured-image-channel');
为什么选择MediaMan?它有什么独特之处?
虽然许多Laravel应用程序都在处理媒体和文件管理,但我经常在Spatie的Laravel MediaLibrary中找到慰藉。然而,尽管它具有功能,但还有一些方面它没有涉及,这是我渴望的功能。
进入MediaMan:时尚、轻量级且功能丰富。无论您需要简单地将媒体附加或解除附加,还是需要一个强大的媒体管理器后端,MediaMan都能满足您的需求。而且请放心,它的演变将遵循现代应用程序不断变化的需求,无论是单体、API驱动、增强Livewire/InertiaJS集成,还是建立在无服务器架构之上。
概述与关键概念
在继续之前,需要了解一些关键概念
-
媒体:它可以是指任何类型的文件。在尝试上传文件之前,您应该在应用程序的验证逻辑中指定文件限制。
-
媒体上传器:媒体项以自己的实体形式上传。在创建时,它不属于系统中的任何其他模型,因此项可以独立管理(这使得它是媒体管理器的完美引擎)。MediaMan提供了“媒体上传器”,用于在数据库中创建记录并存储在文件系统中。
-
媒体集合:它也可以指一组文件。媒体项可以捆绑到任何“集合”。媒体和集合将形成多对多关系。您可以创建集合/虚拟目录/媒体组,稍后检索一组以检查其内容或执行操作。
-
关联:媒体项需要附加到模型才能进行关联。MediaMan提供了帮助程序以轻松完成工作。多对多多态关系允许任意数量的媒体与任意数量的其他模型相关联,而无需修改现有的数据库模式。
-
频道:它也可以指文件的标签。在关联过程中,媒体项绑定到模型的“频道”。因此,您可以轻松地将多种类型的媒体关联到模型。例如,“用户”模型可能有一个“头像”和“文档”媒体频道。如果您的头脑中混乱,只需将“频道”视为特定模型的“标签”即可。频道也用于执行转换。
-
转换:您可以使用转换来操作图像,转换将在媒体项关联到模型时执行。例如,您可以为模型的“画廊”频道注册“缩略图”转换,以便在图像附加到该频道时运行。
目录
需求
- PHP v7.3 | v7.4 | v8.0 | v8.1 | v8.2
- Laravel v7 | v8 | v9 | v10 | v11
- Composer v1 | v2
安装
您可以通过Composer安装此软件包
composer require farhanshares/laravel-mediaman
除非您已禁用自动发现模式,否则Laravel会自动发现此软件包。在这种情况下,请将服务提供程序添加到您的config/app.php
FarhanShares\MediaMan\MediaManServiceProvider::class
安装完成后,您应发布提供的资产以创建必要的迁移和配置文件。
php artisan mediaman:publish-config php artisan mediaman:publish-migration
确保存储已连接。
php artisan storage:link
运行迁移,您就设置完成了。
php artisan migrate
配置
MediaMan开箱即用。如果您想调整它,MediaMan附带一个config/mediaman.php
配置文件。调整的一个常见需求可能是将媒体存储在专用存储中。
MediaMan支持Laravel支持的所有存储驱动程序(例如:本地、S3、SFTP、FTP、Dropbox等)。
以下是一个示例配置,用于为MediaMan使用专用本地媒体磁盘。
// file: config/filesystems.php // define a new disk 'disks' => [ ... 'media' => 'driver' => 'local', 'root' => storage_path('app/media'), 'url' => env('APP_URL') . '/media', 'visibility' => 'public', ], ] // define the symbolic link 'links' => [ ... public_path('media') => storage_path('app/media'), ], // file: config/mediaman.php // update the disk config to use our recently created media disk 'disk' => 'media'
现在,运行php artisan storage:link
来创建我们新创建的媒体磁盘的符号链接。
媒体
上传媒体
您应使用FarhanShares\MediaMan\MediaUploader
类来处理文件上传。您可以一次性上传文件、在数据库中创建记录并将文件存储在文件系统中。
$file = $request->file('file') $media = MediaUploader::source($file)->upload();
文件将存储在默认磁盘和默认集合中,该集合在mediaman配置中指定。文件大小将存储在数据库中,文件名将自动清理。
但是,您可以做更多的事情,而不仅仅是坚持默认设置。
$file = $request->file('file') $media = MediaUploader::source($file) ->useName('Custom name') ->useFileName('custom-name.png') ->useCollection('Images') ->useDisk('media') ->useData([ 'additional_data' => 'will be stored as json', 'use_associative_array' => 'to store any data you want to be with the file', ]) ->upload();
如果集合不存在,它将自动创建。您可以在下面了解更多关于集合的信息。
问题:如果我在上述过程中不提供唯一的文件名,会发生什么?
答案:不要担心,MediaMan以智能和安全的方 式管理上传。文件以冲突几乎不会发生的方式存储在磁盘上。在存储磁盘时,MediaMan将在磁盘上创建一个格式为mediaId-hash
的目录并将文件放在其中。与文件相关的任何内容都将拥有自己的小屋。
问题:但是为什么?我会得到一堆目录吗?
答案:是的,你会的。如果您想,可以扩展FarhanShares\MediaMan\Models\Media
模型,并按您喜欢的任何方式自定义。最后,将您的自定义模型指向mediaman配置。但我们建议坚持默认设置,这样您就不必担心文件冲突。添加了hash以及mediaId,因此用户无法猜测并检索随机文件。稍后将添加更多有关自定义的信息。
提醒:MediaMan将任何文件(Illuminate\Http\UploadedFile
的实例)视为媒体源。如果您想上传特定类型的文件,可以使用Laravel的验证器。
检索媒体
您可以使用任何Eloquent操作来检索媒体,我们还添加了findByName()。
// by id $media = Media::find(1); // by name $media = Media::findByName('media-name'); // with collections $media = Media::with('collections')->find(1);
Media实例具有以下属性
'id' => int 'name' => string 'file_name' => string 'extension' => string 'type' => string 'mime_type' => string 'size' => int // in bytes 'friendly_size' => string // in human readable format 'media_uri' => string // media URI for the original file. Usage in Blade: {{ asset($media->media_uri) }}. 'media_url' => string // direct URL for the original file. 'disk' => string 'data' => array // casts as array 'created_at' => string 'updated_at' => string 'collections' => object // eloquent collection
您可以使用一些方法以及属性
// $media->mime_type => 'image/jpg' $media->isOfType('image') // true // get the media url, accepts optional '$conversionName' argument $media->getUrl('conversion-name') // get the path to the file on disk, accepts optional '$conversionName' argument $media->getPath('conversion-name') // get the directory where the media stored on disk $media->getDirectory()
更新媒体
使用Media
实例,您可以执行各种更新操作
$media = Media::first(); $media->name = 'New name'; $media->data = ['additional_data' => 'additional data'] $media->save()
更新媒体名称
$media = Media::first(); $media->name = 'New Display Name'; $media->save();
更新附加数据
$media->data = ['additional_data' => 'new additional data']; $media->save();
删除所有附加数据
$media->data = []; $media->save();
更新媒体文件名
更新媒体文件名也将重命名存储中的实际文件。
$media->file_name = 'new_filename.jpg'; $media->save();
更改媒体存储磁盘
将媒体移动到另一个存储磁盘将实际文件转移到指定的磁盘。
$media->disk = 's3'; // Example disk name, ensure it exists $media->save();
注意!有关磁盘读写操作访问性检查的配置: check_disk_accessibility
。
磁盘访问性检查:
- 优点:早期识别潜在磁盘问题。
- 缺点:可能会引入性能延迟。
提示:启用此检查可以预先发现存储问题,但可能会增加轻微的操作延迟。请根据您的系统需求相应决定。
删除媒体
您可以通过对Media实例调用delete()方法来删除媒体。
$media = Media::first(); $media->delete()
或者这样删除媒体
Media::destroy(1); Media::destroy([1, 2, 3]);
注意:当删除Media实例时,文件将从文件系统中删除,与您的App Models和MediaCollection的所有关联也将被删除。
注意!您不应使用查询删除媒体,例如 Media::where('name', 'the-file')->delete()
,这不会触发删除事件,文件也不会从文件系统中删除。有关详细信息,请参阅官方文档。
媒体 & 模型
关联媒体
MediaMan通过FarhanShares\MediaMan\HasMedia
特质提供易于使用的API,用于将媒体项关联到模型。在您的App Model中使用此特质,然后您就可以开始了。
use Illuminate\Database\Eloquent\Model; use FarhanShares\MediaMan\Traits\HasMedia; class Post extends Model { use HasMedia; }
这将建立您的App Model和Media Model之间的关系。
完成设置后,您可以将媒体关联到模型,如下所示。
attachMedia()
方法的第一个参数可以是媒体模型/ID或模型/ID的可迭代集合。
$post = Post::first(); // Associate in the default channel $post->attachMedia($media); // or 1 or [1, 2, 3] or collection of media models // Associate in a custom channel $post->attachMedia($media, 'featured-image');
attachMedia()
在成功时返回关联的媒体数量(整数),在失败时返回null。
检索模型的媒体
除了这些,HasMedia
特质还使您的App Models可以方便地检索媒体。
// All media from the default channel $post->getMedia(); // All media from the specified channel $post->getMedia('featured-image');
尽管原始媒体URL已附加到Media模型,但您应该知道有一个getUrl()方法可用。
$media = $post->getMedia('featured-image'); // getUrl() accepts only one optional argument: name of the conversion // leave it empty to get the original media URL $mediaOneUrl = $media[0]->getUrl();
对于大多数Laravel应用程序,使用第一个媒体项的频率较高,因此MediaMan提供了专门的方法来检索所有关联媒体中的第一个项目。
// First media item from the default channel $post->getFirstMedia(); // First media item from the specified channel $post->getFirstMedia('featured-image'); // URL of the first media item from the default channel $post->getFirstMediaUrl(); // URL of the first media item from the specified channel $post->getFirstMediaUrl('featured-image');
提示:getFirstMediaUrl()接受两个可选参数:频道名称和转换名称
解除媒体关联
您可以使用HasMedia特质中提供的detachMedia()
方法来从模型中解除媒体关联。
// Detach the specified media $post->detachMedia($media); // or 1 or [1, 2, 3] or collection of media models // Detach all media from all channels $post->detachMedia(); // Detach all media of the default channel $post->clearMediaChannel(); // Detach all media of the specific channel $post->clearMediaChannel('channel-name');
detachMedia()
在成功时返回解除关联的媒体数量(整数),在失败时返回null。
同步关联/解除关联
您可以使用syncMedia()方法同步指定频道的媒体。这提供了维护模型和关联媒体记录之间关联的灵活方式。默认的方法签名如下:syncMedia($media, string $channel = 'default', array $conversions = [], $detaching = true)
如果$detaching为真,这将删除提供的列表中不存在的媒体,并添加尚未关联的媒体。
$post = Post::first(); $media = Media::find(1); // model instance or just an media id: 1, or array of id: [1, 2, 3] or a collection of media models // Sync media in the default channel (the $post will have only $media and others will be removed) $post->syncMedia($media);
注意!attachMedia、detachMedia或syncMedia方法都不会删除文件,它只是按照其含义执行。有关如何删除媒体,请参阅“删除媒体”部分。
集合
MediaMan提供集合以更好地管理媒体。使用FarhanShares\MediaMan\Models\MediaCollection
处理媒体集合。
创建集合
当上传文件时,如果不存在,则会自动创建集合。
$media = MediaUploader::source($request->file('file')) ->useCollection('My Collection') ->upload();
如果您希望在不上传文件的情况下创建集合,您也可以这样做,毕竟它是一个Eloquent模型。
MediaCollection::create(['name' => 'My Collection']);
检索集合
您可以通过ID或名称检索集合。
MediaCollection::find(1); MediaCollection::findByName('My Collection'); // Retrieve the bound media as well MediaCollection::with('media')->find(1); MediaCollection::with('media')->findByName('My Collection');
更新集合
您可以更新集合名称。实际上没有其他可以更新的内容。
$collection = MediaCollection::findByName('My Collection'); $collection->name = 'Our Collection' $collection->save();
删除集合
您可以使用MediaCollection实例删除集合。
$collection = MediaCollection::find(1); $collection->delete()
这将不会从磁盘上删除媒体,但会从数据库中删除绑定。
注意!deleteWithMedia()是一个尚未实现的概念性方法,如果需要此功能,请创建一个功能请求。PR非常受欢迎。
媒体 & 集合
Media
与 MediaCollection
之间的关系已经配置好了。您可以轻松地进行绑定、解绑以及同步绑定和解绑。对于 Media::**Collections()
和 MediaCollection::**Media()
的方法签名是相似的。
绑定媒体
$collection = MediaCollection::first(); // You can just pass a media model / id / name or an iterable collection of those // e.g. 1 or [1, 2] or $media or [$mediaOne, $mediaTwo] or 'media-name' or ['media-name', 'another-media-name'] $collection->attachMedia($media);
attachMedia()
在成功时返回已绑定的媒体数量(int),在失败时返回 null。或者,您可以使用 Media::attachCollections()
从媒体模型实例绑定到集合。
注意! 与 HasMedia
特性不同,您不能在媒体集合上拥有频道。
解绑媒体
$collection = MediaCollection::first(); // You can just pass a media model / id / name or an iterable collection of those // e.g. 1 or [1, 2] or $media or [$mediaOne, $mediaTwo] or 'media-name' or ['media-name', 'another-media-name'] $collection->detachMedia($media); // Detach all media by passing null / bool / empty-string / empty-array $collection->detachMedia([]);
detachMedia()
在成功时返回已解绑的媒体数量(int),在失败时返回 null。或者,您可以使用 Media::detachCollections()
从媒体模型实例解绑集合。
同步绑定与解绑
$collection = MediaCollection::first(); // You can just pass media model / id / name $collection->syncMedia($media); // You can even pass iterable list / collection $collection->syncMedia(Media::all()) $collection->syncMedia([1, 2, 3, 4, 5]); $collection->syncMedia([$mediaSix, $mediaSeven]); $collection->syncMedia(['media-name', 'another-media-name']); // Synchronize to having zero media by passing null / bool / empty-string / empty-array $collection->syncMedia([]);
syncMedia()
总是返回一个包含同步状态的数组。或者,您可以使用 Media::syncCollections()
与媒体模型实例的集合同步。
转换
当媒体绑定到频道时,您可以指定一个模型来执行“转换”。
MediaMan 提供了一个流畅的 API 来操作图像。它底层使用了流行的 intervention/image 库。缩放、添加水印、转换为不同的格式或其他支持的任何操作都可以完成。简而言之,您可以利用库中的所有功能。
转换是全局注册的。这意味着它们可以在您的应用程序中重用,例如,一个文章和一个用户都可以有相同大小的缩略图,而无需两次注册相同的转换。
要开始使用,您首先应该在应用程序的一个服务提供者中注册一个转换。
use Intervention\Image\Image; use FarhanShares\MediaMan\Facades\Conversion; class AppServiceProvider extends ServiceProvider { public function boot() { Conversion::register('thumb', function (Image $image) { // you have access to intervention/image library, // perform your desired conversions here return $image->fit(64, 64); }); } }
注册转换后,您应该配置一个媒体频道,以便在媒体绑定到您的模型时执行转换。
class Post extends Model { use HasMedia; public function registerMediaChannels() { $this->addMediaChannel('gallery') ->performConversions('thumb'); } }
从现在起,每当媒体项绑定到“gallery”频道时,都会生成一个转换后的图像。您可以像下面这样获取转换后图像的 URL
// getFirstMediaUrl() accepts two optional arguments: channel name & conversion name // you should provide channel name & conversion name to get the url $post->getFirstMediaUrl('gallery', 'thumb');
提示: 默认频道名称为 default
。
// if you have multiple media associated & need to retrieve URLs you can do it with getUrl(): $media = $post->getMedia(); // getUrl() accepts only one optional argument: name of the conversion // you should provide the conversion name to get the url $mediaOneThumb = $media[0]->getUrl('thumb');
提示: media_uri
和 media_url
总是附加一个 Media
实例,这些反映了原始文件(而不是转换)。
升级到MediaMan v1.x指南
如果您是从 MediaMan 的早期版本升级,请放心,过渡相当直接。以下是您需要了解的内容
变更
-
引入
media_uri
:在本版本中,我们引入了一个新的属性media_uri
。这提供了原始文件的 URI。当您想要生成用于 Blade 的完整 URL 时,您可以使用它如下{{ asset($media->media_uri) }}
-
修改
media_url
:在之前的版本中,media_url
的行为类似于现在的media_uri
。从 v1.0.0 开始,media_url
将直接提供原始文件的绝对 URL。
升级步骤
-
更新包:运行 composer update 命令以获取最新版本。
composer update farhanshares/laravel-mediaman
-
审查您的 Blade 文件:如果您之前使用
media_url
与asset()
辅助函数一起使用,如下所示{{ asset($media->media_url) }}
将其更新为
{{ asset($media->media_uri) }}
如果您在没有
asset()
的情况下使用media_url
,则不需要任何更改。 -
运行任何新的迁移(如果适用):始终检查新的迁移并运行它们以确保您的数据库模式是最新的。
-
测试您的应用程序:如往常一样,在升级后,确保您彻底测试应用程序,特别是使用媒体文件的部分,以确保一切按预期工作。
感谢您使用 MediaMan,并希望您喜欢 v1.0.0 版本的改进!如果您遇到任何问题,请随时在 GitHub 上提交工单。
贡献和许可
如果您遇到任何错误,请考虑在 GitHub 上提交问题。欢迎提出功能请求和 PR。
麻省理工学院许可证(MIT)。请阅读许可文件以获取更多信息。