Search code examples
laravellaravel-5laravel-5.5laravel-responselaravel-resource

Laravel Resource


I have multiple resources and mostly resource content few fields that are same for all other resource and it's very difficult to modify all the resource in case I need to update/add key/value in the resource.

Is there any way that I can create one main resource that will contain all common fields and then call the main resource in my another resource and add few additional fields.

Here is my controller where I am calling CitizenFeedResource file.

if ($events->total()) {
            return CitizenFeedResource::collection($events);
        }

This is my CitizenFeedResource file.

use Illuminate\Http\Resources\Json\JsonResource;

class CitizenFeedResource extends JsonResource
{

    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'description' => $this->description,
            'start_timestamp' => optional($this->start_timestamp)->toDateTimeString(),
            'end_timestamp' => optional($this->end_timestamp)->toDateTimeString(),
            'location' => [
                'name' => $this->location,
                'landmark' => $this->landmark,
                'coordinates' => $this->coordinates,
                'city' => $this->city,
            ],
            'open_event' => $this->open_event,
            'full_day_event' => $this->full_day_event,
            'banner' => $this->banner,
            'url' => $this->path(),
            'web_url' => $this->webUrl(),
            'categories' => $this->categories,
            'timestamp' => $this->created_at->toDateTimeString(),
            'timestamp_ago' => $this->created_at->diffForHumans(),
            'statistics' => $this->statistics,
            'additional_details' => $this->additionalDetails(),
            'municipal_details' => $this->municipal_details,
            'user' => optional($this->user)->getProfile($this->channel, '1.1'),
            'complaint_id' => $this->complaint_id,
            'volunteers' => (isset($this->volunteers) && $this->volunteers) ? $this->user->getVolunteerProfile($this->volunteers, '1.1') : array(),
            'share_count' => (isset($this->statistics) && isset($this->statistics['share_count'])) ? array_sum($this->statistics['share_count']) : 0,
            'volunteer_status' => $this->getVolunteerStatus($request),
            'editable' => $this->editable(),
            'type' => 'Event',
        ];
    }
}

Solution

  • You don't have to extend directly from JsonResponse, so you can create one main object let's say like this:

    use Illuminate\Http\Resources\Json\JsonResource;
    
    class BaseResource extends JsonResource
    {
    
        /**
         * Transform the resource into an array.
         *
         * @param  \Illuminate\Http\Request $request
         * @return array
         */
        public function toArray($request)
        {
            return [
                'id' => $this->id,
                'title' => $this->title,
                'description' => $this->description,
            ];
        }
    }
    

    and then

    class CitizenFeedResource extends BaseResource
    {
    
        /**
         * Transform the resource into an array.
         *
         * @param  \Illuminate\Http\Request $request
         * @return array
         */
        public function toArray($request)
        {
           $data = parent::toArray($request);
           $data['custom_field'] = $this->custom_field;
           // ...
           return $data;
        }
    }