Mauro
Mauro

Reputation: 4234

Present related objects as strings on JSON responses on a Laravel REST API?

I'm writing a REST API on Laravel and I'm taking advantage of polymorphic relationships. So many resources have tied images. When I create the response, using eager loading like this:

return User::with('image')->find($id);

I get something like this:

{
    id: 27,
    image: {
        id: 340,
        url: "https://amazonbucket.com/2lBqWzDme.jpg",
        created_at: "2015-01-28 17:21:17",
        updated_at: "2015-01-28 18:28:42",
    }
}

Instead, I want it to be automatically output just the url as a string like this, so it's easier on the frontend:

{
    id: 27,
    image: "https://amazonbucket.com/2lBqWzDme.jpg"
}

I tried to work with the Image::toJson() method but it didn't work. I Could use the User::toJson() method, but I'd had to do it on all the existing/upcoming instances that use images. Ideas?

Upvotes: 1

Views: 126

Answers (2)

Mauro
Mauro

Reputation: 4234

As it happens usually, I found a better, less invasive way of doing this looking for something else:

Just add the $appends protected attribute to your model and set the getImageAttribute() method.

protected $appends = ['image'];  

function getImageAttribute() {
    return $this->images()->first()->url;
}

Check the bottom of http://laravel.com/docs/4.2/eloquent#converting-to-arrays-or-json.

It works like charm!

Upvotes: 2

patricus
patricus

Reputation: 62398

Overriding the Image::toJson() method won't help here. In this case, the truncated call stack would be User::toJson() --> User::toArray() --> Image::toArray().

So, now the problem becomes that in order to do what you want to do, you would have to override the Image::toArray() method so that it no longer returns an array, but instead returns a string containing the url value. I can't imagine this would go over too well, but I've never done it before.

If you're looking to only modify the Image class, the closest you could get would be to assign the Image::visible attribute to only include the url key. This would turn your JSON into:

{
    id: 27,
    image: {
        url: "https://amazonbucket.com/2lBqWzDme.jpg",
    }
}

Outside of that, you're looking at a solution where you'll need to modify each class that will be imageable. However, you could extract the required functionality out into a Trait or a base class that your other classes extend. In either case, you're looking to modify the toArray() method, not the toJson() method.

Upvotes: 1

Related Questions