niels van hoof
niels van hoof

Reputation: 489

returning full image path from an API using spatie imagelibrary

I got a nuxtJs front-end that sends requests to a laravel API, users can upload an image with their post. This is uploaded via the laravel spatie medialibrary package.

Now when users view their post in detail, the image they uploaded should also be displayed.

NuxtJS makes a fetch request to the API :

      async fetch() {
        this.post = await this.$axios.$get('http://127.0.0.1:8000/api/posts/' + this.$route.params.slug)
      },

Requests enters on the show method

public function show(string $slug): PostCollection
{
    return new PostCollection(Post::with(['comments', 'media'])->where('slug', '=', $slug)->get());
}

This returns a new ResourceCollection

       #[ArrayShape(['data' => Collection::class])] public function toArray($request): array
        {
            return [
                'data' => $this->collection,
            ];
        }

contaning e.g. this kind of data

{
    "data": [
        {
            "id": 1,
            "title": "My first blog post",
            "slug": "my-first-blog-post",
            "content": "Beep boop",
            "deleted_at": null,
            "created_at": "2021-07-05T08:43:00.000000Z",
            "updated_at": "2021-07-05T08:43:00.000000Z",
            "comments": [],
            "media": [
                {
                    "id": 1,
                    "model_type": "App\\Models\\Post",
                    "model_id": 1,
                    "uuid": "3c899a67-d59a-41b7-b5ae-f88e9bfc901b",
                    "collection_name": "images",
                    "name": "index",
                    "file_name": "index.jpg",
                    "mime_type": "image/jpeg",
                    "disk": "public",
                    "conversions_disk": "public",
                    "size": 11803,
                    "manipulations": [],
                    "custom_properties": [],
                    "generated_conversions": [],
                    "responsive_images": [],
                    "order_column": 1,
                    "created_at": "2021-07-05T08:43:00.000000Z",
                    "updated_at": "2021-07-05T08:43:00.000000Z"
                }
            ]
        }
    ]
}

Now how would I go about making it so that in the JSON response the full path of the image is returned e.g.http://127.0.0.1:8000/public/storage/1/filename.jpg, so I could show it on my front-end.

The Post model looks like this:

   

      <?php
            
            namespace App\Models;
    
        use Cviebrock\EloquentSluggable\Sluggable;
        use Illuminate\Database\Eloquent\Factories\HasFactory;
        use Illuminate\Database\Eloquent\Model;
        use Illuminate\Database\Eloquent\Relations\HasMany;
        use Illuminate\Database\Eloquent\SoftDeletes;
        use JetBrains\PhpStorm\ArrayShape;
        use Spatie\MediaLibrary\HasMedia;
        use Spatie\MediaLibrary\InteractsWithMedia;
    
            
         
            class Post extends Model implements HasMedia
            {
                use HasFactory;
                use SoftDeletes;
                use Sluggable;
                use InteractsWithMedia;
            
                protected $fillable = [
                    'title',
                    'slug',
                    'content',
                    'image'
                ];
            
                public function comments(): HasMany
                {
                    return $this->hasMany(Comment::class);
                }
            
                #[ArrayShape(['slug' => "string[]"])] public function sluggable(): array
                {
                    return [
                        'slug' => [
                            'source' => 'title'
                        ]
                    ];
                }
            
            }

Upvotes: 0

Views: 1800

Answers (2)

Vikas Rathore
Vikas Rathore

Reputation: 1

Customize Model

protected $appends = ["profile_url"];

public function getProfileUrlAttribute(){ return $this->getFirstMediaUrl('images'); }

Upvotes: 0

Eric Landheer
Eric Landheer

Reputation: 2243

The package returns a Collection of Media objects for the the media() relation. On each of the objects, the function ->getFullUrl() can be called.

In order to return the media with the full URL, you will have to create a custom Attribute.

You could add something lke this to your model, or to a trait if you need to reuse this (not tested):

public function getFullUrlMediaAttribute()
{
    return $this->getMedia()->map( function($mediaObject) {
        $mediaObject->full_url = $mediaObject->getFullUrl();
        return $mediaObject;
    });
}

Checkout the Laravel Medialibrary docs for more information.

After doing so, you would have to update your show function to:

public function show(string $slug): PostCollection
{
    return new PostCollection(Post::with(['comments'])
       ->where('slug', '=', $slug)
       ->get()
       ->append('full_url_media')
    );
}

Upvotes: 2

Related Questions