corollarium/modelarium-medialibrary

整合 Spatie Laravel-media-library 至 Modelarium 和 GraphQL

v0.5.0 2021-01-26 20:14 UTC

This package is auto-updated.

Last update: 2024-09-05 20:24:05 UTC


README

Latest Stable Version Total Downloads License

此包将 Spatie 的 Laravel Media Library 集成到 Modelarium,允许使用 LighthousePHP 进行 GraphQL 查询,以轻松访问模型上的媒体。

安装

在您的 Laravel 应用中运行

composer require corollarium/modelarium-medialibrary

快速概述

这是一个针对具有两个不同媒体集合("image" 和 "map")的模型的 Graphql 文件。两者都有额外的字段 "url" 和 "description"。 "Map" 还有一个转换 "thumb",其大小为 150x150(最大,保持宽高比)缩略图。

type Post
  @migrationSoftDeletes
  @migrationTimestamps {
  id: ID!

  name: String!
    @modelFillable
    @renderable(
        label: "Name"
        size: "large"
        itemtype: "name"
        card: true
        title: true
    )

  description: Text!
      @modelFillable
      @renderable(label: "Description", itemtype: "description")

  imageUrl: Url @migrationSkip

  image: LaravelMediaLibraryData
      @migrationSkip
      @laravelMediaLibraryData(
            collection: "image"
            fields: ["url", "description"]
      )

  map: LaravelMediaLibraryData
      @migrationSkip
      @laravelMediaLibraryData(
            collection: "map"
            fields: ["url", "description"]
            conversions: [
                { name: "thumb", width: 150, height: 150 }
            ]
      )
}

这将在您的模型类上自动生成以下代码

/** 
 * This file was automatically generated by Modelarium on 2020-12-13T18:28:11+00:00
 */
namespace App\Models;

abstract class BasePost extends \Illuminate\Database\Eloquent\Model implements \Spatie\MediaLibrary\HasMedia
{
    use \Spatie\MediaLibrary\InteractsWithMedia;

    // ...lots of base stuff...

    /**
     * Configures Laravel media-library
     */
    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('image');

        $this->addMediaCollection('map');
    }

    /**
     * Returns a collection media from Laravel-MediaLibrary
     */
    public function getMediaImageCollection(): \Spatie\MediaLibrary\MediaCollections\Models\Collections\MediaCollection
    {
        return $this->getMedia('image');
    }

    /**
     * Returns custom fields for the media
     */
    public function getMediaImageCustomFields(): array
    {
        return ['url', 'description'];
    }

    /**
     * Returns the media attribute (url) for the image
     */
    public function getImageUrlAttribute(): string
    {
        $image = $this->getMediaImageCollection()->first();
        if ($image) {
            return $image->getUrl();
        }
        return '';
    }

    /**
     * Returns media attribute for the image media with custom fields
     */
    public function getImageAttribute(): array
    {
        $image = $this->getMediaImageCollection()->first();
        if ($image) {
        $customFields = [];
        foreach ($this->getMediaImageCustomFields() as $c) {
            $customFields[$c] = $image->getCustomProperty($c);
        }
        return [
            'url' => $image->getUrl(),
            'fields' => json_encode($customFields)
        ];
        }
        return [];
    }

    /**
     * Configures Laravel media-library conversions
     */
    public function registerMediaConversions(?\Spatie\MediaLibrary\MediaCollections\Models\Media $media = null): void
    {
        $this->addMediaConversions('thumb')->width('150')->height('150');
    }

    /**
     * Returns a collection media from Laravel-MediaLibrary
     */
    public function getMediaMapCollection(): \Spatie\MediaLibrary\MediaCollections\Models\Collections\MediaCollection
    {
        return $this->getMedia('map');
    }

    /**
     * Returns custom fields for the media
     */
    public function getMediaMapCustomFields(): array
    {
        return ['url', 'description'];
    }

    /**
     * Returns the media attribute (url) for the map
     */
    public function getMapUrlAttribute(): string
    {
        $image = $this->getMediaMapCollection()->first();
        if ($image) {
            return $image->getUrl();
        }
        return '';
    }

    /**
     * Returns media attribute for the map media with custom fields
     */
    public function getMapAttribute(): array
    {
        $image = $this->getMediaMapCollection()->first();
        if ($image) {
        $customFields = [];
        foreach ($this->getMediaMapCustomFields() as $c) {
            $customFields[$c] = $image->getCustomProperty($c);
        }
        return [
            'url' => $image->getUrl(),
            'fields' => json_encode($customFields)
        ];
        }
        return [];
    }

    // ...more stuff here...
}

文档

@laravelMediaLibraryData 指令支持以下参数

