Bulent
Bulent

Reputation: 3411

How to Combine Some Relations in Laravel

On my project, Picture model has some "one to many" relations to create featured images. Those relations:

    public function featuredByPosts()
    {
        return $this->hasMany('App\Post', 'featured_image_id');
    }

    public function featuredByProduct()
    {
        return $this->hasMany('App\Products', 'featured_image_id');
    }

    public function featuredByPages()
    {
        return $this->hasMany('App\Page', 'featured_image_id');
    }

One of the inverse relations is like so:

    public function featured_image()
    {
        return $this->belongsTo('App\Picture', 'featured_image_id');
    }

When I get the pictures with those relations, each picture in collection has featured_by_posts, featured_by_products and featured_by_pages keys and related content as values of those keys.

What I want to do is to create a new key named "featured_by" directly in each picture in the collection and move current featured_by_* relations into new key by modifing their keys like so:

From this:

$picture = [
    "id" => "1",
    "name" => "someName",
    "featured_by_posts" => [array of posts],
    "featured_by_pages" => [array of pages]   
]

To this:

$picture= [
    "id" => "1",
    "name" => "someName",
    "featured_by" => [
        "posts" => (values of featured_by_posts),
        "pages" => (values of featured_by_pages)
    ]    
]

I don't know if it can be done while getting data from database. That's why I tried to add the codes down below in index function on my API controller to produce formatted item of picture.

$relations = ["tags", "posts", "products", "featuredByPosts", "featuredByProducts", "featuredByPages"];
$pictures = Picture::with($relations)->get();
foreach ($pictures as $picture) {
    $featureds = ["posts", "products", "pages"];
    $key = "featured_by";
    $picture[$key] = [];
    foreach ($featureds as $featured) {
        $oldKey = "{$key}_{$featured}";
        $picture[$key][$featured] = $picture[$oldKey]; //This line produces the error
        unset($picture[$oldKey]);
    }
}

//ERROR: Indirect modification of overloaded element of App\Picture has no effect.

I don't understand what that means since the think. I searched this error and found some answers, but I couldn't make it work. So I hope someone can help. Thanks.

Upvotes: 1

Views: 57

Answers (1)

zsocakave
zsocakave

Reputation: 66

You should use the eloquent API resources: https://laravel.com/docs/7.x/eloquent-resources

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class PictureResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'featured_by' => [
                'posts' => $this->featuredByPost,
                'products' => $this->featuredByProduct,
            ],
        ];
    }
}

Your controller:

return new PictureResource(Picture::find(1));

Upvotes: 1

Related Questions