awcodes/filament-curator

FilamentPHP 的媒体选择插件。

v3.6.9 2024-08-24 16:59 UTC

This package is auto-updated.

Last update: 2024-08-24 17:01:45 UTC


README

Latest Version on Packagist Total Downloads

Filament Admin 的媒体选择/管理插件。

注意 此包与 Spatie Media Library 不兼容。

curator-og

安装

您可以通过 composer 安装此包,然后运行安装命令

composer require awcodes/filament-curator
php artisan curator:install

如果您使用的是独立表单包,则需要在布局文件中包含 Curator 模态框,通常您会将其放置在关闭 body 标签之前。

<x-curator::modals.modal />

为了与 Filament 的主题化方法保持一致,您需要使用自定义主题来使用此插件。

注意 如果您尚未设置自定义主题并且正在使用面板,请首先遵循 Filament 文档 中的说明。以下适用于面板包和独立表单包。

您还需要添加 cropper.js。

npm install -D cropperjs
  1. 将插件样式表和 cropperjs 样式表导入您的主题 css 文件。
@import '<path-to-node-modules>/cropperjs/dist/cropper.css';
@import '<path-to-vendor>/awcodes/filament-curator/resources/css/plugin.css';
  1. 将插件的视图添加到您的 tailwind.config.js 文件。
content: [
    './vendor/awcodes/filament-curator/resources/**/*.blade.php',
]

升级

如果您是从 2.x 升级到 3.x,则需要运行以下操作

php artisan curator:upgrade

这将更新 Curator 的数据库模式并创建一个备份您的媒体表,在升级后可以选择删除。

附加步骤

  1. CurationPreset 需要更新到 新格式
  2. GliderFallback 需要更新到 新格式
  3. 自定义 Glide 服务器生成器需要更新为使用 新格式

使用方法

全局设置

全局设置可以通过插件的配置文件进行管理。您可以使用以下命令发布配置文件

php artisan vendor:publish --tag="curator-config"

与 Filament 面板一起使用

如果您使用 Filament 面板,则需要将插件添加到面板的配置中。这将注册插件的资源到面板。所有方法都是可选的,如果没有提供,将从中读取配置文件。

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            \Awcodes\Curator\CuratorPlugin::make()
                ->label('Media')
                ->pluralLabel('Media')
                ->navigationIcon('heroicon-o-photo')
                ->navigationGroup('Content')
                ->navigationSort(3)
                ->navigationCountBadge()
                ->registerNavigation(false)
                ->defaultListView('grid' || 'list')
                ->resource(\App\Filament\Resources\CustomMediaResource::class)
        ]);
}

Curator 选择字段

将 CuratorPicker 字段包含在您的表单中,以触发模态框,并选择现有图像或上传新图像。可以采用 Filament 的 FileUpload 组件的一些常用方法来帮助对每个 CuratorPicker 的特定实例进行尺寸、验证等。

use Awcodes\Curator\Components\Forms\CuratorPicker;

CuratorPicker::make(string $fieldName)
    ->label(string $customLabel)
    ->buttonLabel(string | Htmlable | Closure $buttonLabel)
    ->color('primary|secondary|success|danger') // defaults to primary
    ->outlined(true|false) // defaults to true
    ->size('sm|md|lg') // defaults to md
    ->constrained(true|false) // defaults to false (forces image to fit inside the preview area)
    ->pathGenerator(DatePathGenerator::class|UserPathGenerator::class) // see path generators below
    ->lazyLoad(bool | Closure $condition) // defaults to true
    ->listDisplay(bool | Closure $condition) // defaults to true
    ->tenantAware(bool | Closure $condition) // defaults to true
    ->defaultPanelSort(string | Closure $direction) // defaults to 'desc'
    // see https://filamentphp.com/docs/2.x/forms/fields#file-upload for more information about the following methods
    ->preserveFilenames()
    ->maxWidth()
    ->minSize()
    ->maxSize()
    ->rules()
    ->acceptedFileTypes()
    ->disk()
    ->visibility()
    ->directory()
    ->imageCropAspectRatio()
    ->imageResizeTargetWidth()
    ->imageResizeTargetHeight()
    ->multiple() // required if using a relationship with multiple media
    ->relationship(string $relationshipName, string 'titleColumnName')
    ->orderColumn('order') // only necessary to rename the order column if using a relationship with multiple media

关系

单个

表单组件

CuratorPicker::make('featured_image_id')
    ->relationship('featured_image', 'id'),

模型

use Awcodes\Curator\Models\Media;

public function featuredImage(): BelongsTo
{
    return $this->belongsTo(Media::class, 'featured_image_id', 'id');
}

多个

表单组件

CuratorPicker::make('product_picture_ids')
    ->multiple()
    ->relationship('product_pictures', 'id')
    ->orderColumn('order'), // only necessary if you need to rename the order column

