Salal Aslam
Salal Aslam

Reputation: 1377

Laravel Eloquent get all in single key value pair

I have two tables posts and post_metas with the schema as below:

POSTS
+------------+------------------+
| Field      | Type             |
+------------+------------------+
| id         | int(10) unsigned |
| title      | varchar(255)     |
| content    | longtext         |


POST_METAS
+------------+------------------+
| Field      | Type             |
+------------+------------------+
| id         | int(10) unsigned |
| post_id    | int(10) unsigned |
| key        | varchar(255)     |
| value      | longtext         |

using a simple one to many relationship, i get this output

[
  {
    "id": 1,
    "title": "Dibbert LLC",
    "content": null,
    "post_metas": [
      {
        "key": "code",
        "value": "YSRSLBZ7"
      },
      {
        "key": "agent_id",
        "value": "32"
      }
    ]
  }
]

I am wondering if it is possible to have the post metas as an object not an array, like this instead:

[
  {
    "id": 1,
    "title": "Dibbert LLC",
    "content": null,
    "post_metas": {
        "code": "YSRSLBZ7",
        "agent_id": "32"
      }
  }
]

Upvotes: 7

Views: 13551

Answers (2)

Kenny Horna
Kenny Horna

Reputation: 14271

Laravel by default return an instance of the Collection class. This is also applied when querying relationship elements.

Now, if you want to customize the fields to be returned (hide, transform or add something, for example), you could use API Resources. This will let you easily transform your responses.

Check this other answer to help you with API Resources.


Update

To implement API Resources to your needs we'll need to:

  1. Define the PostResource and PostMetaResource classes.
  2. Customize them
  3. Use them in the controller to return the desired data to the view/API

Defining API Resources classes

php artisan make:resource PostMetaResource
php artisan make:resource PostResource

Customization

App/Http/Resources/PostMetaResource.php

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\Resource;

class PostMetaResource extends Resource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'key' => $this->key,
            'value' => $this->value,
        ];
    }
}

App/Http/Resources/PostResource.php

class PostResource extends Resource
{

    use PostMetaResource;

    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            // the rest of your fields..

            // here is where we load the relationship resource:
            'post_metas' => PostMetaResource::collection($this->whenLoaded('post_metas')),
        ];
    }
}

Applying them

use App\Http\Resources\PostResource;

//

public function index(Request $request)
{
    $posts = Post::with('post_metas')->get();

    return PostResource::collection($posts);
}

Upvotes: 1

Devon Bessemer
Devon Bessemer

Reputation: 35357

You can't change how Eloquent returns relationship collections, nor should you want to, but you can certainly manipulate the collection in your response:

$model->post_metas->pluck('value', 'key');

Read up on all the available collection methods.

Upvotes: 15

Related Questions