Home > Enterprise >  Laravel: Move model attributes position
Laravel: Move model attributes position

Time:01-09

I was used relationships in my model and it's working fine but the sort of output array is wrong.I want to move created_at and updated_at in the end of the array

The output is:

{
    "id": 1,
    "title": "Test home",
    "created_at": "2022-01-01T15:27:31.000000Z", <---------
    "updated_at": "2022-01-01T15:27:31.000000Z", <---------
    "doors": [
        {
            "id": 1,
            "home_id": 1,
            "button_count": 2,
            "created_at": null,
            "updated_at": null
        }
    ]
}

But it's should be:

{
    "id": 1,
    "title": "Test home",
    "doors": [
        {
            "id": 1,
            "home_id": 1,
            "button_count": 2,
            "created_at": null,
            "updated_at": null
        }
    ],
    "created_at": "2022-01-01T15:27:31.000000Z", <---------
    "updated_at": "2022-01-01T15:27:31.000000Z"  <---------
}

And it's my model class:

class Home extends Model
{
    use HasFactory;

    protected $table = "homes";
    protected $hidden = ["device_id"];
    protected $with = ["doors"];

    public function device(){
        return $this->hasOne(Device::class,"id","device_id");
    }
}

CodePudding user response:

The cleanest approach if you are building an API (not sure if your scenario) is by using Resources where you can format the response as you wish. This is also helpful for being sure that Models will be returned with the same structure in all endpoints.

Assuming you want to fetch all homes with their devices, you can create a DeviceResource for returning specific device properties

PHP artisan make:resource DeviceResource
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class DeviceResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'home_id' => $this->home_id,
            'button_count' => $this->button_count,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
    }
}

Then create a HomeResource which will includes DeviceResource

PHP artisan make:resource HomeResource
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class HomeResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'devices' => DeviceResource::collection($this->whenLoaded('devices')),
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
    }
}

Then you just return the HomeResource collection in your controller

$homes = Home::with('devices')->get();
$response = HomeResource::collection($homes);

return $response;

Or in case you want to return only 1 Home...

$home = Home::with('devices')->findOrFail($home_id);
$response = new HomeResource($home);

return $response;

Be aware that if you don't load devices relationships, the HomeResource won't return the devices property.

CodePudding user response:

You can use resouces to map data and organize response like you want

  •  Tags:  
  • Related