模型

use Awcodes\Curator\Models\Media;

public function productPictures(): BelongsToMany
{
    return $this
        ->belongsToMany(Media::class, 'media_post', 'post_id', 'media_id')
        ->withPivot('order')
        ->orderBy('order');
}

可变形

注意: 当前实现支持表单中的可变形关系,但在表格列中尚未启用。需要进一步的调整以实现完全兼容。

示例迁移

Schema::create('media_items', function (Blueprint $table) {
    $table->id();
    $table->morphs('mediable');
    $table->foreignId('media_id')->constrained()->onDelete('cascade');
    $table->integer('order');
    $table->string('type');
    $table->timestamps();
});

模型

public function media(): MorphMany
{
    return $this->morphMany(MediaItem::class, 'mediable')->orderBy('order');
}

表单组件

CuratorPicker::make('document_ids')
    ->multiple()
    ->relationship('media', 'id')
    ->orderColumn('order') // Optional: Rename the order column if needed
    ->typeColumn('type') // Optional: Rename the type column if needed
    ->typeValue('document'); // Optional: Specify the type value if using types

路径生成

默认情况下,Curator 将使用配置中设置的目录和磁盘来存储您的媒体。如果您想以不同的方式存储媒体,Curator 提供了路径生成器,可以修改其行为。只需在配置中全局设置或为您的 CuratorPicker 字段实例设置您想要的即可。

use Awcodes\Curator\View\Components\CuratorPicker;
use Awcodes\Curator\PathGenerators\DatePathGenerator;

public function register()
{
    CuratorPicker::make('image')
        ->pathGenerator(DatePathGenerator::class);
}

可用生成器

DefaultPathGenerator 将文件保存在磁盘/目录中。

DatePathGenerator 将文件保存在磁盘/目录/Y/m/d 中。

UserPathGenerator 将文件保存在磁盘/目录/user-auth-identifier 中

您也可以通过在自己的类中实现PathGenerator接口来自由地使用自己的路径生成器。

use Awcodes\Curator\PathGenerators;

class CustomPathGenerator implements PathGenerator
{
    public function getPath(?string $baseDir = null): string
    {
        return ($baseDir ? $baseDir . '/' : '') . 'my/custom/path';
    }
}

Curator列

为了在表格中渲染您的媒体,Curator提供了一个具有与Filament的ImageColumn相同方法的CuratorColumn

CuratorColumn::make('featured_image')
    ->size(40)

对于多张图片,您可以控制显示的图片数量、环大小和重叠。

CuratorColumn::make('product_pictures')
    ->ring(2) // options 0,1,2,4
    ->overlap(4) // options 0,2,3,4
    ->limit(3),

关系

如果您使用关系来存储您的媒体,则会在列上遇到n+1问题。为了防止这种情况,您应该修改您的表查询以预加载关系。

例如,当在您的ListResource中使用管理面板时

protected function getTableQuery(): Builder
{
    return parent::getTableQuery()->with(['featured_image', 'product_pictures']);
}

Curations

Curations是一种创建图像自定义大小和焦点的途径。

Curation预设

如果您经常使用某个curations,您可以创建预设,这些预设将在curations模态中可用,以便更容易地重复使用。创建curations预设后,可以通过其键引用它们以在blade文件中输出。

use Awcodes\Curator\Curations\CurationPreset;

class ThumbnailPreset extends CurationPreset
{
    public function getKey(): string
    {
        return 'thumbnail';
    }

    public function getLabel(): string
    {
        return 'Thumbnail';
    }

    public function getWidth(): int
    {
        return 200;
    }

    public function getHeight(): int
    {
        return 200;
    }

    public function getFormat(): string
    {
        return 'webp';
    }

    public function getQuality(): int
    {
        return 60;
    }
}

然后简单地在配置中注册您的预设。

'curation_presets' => [
    ThumbnailPreset::class,
],

您还可以通过在配置文件中更改curation_formats来更改curations可用的格式。这些应该与Intervention Image的编码类型兼容。

'curation_formats' => [
    'jpg',
    'jpeg',
    'webp',
    'png',
    'avif',
],

如果您想禁用媒体编辑器中的“Curations”标签,可以在配置文件中将tabs.display_curation设置为false。默认值为true

'tabs' => [
    'display_curation' => false,
],

如果您想禁用媒体编辑器中的“上传新”标签,可以在配置文件中将tabs.display_upload_new设置为false。默认值为true

'tabs' => [
    'display_upload_new' => false,
],

Glider Blade组件

为了尽可能简化媒体输出,Curator提供了一个<x-curator-glider> blade组件。

有关Glide选项的更多信息,请参阅Glide的快速参考

