Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge Laravel Resources into one

Tags:

php

laravel

I have two model resources and I want to be merged into a flat array without having to explicitly define all the attributes of the other resource.

Model 1:

id
name
created_at

Model 2:

id
alternate_name
child_name
parent_name
sibling_name
created_at

Model1Resource

public function toArray($request)
{
    return [
        id => $this->id,
        name => $this->name,
    ]
}

Model 2 Resource

public function toArray($request)
{
    return [
        alternate_name => $this->alternate_name, 
        child_name => $this->child_name, 
        parent_name => $this->parent_name, 
        sibling_name => $this->sibling_name
    ]
}

I want Model1Resource to contain Model2Resource in a flat structure. I can easily get the Model 2 resource in a sub array by adding in another attribute to the resource like so:

Model2 => new Model2Resource($this->model2);

But this is not the flat structure. Ideally I would want to be returned a structure like this.

[id, name, alternate_name, child_name, parent_name, sibling_name]

I could do this by redefining all the attributes of Model2Resource in the Model1Resource but this seems unnecessary.

To clarify I am referring to https://laravel.com/docs/5.5/eloquent-resources#writing-resources. Under the relationships section a one to many relationship is demonstrated using posts. However if the structure is one to one I would expect to be able to make this a flat array instead of having an array in one of the properties.

What's an easy way to merge these two resources into one with a flat structure?

like image 263
Tom Headifen Avatar asked Feb 07 '18 17:02

Tom Headifen


1 Answers

So after some digging this doesn't seem to be easily possible. I've decided the easiest way is to just redefine the outputs in the first model and use the mergeWhen() function to only merge when the relationship exists.

return [
    id => $this->id,
    name => $this->name,
    // Since a resource file is an extension
    // we can use all the relationships we have defined.
    $this->mergeWhen($this->Model2()->exists(), function() {
        return [
            // This code is only executed when the relationship exists.
            alternate_name => $this->Model2->alternate_name, 
            child_name => $this->Model2->child_name, 
            parent_name => $this->Model2->parent_name, 
            sibling_name => $this->Model2->sibling_name
        ];
    }
]
like image 51
Tom Headifen Avatar answered Sep 21 '22 12:09

Tom Headifen