Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Api Response Laravel Package

ellipsesynergie/api-response

A Laravel package for building consistent JSON API responses. It offers success and error helpers, HTTP status and custom error-code handling, Fractal transformer integration, and pagination support, so you can standardize API endpoints with less boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and let Laravel discover the service provider on versions that support package discovery:

composer require ellipsesynergie/api-response

On older Laravel versions, register the provider and optional facade manually:

// config/app.php
'providers' => [
    EllipseSynergie\ApiResponse\LaravelServiceProvider::class,
],

'aliases' => [
    'ApiResponse' => EllipseSynergie\ApiResponse\Facades\Laravel::class,
],

Publish the config if you need to change the error envelope:

php artisan vendor:publish --provider="EllipseSynergie\ApiResponse\LaravelServiceProvider"

Look first at:

  • config/api-response.php — response/error formatting.
  • EllipseSynergie\ApiResponse\Contracts\Response — the contract you should inject.
  • EllipseSynergie\ApiResponse\Laravel\Response — the default Laravel implementation.
  • Your Fractal transformers — most of your response shape lives there.

The first useful endpoint is a single-resource response. Create a Fractal transformer:

use League\Fractal\TransformerAbstract;

class UserTransformer extends TransformerAbstract
{
    public function transform(User $user): array
    {
        return [
            'id' => (int) $user->id,
            'name' => $user->name,
            'email' => $user->email,
        ];
    }
}

Then inject the response contract and return an item:

use EllipseSynergie\ApiResponse\Contracts\Response;

class UserController extends Controller
{
    public function __construct(private Response $response)
    {
    }

    public function show(User $user)
    {
        return $this->response->withItem($user, new UserTransformer);
    }
}

This gives you a consistent data envelope and lets Fractal handle serialization.

Implementation Patterns

Use constructor injection, not the facade

Injection keeps controllers testable and makes it easy to swap in a custom response implementation:

abstract class ApiController extends Controller
{
    public function __construct(protected Response $response)
    {
    }
}

Then extend it for API controllers.

Standard CRUD responses

public function index()
{
    return $this->response->withPaginator(
        User::paginate(25),
        new UserTransformer
    );
}

public function store(StoreUserRequest $request)
{
    $user = User::create($request->validated());

    return $this->response->withItem($user, new UserTransformer, 201);
}

public function show(User $user)
{
    return $this->response->withItem($user, new UserTransformer);
}

public function destroy(User $user)
{
    $user->delete();

    return $this->response->withSuccess('User deleted');
}

Use withPaginator() rather than withCollection() for paginated results so pagination metadata is included.

Return ad-hoc arrays when no transformer is needed

return $this->response->withArray([
    'user' => (new UserTransformer)->transform($user),
    'token' => $token,
]);

Use this for compound payloads such as login responses, health checks, or small configuration endpoints.

Centralize error responses

return $this->response->withError('User not found', 404);

For exceptions, map them in App\Exceptions\Handler::render() so API clients always receive the same envelope:

public function render($request, Throwable $e)
{
    if ($request->expectsJson() && $e instanceof ModelNotFoundException) {
        return app(\EllipseSynergie\ApiResponse\Contracts\Response::class)
            ->withError('Resource not found', 404);
    }

    return parent::render($request, $e);
}

Also handle validation exceptions there if you want validation errors to use the same structure as other API errors.

Customize by binding your own implementation

Create a subclass of the package response if you need a different envelope, extra metadata, or custom error handling:

namespace App\Support;

class ApiResponse extends \EllipseSynergie\ApiResponse\Laravel\Response
{
    // Override response-building methods as needed.
}

Rebind the contract in a service provider:

$this->app->bind(
    \EllipseSynergie\ApiResponse\Contracts\Response::class,
    \App\Support\ApiResponse::class
);

This is the main extension point. Prefer it over editing vendor files.

Integrate with API routes and JSON negotiation

Put these endpoints behind your API route group and ensure clients send Accept: application/json. For browser-facing or mixed routes, add middleware that forces JSON when the request is under your API prefix:

if ($request->is('api/*')) {
    $request->headers->set('Accept', 'application/json');
}

This keeps Laravel validation and exception handling in JSON mode.

Test the envelope, not just the status code

$response->assertStatus(200)
    ->assertJsonStructure([
        'data' => ['id', 'name', 'email'],
    ]);

For errors, assert the configured error keys as well as the HTTP status.

Gotchas and Tips

  • This package is a thin Fractal wrapper. Most response-shape problems are transformer problems. Keep transformers focused and avoid database queries inside them.
  • Eager load relationships used by transformers. It is easy to introduce N+1 queries with withCollection() and withPaginator().
  • Pass transformer instances, not class strings. The package methods expect a TransformerAbstract instance, e.g. new UserTransformer, not UserTransformer::class.
  • Use the right collection method. withCollection() returns a Fractal collection; withPaginator() adds pagination metadata. Passing a paginator to withCollection() loses that metadata.
  • Status codes matter. Do not return 200 for created or deleted resources. Pass a status code where the method supports it, or set it before building the response.
  • Publish config before changing the error format. The error envelope is controlled by config/api-response.php. Customizing keys can break existing clients, so version your API or keep the default envelope stable.
  • Clear config cache after changes. If you use php artisan config:cache, edits to config/api-response.php will not take effect until you run php artisan config:clear and re-cache.
  • Check Laravel compatibility before adopting. This is a small, long-lived package; verify its composer constraints against your Laravel version and pin it in composer.json. Do not assume the latest release date means it is actively maintained.
  • Register the provider manually on older Laravel versions. If package discovery is unsupported, missing provider registration will surface as a container binding error for the Response contract.
  • Avoid mixing response styles. If you inject the response contract in a controller, do not also return raw response()->json() from the same endpoint family. Pick one convention per API surface.
  • Debug the built response, not the transformer alone. Dump getContent() or getData(true) on the returned response to inspect the final envelope, including Fractal’s data wrapper.
  • Validation errors need special attention. Laravel’s default validation response may not match your configured error format. Normalize it in the exception handler if clients depend on a consistent error schema.
  • Beware of output before the response. Whitespace or debug output before the response will corrupt JSON and make the package look broken.
  • Use a custom response class for extension. Overriding package internals via vendor edits is brittle; subclass the Laravel response implementation and rebind the contract instead.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib