LeonelGauna's avatar

Using API Resources without Models?

Hello, how is everyone doing?

I already asked Gemini for info and researched the web, and it seems there is no problem doing this, but I kind of wanted an excuse to use the Laracasts forum 😊.

I have a question about API Resources. I'm playing around with a small API of mine and I wanted to make all its responses consistent by having the same shape, something like the following:

{ success: boolean, message: string, data: [ ... ] }

I learned from the videos here that Laravel comes with these "Resource" classes which seem pretty useful; however, they appear to be highly coupled to Eloquent models. For each model, I basically have to create a new Resource class.

This made me wonder: can I use these Resource classes for data that doesn't necessarily have a model associated with it? For example, what if I want to return an object that is just an aggregate of two or more models?.

0 likes
5 replies
LaryAI's avatar
Level 58

Absolutely, you can use Laravel API Resources for data that isn't tied directly to Eloquent models! Resources are really just transformers — you feed them any array or object, and they output a consistent, formatted response for your API.

How?

You can instantiate a resource with plain PHP arrays, collections, or any object — it doesn't have to be an Eloquent model. The same pattern applies if you're building an aggregate array or merging output from multiple models.

Example: Resource with Non-Model Data

// In app/Http/Resources/CustomResource.php
namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class CustomResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'foo' => $this['foo'],
            'bar' => $this['bar'],
        ];
    }
}

Then in your controller:

use App\Http\Resources\CustomResource;

public function showCustomData()
{
    $aggregatedData = [
        'foo' => 'hello',
        'bar' => 'world',
    ];

    return new CustomResource($aggregatedData);
}

Or for a collection of plain arrays:

use Illuminate\Support\Collection;
use App\Http\Resources\CustomResource;

public function index()
{
    $data = collect([
        ['foo' => 'a', 'bar' => 1],
        ['foo' => 'b', 'bar' => 2],
    ]);

    return CustomResource::collection($data);
}

Wrapping Data in a Custom Top-Level Structure

If you want all responses to have { success, message, data }, you can:

1. Use with() method in the Resource

public function with($request)
{
    return [
        'success' => true,
        'message' => 'OK',
    ];
}

This will wrap every resource response:

{
    "data": { /* your payload */ },
    "success": true,
    "message": "OK"
}

2. Or, Override the toArray entirely

You can override the toArray($request) method to customize the entire response shape:

public function toArray($request)
{
    return [
        'success' => true,
        'message' => 'Fetched successfully',
        'data' => parent::toArray($request), // or use your own custom structure
    ];
}

Summary:
Resources can transform any data — not just Eloquent models! Array, Collection, custom objects, even plain PHP arrays; if you pass it in, Resource will handle it.


References:

1 like
martinbean's avatar

@leonelgauna What is the point of putting success in the response body? That’s what HTTP status codes are for.

Also, what are you going to do for the actual “data” part of your responses? That’s what Eloquent API resources are for: for consistently formatting entities in the output of your API. If you just use resources for formatting generic responses, then you’re either going to have resources-in-resources when you need to present models in those responses; or worse: completely defeat the point of resources and have different endpoints returning different representations of the same model.

So, to answer your question: yes, resources can be used without Eloquent models (I’ve used resources for things like Stripe checkout session objects), but they’re wholly unsuitable for the use case you’ve mentioned.

1 like
LeonelGauna's avatar

Yeah it makes sense, thanks for the feedback.

1 like

Please or to participate in this conversation.