待办事项

常见问题解答

我需要在我的集合上进行一些自定义转换。

如果指令的基本参数不够,只需在您的模型类中覆盖方法即可

class Post extends BasePost 
{
    public function registerMediaConversions(?\Spatie\MediaLibrary\MediaCollections\Models\Media $media = null): void
    {
        // do your stuff here
    }
}

我如何在类型中仅获取单个图像的图像 URL?

在您的类型中定义一个 xxxUrl,其中 xxx 是您的集合名称。它将由模型上的属性方法自动填充。别忘了添加 @migrationSkip 以防止它在迁移中创建。示例

type Post { 
    # ...

    # this field is filled automatically by the model
    imageUrl: Url @migrationSkip

    image: LaravelMediaLibraryData
        @migrationSkip
        @laravelMediaLibraryData(
            collection: "image"
            singleFile: true
            fields: ["url", "description"]
        )
}

您的查询将看起来像这样

query($id: ID!) {
    post(id: $id) {
        id

        # ... other fields

        imageUrl # this will return the image url
    }
}

我如何在查询中获取完整图像数据?

只需在您的类型中定义 LaravelMediaLibraryData 字段。示例

type Post { 
    image: [LaravelMediaLibraryData!]
        @migrationSkip
        @laravelMediaLibraryData(
            collection: "image"
            fields: ["url", "description"]
        )
}

在您的查询中获取字段

query($id: ID!) {
    post(id: $id) {
        id

        # ... other fields

        image {
            url # the url, a String
            fields # a JSON-encoded string with your custom fields if they exist
        }
    }
}

您也可以轻松地获取第一个

type Post { 
    image: [LaravelMediaLibraryData!]
        @migrationSkip
        @laravelMediaLibraryData(
            collection: "image"
            fields: ["url", "description"]
        )
    
    # add this to get the first one:
    imageFirst: LaravelMediaLibraryData @migrationSkip
}

在您的查询中

query($id: ID!) {
    post(id: $id) {
        id

        # ... other fields

        imageFirst {
            url # the url, a String
            fields # a JSON-encoded string with your custom fields if they exist
        }
    }
}

我想要一个集合中的单个图像,永远不会超过一个。我该如何做?

声明一个 singleFile 集合。注意,这里的返回类型是一个单独的 LaravelMediaLibraryData,而不是数组

type Post { 
    image: LaravelMediaLibraryData
        @migrationSkip
        @laravelMediaLibraryData(
            collection: "image"
            singleFile: true
            fields: ["url", "description"]
        )

    # the [collection]First attribute is also available, so you can mix it with non-singleFile collections:
    imageFirst: LaravelMediaLibraryData @migrationSkip

}

然后正常访问它

query($id: ID!) {
    post(id: $id) {
        id

        # ... other fields

        image {
            url # the url, a String
            fields # a JSON-encoded string with your custom fields if they exist
        }
    }
}

我如何添加缩略图?

添加一个 conversions 字段。将为每个集合创建两个访问器方法:[CollectionName][ConversionName]HTML(生成完整的 HTML 标签)和 [CollectionName][ConversionName]Url(仅 URL)。将它们添加到您的 GraphQL 类型中(并记得 @migrationSkip 它们)以访问它们。示例

type Post { 
    image: LaravelMediaLibraryData
        @migrationSkip
        @eagerLoad(name: "media")
        @laravelMediaLibraryData(
            collection: "image"
            conversions: [{ name: "thumb", width: 128, height: 128 }]
        )

    imageThumbHTML: String @migrationSkip @renderable(show: true)

    imageThumbUrl: Url @migrationSkip @renderable(show: true)

}

易于获取

query($id: ID!) {
    post(id: $id) {
        id

        # ... other fields

        imageThumbUrl
    }
}

我如何在查询中获取响应式图像数据?

添加一个具有 responsive: trueconversions 字段。

type Post { 
    image: LaravelMediaLibraryData
        @migrationSkip
        @eagerLoad(name: "media")
        @laravelMediaLibraryData(
            collection: "image"
            conversions: [{ name: "thumb",  responsive: true}]
        )
}

待办事项:解释如何获取数据

我如何预加载?

添加一个 @eagerLoad 指令以预加载表并避免 N+1 问题。

type Post { 
    image: LaravelMediaLibraryData
        @migrationSkip
        @eagerLoad(name: "media")
        @laravelMediaLibraryData(
            collection: "image"
            fields: ["url", "description"]
        )
}

赞助商

Corollarium

我们想感谢 Spatie 及其出色的 Spatie 的 Laravel Media Library

贡献 contributions welcome

欢迎任何贡献。请发送 PR。