PHPackages                             philiprehberger/laravel-response-macros - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. philiprehberger/laravel-response-macros

ActiveLibrary[API Development](/categories/api)

philiprehberger/laravel-response-macros
=======================================

Response macros for consistent, standardized API responses in Laravel

v1.2.0(4mo ago)172MITPHPPHP ^8.2CI passing

Since Mar 9Pushed 1mo agoCompare

[ Source](https://github.com/philiprehberger/laravel-response-macros)[ Packagist](https://packagist.org/packages/philiprehberger/laravel-response-macros)[ Docs](https://github.com/philiprehberger/laravel-response-macros)[ GitHub Sponsors](https://github.com/philiprehberger)[ RSS](/packages/philiprehberger-laravel-response-macros/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (19)Versions (10)Used By (0)

Laravel Response Macros
=======================

[](#laravel-response-macros)

[![Tests](https://github.com/philiprehberger/laravel-response-macros/actions/workflows/tests.yml/badge.svg)](https://github.com/philiprehberger/laravel-response-macros/actions/workflows/tests.yml)[![Latest Version on Packagist](https://camo.githubusercontent.com/b5bba153fa16b5c94e5efe9ad4cefc020252dbab03b7a84343e438856a1b8d84/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7068696c69707265686265726765722f6c61726176656c2d726573706f6e73652d6d6163726f732e737667)](https://packagist.org/packages/philiprehberger/laravel-response-macros)[![Last updated](https://camo.githubusercontent.com/1db07bf73fa22af37aea553444bce888e4d4d8cc5674a2363e65c84d44705a8e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f7068696c69707265686265726765722f6c61726176656c2d726573706f6e73652d6d6163726f73)](https://github.com/philiprehberger/laravel-response-macros/commits/main)

Response macros for consistent, standardized API responses in Laravel.

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11 or 12

Installation
------------

[](#installation)

```
composer require philiprehberger/laravel-response-macros
```

The service provider is auto-discovered by Laravel. No manual registration is needed.

### Publish the config (optional)

[](#publish-the-config-optional)

```
php artisan vendor:publish --tag=response-macros-config
```

This copies `config/response-macros.php` to your application's config directory.

Usage
-----

[](#usage)

### Configuration

[](#configuration)

```
// config/response-macros.php

return [
    // Key used to wrap data in the envelope() macro
    'envelope_key' => 'data',

    // Key used to nest metadata in the envelope() macro
    'meta_key' => 'meta',

    // When true, each response body includes a "status" key mirroring the HTTP status code
    'include_status_code' => true,
];
```

### `response()->success()`

[](#response-success)

Returns a `200 OK` response (or any 2xx) indicating a successful operation.

**Signature**

```
response()->success(mixed $data = null, string $message = 'Success', int $status = 200): JsonResponse
```

> **Note:** The `$status` parameter must be a 2xx status code (200–299). Passing a non-2xx status throws `InvalidArgumentException`.

**Example**

```
return response()->success($user, 'User retrieved successfully');
```

**Response**

```
{
    "success": true,
    "message": "User retrieved successfully",
    "data": { "id": 1, "name": "Jane Doe" },
    "status": 200
}
```

### `response()->error()`

[](#response-error)

Returns a `400 Bad Request` response (or any 4xx/5xx) indicating a failed operation.

**Signature**

```
response()->error(string $message = 'Error', int $status = 400, mixed $errors = null): JsonResponse
```

> **Note:** The `$status` parameter must be a 4xx or 5xx status code (400–599). Passing a non-error status throws `InvalidArgumentException`.

**Example**

```
return response()->error('Resource not found', 404);
```

**Response**

```
{
    "success": false,
    "message": "Resource not found",
    "errors": null,
    "status": 404
}
```

With additional error detail:

```
return response()->error('Payment failed', 402, ['code' => 'card_declined']);
```

```
{
    "success": false,
    "message": "Payment failed",
    "errors": { "code": "card_declined" },
    "status": 402
}
```

### `response()->paginated()`

[](#response-paginated)

Wraps a `LengthAwarePaginator` with standardized pagination metadata.

**Signature**

```
response()->paginated(LengthAwarePaginator $paginator, string $message = 'Success'): JsonResponse
```

**Example**

```
$users = User::paginate(15);

return response()->paginated($users, 'Users retrieved');
```

**Response**

```
{
    "success": true,
    "message": "Users retrieved",
    "data": [ ... ],
    "meta": {
        "current_page": 1,
        "last_page": 4,
        "per_page": 15,
        "total": 60
    },
    "status": 200
}
```

### `response()->validationError()`

[](#response-validationerror)

Returns a `422 Unprocessable Entity` response from a `Validator` instance or a `MessageBag`.

**Signature**

```
response()->validationError(Validator|MessageBag $validator, string $message = 'The given data was invalid.'): JsonResponse
```

**Example with a Validator**

```
$validator = Validator::make($request->all(), [
    'email' => 'required|email',
    'name'  => 'required|string|max:255',
]);

if ($validator->fails()) {
    return response()->validationError($validator);
}
```

**Example with a MessageBag**

```
$messages = new \Illuminate\Support\MessageBag([
    'email' => ['This email address is already taken.'],
]);

return response()->validationError($messages);
```

**Response**

```
{
    "success": false,
    "message": "The given data was invalid.",
    "errors": {
        "email": ["The email field is required."],
        "name":  ["The name field is required."]
    },
    "status": 422
}
```

You can customize the error message:

```
return response()->validationError($validator, 'Please fix the highlighted fields.');
```

### `response()->noContent()`

[](#response-nocontent)

> **Removed in v1.1.0.** The `noContent()` macro was dead code — Laravel's `ResponseFactory` defines `noContent()` natively, and native methods take precedence over macros. Use Laravel's built-in `response()->noContent()` instead, which returns an HTTP `204` with an empty body.

### `response()->accepted()`

[](#response-accepted)

Returns a `202 Accepted` response indicating the request has been queued or is being processed asynchronously.

**Signature**

```
response()->accepted(mixed $data = null, string $message = 'Accepted'): JsonResponse
```

**Example**

```
ProcessReportJob::dispatch($report);

return response()->accepted(['job_id' => $job->id], 'Report generation queued');
```

**Response**

```
{
    "success": true,
    "message": "Report generation queued",
    "data": { "job_id": "abc-123" },
    "status": 202
}
```

### Cursor Pagination

[](#cursor-pagination)

Wraps a `CursorPaginator` with cursor-based pagination metadata. Ideal for infinite-scroll UIs and large datasets where offset pagination is impractical.

**Signature**

```
response()->cursorPaginated(CursorPaginator $paginator, string $wrap = 'data', int $status = 200): JsonResponse
```

**Example**

```
$users = User::cursorPaginate(15);

return response()->cursorPaginated($users);
```

**Response**

```
{
    "data": [ ... ],
    "meta": {
        "next_cursor": "eyJpZCI6MTUsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0",
        "prev_cursor": null,
        "has_more": true,
        "per_page": 15
    }
}
```

You can customize the wrap key:

```
return response()->cursorPaginated($users, 'results');
```

### Rate Limit Headers

[](#rate-limit-headers)

Adds standard rate-limiting headers to a response. Chain it after building a JSON response or call it directly from the response factory.

**Signature**

```
response()->withRateLimit(int $limit, int $remaining, ?int $retryAfter = null): JsonResponse
```

**Example**

```
return response()->withRateLimit(100, 97);
```

**Headers**

```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 97

```

When the client should back off:

```
return response()->withRateLimit(100, 0, 60);
```

```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
Retry-After: 60
X-RateLimit-Reset: 1711929600

```

### Cached Responses

[](#cached-responses)

Returns a JSON response with `Cache-Control` headers and optional `ETag` support including automatic `304 Not Modified` handling.

**Signature**

```
response()->cached(mixed $data, int $ttl = 3600, ?string $etag = null): JsonResponse
```

**Example without ETag**

```
return response()->cached($config, 1800);
```

**Headers**

```
Cache-Control: public, max-age=1800

```

**Example with ETag**

```
$etag = md5(json_encode($data));

return response()->cached($data, 3600, $etag);
```

When the client sends `If-None-Match` matching the ETag, a `304 Not Modified` response is returned automatically with no body.

### `response()->envelope()`

[](#response-envelope)

Wraps arbitrary data under a configurable key with optional metadata. Useful when you need full control over the response shape without the opinionated `success`/`message` fields.

**Signature**

```
response()->envelope(mixed $data, array $meta = []): JsonResponse
```

**Example without metadata**

```
return response()->envelope($product);
```

**Response**

```
{
    "data": { "id": 42, "name": "Widget Pro" },
    "status": 200
}
```

**Example with metadata**

```
return response()->envelope($results, [
    'version' => '2.1',
    'locale'  => 'en-US',
    'cached'  => true,
]);
```

**Response**

```
{
    "data": [ ... ],
    "meta": {
        "version": "2.1",
        "locale": "en-US",
        "cached": true
    },
    "status": 200
}
```

### Omitting the Status Code from the Body

[](#omitting-the-status-code-from-the-body)

Set `include_status_code` to `false` in `config/response-macros.php` to remove the `"status"` key from all response bodies:

```
'include_status_code' => false,
```

Before:

```
{ "success": true, "message": "OK", "data": null, "status": 200 }
```

After:

```
{ "success": true, "message": "OK", "data": null }
```

The HTTP status code on the response itself is never affected by this option.

API
---

[](#api)

MacroSignatureDescription`response()->success()``success(mixed $data, string $message, int $status): JsonResponse`2xx success response`response()->error()``error(string $message, int $status, mixed $errors): JsonResponse`4xx/5xx error response`response()->paginated()``paginated(LengthAwarePaginator $paginator, string $message): JsonResponse`Paginated response with metadata`response()->validationError()``validationError(Validator|MessageBag $validator, string $message): JsonResponse`422 validation error`response()->accepted()``accepted(mixed $data, string $message): JsonResponse`202 async accepted response`response()->envelope()``envelope(mixed $data, array $meta): JsonResponse`Data under configurable key`response()->cursorPaginated()``cursorPaginated(CursorPaginator $paginator, string $wrap, int $status): JsonResponse`Cursor-paginated response with metadata`response()->withRateLimit()``withRateLimit(int $limit, int $remaining, ?int $retryAfter): JsonResponse`Adds X-RateLimit-\* headers`response()->cached()``cached(mixed $data, int $ttl, ?string $etag): JsonResponse`Cached response with ETag and 304 supportDevelopment
-----------

[](#development)

```
composer install
vendor/bin/phpunit
vendor/bin/pint --test
vendor/bin/phpstan analyse
```

Support
-------

[](#support)

If you find this project useful:

⭐ [Star the repo](https://github.com/philiprehberger/laravel-response-macros)

🐛 [Report issues](https://github.com/philiprehberger/laravel-response-macros/issues?q=is%3Aissue+is%3Aopen+label%3Abug)

💡 [Suggest features](https://github.com/philiprehberger/laravel-response-macros/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)

❤️ [Sponsor development](https://github.com/sponsors/philiprehberger)

🌐 [All Open Source Projects](https://philiprehberger.com/open-source-packages)

💻 [GitHub Profile](https://github.com/philiprehberger)

🔗 [LinkedIn Profile](https://www.linkedin.com/in/philiprehberger)

License
-------

[](#license)

[MIT](LICENSE)

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance84

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 91.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

9

Last Release

132d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/cfd7d24cbbf32400fa13ce0bbe7a31edd2d66a6d4488eafdb3d64c5337bf0435?d=identicon)[philiprehberger](/maintainers/philiprehberger)

---

Top Contributors

[![philiprehberger](https://avatars.githubusercontent.com/u/8218077?v=4)](https://github.com/philiprehberger "philiprehberger (22 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (2 commits)")

---

Tags

responsejsonapilaravelmacros

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/philiprehberger-laravel-response-macros/health.svg)

```
[![Health](https://phpackages.com/badges/philiprehberger-laravel-response-macros/health.svg)](https://phpackages.com/packages/philiprehberger-laravel-response-macros)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M354](/packages/psalm-plugin-laravel)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

818355.4k3](/packages/defstudio-telegraph)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

79227.1M211](/packages/laravel-mcp)[api-platform/laravel

API Platform support for Laravel

58190.1k21](/packages/api-platform-laravel)[nuwave/lighthouse

A framework for serving GraphQL from Laravel

3.5k12.2M126](/packages/nuwave-lighthouse)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5226.7k](/packages/simplestats-io-laravel-client)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