特殊属性

  • media: id(整数)或模型(Media)实例 必需
  • loading: 默认为'lazy'
  • glide: 如果不想使用单个属性,可以使用此参数传递Glide查询字符串
  • srcset: 这将输出glide生成的URL的必要srcset。必须是一个包含srcset宽度的数组,并且需要设置'sizes'属性。
  • force: (布尔值)此参数可用于强制glider返回签名URL,这在从云盘中返回URL时很有用。这应该在了解可能具有性能影响的情况下使用。
<div class="w-64 aspect-video">
    <x-curator-glider
        class="object-cover w-auto"
        :media="1"
        glide=""
        fallback=""
        :srcset="['1024w','640w']"
        sizes="(max-width: 1200px) 100vw, 1024px"
        background=""
        blur=""
        border=""
        brightness=""
        contrast=""
        crop=""
        device-pixel-ratio=""
        filter=""
        fit=""
        flip=""
        format=""
        gamma=""
        height=""
        quality=""
        orientation=""
        pixelate=""
        sharpen=""
        width=""
        watermark-path=""
        watermark-width=""
        watermark-height=""
        watermark-x-offset=""
        watermark-y-offset=""
        watermark-padding=""
        watermark-position=""
        watermark-alpha=""
    />
</div>

Glider回退图片

Glide允许使用回退图片,如果媒体项不存在。可以通过传递一个引用您的注册GliderFallback之一的fallback属性来设置它。

use Awcodes\Curator\Glide\GliderFallback;

class MyCustomGliderFallback extends GliderFallback
{
    public function getAlt(): string
    {
        return 'boring fallback image';
    }

    public function getHeight(): int
    {
        return 640;
    }

    public function getKey(): string
    {
        return 'card_fallback';
    }

    public function getSource(): string
    {
        return 'https://via.placeholder.com/640x420.jpg';
    }

    public function getType(): string
    {
        return 'image/jpg';
    }

    public function getWidth(): int
    {
        return 420;
    }
}

然后请在配置中注册您的回退。

'glide' => [
    'fallbacks' => [
        MyCustomGliderFallback::class,
    ],
],

然后您可以在blade组件中引用您的回退。

<x-curator-glider :media="1" fallback="card_fallback"/>

自定义Glide路由

默认情况下,Curator将在通过Glide提供图像时使用curator路由。如果您想更改此设置,可以更新Curator配置文件中的glide.route_path设置。

'glide' => [
    'route_path' => 'uploads',
],

自定义Glide服务器

如果您想使用自己的Glide服务器来处理Glide处理的媒体,您可以在自己的类中实现ServerFactory接口并将其设置为配置。

use League\Glide\Responses\LaravelResponseFactory;
use League\Glide\Server;
use League\Glide\ServerFactory;

class CustomServerFactory implements Contracts\ServerFactory
{
    public function getFactory(): ServerFactory | Server
    {
        return ServerFactory::create([
            'driver' => 'imagick',
            'response' => new LaravelResponseFactory(app('request')),
            'source' => storage_path('app'),
            'source_path_prefix' => 'public',
            'cache' => storage_path('app'),
            'cache_path_prefix' => '.cache',
            'max_image_size' => 2000 * 2000,
        ]);
    }
}

然后请在配置中注册您的服务器。

'glide' => [
    'server' => \App\Glide\CustomServerFactory::class,
],

Curation Blade组件

为了尽可能简化curations的输出,Curator提供了一个<x-curator-curation> blade组件。

特殊属性

  • media: id(整数)或模型(Media)实例 必需
<x-curator-curation :media="10" curation="thumbnail" loading="lazy"/>

实际用例

由于curations可能对每个媒体项都存在,或者不存在,因此最好在blade文件中使用回退到glider组件,以确保始终适当地渲染图像。这也让您不必为每个媒体项创建curations,只需为那些您试图更改焦点等的媒体项创建。

@php
    $preset = new ThumbnailPreset();
@endphp

@if ($media->hasCuration('thumbnail'))
    <x-curator-curation :media="$media" curation="thumbnail"/>
@else
    <x-curator-glider
        class="object-cover w-auto"
        :media="$media"
        :width="$preset->getWidth()"
        :height="$preset->getHeight()"
    />
@endif

自定义模型

如果您想使用自己的模型来处理媒体,可以通过扩展 Curator 的 Media 模型来实现,并将其设置到配置文件中。

use Awcodes\Curator\Models\Media;

class CustomMedia extends Media
{
    protected $table = 'media';
}
'model' => \App\Models\Cms\Media::class,

测试

composer test

变更日志

请参阅 变更日志 了解最近的变化信息。

贡献

请参阅 贡献指南 了解详细信息。

安全漏洞

请查看 我们的安全策略 了解如何报告安全漏洞。

致谢

许可证

MIT 许可证 (MIT)。请参阅 许可证文件 了解更多信息。