{"id":13396235,"url":"https://github.com/flugg/laravel-responder","last_synced_at":"2026-01-11T16:51:55.356Z","repository":{"id":43836582,"uuid":"61958636","full_name":"flugg/laravel-responder","owner":"flugg","description":"A Laravel Fractal package for building API responses, giving you the power of Fractal with Laravel's elegancy.","archived":false,"fork":false,"pushed_at":"2024-05-07T21:23:58.000Z","size":1966,"stargazers_count":864,"open_issues_count":38,"forks_count":86,"subscribers_count":14,"default_branch":"master","last_synced_at":"2024-10-30T00:36:01.234Z","etag":null,"topics":["api","fractal","laravel","lumen","responder","transformer"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/flugg.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-06-25T19:36:04.000Z","updated_at":"2024-10-28T16:04:21.000Z","dependencies_parsed_at":"2023-02-17T16:00:33.222Z","dependency_job_id":"c1c4fab2-8145-4f70-a594-ca9399ff017c","html_url":"https://github.com/flugg/laravel-responder","commit_stats":{"total_commits":372,"total_committers":33,"mean_commits":"11.272727272727273","dds":0.239247311827957,"last_synced_commit":"889d79991085e531b6170f29330c2cc7c5767019"},"previous_names":["flugger/laravel-responder"],"tags_count":118,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flugg%2Flaravel-responder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flugg%2Flaravel-responder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flugg%2Flaravel-responder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flugg%2Flaravel-responder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/flugg","download_url":"https://codeload.github.com/flugg/laravel-responder/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243493990,"owners_count":20299750,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","fractal","laravel","lumen","responder","transformer"],"created_at":"2024-07-30T18:00:42.827Z","updated_at":"2026-01-11T16:51:55.347Z","avatar_url":"https://github.com/flugg.png","language":"PHP","funding_links":["https://www.paypal.com/cgi-bin/webscr?cmd=_donations\u0026business=PRMC9WLJY8E46\u0026lc=NO\u0026item_name=Laravel%20Responder\u0026currency_code=USD\u0026bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted"],"categories":["Popular Packages"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/1271812/111231999-824f2b00-85ea-11eb-9afc-c0176529a234.png\" width=\"500px\"\u003e\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/flugger/laravel-responder\"\u003e\u003cimg src=\"https://poser.pugx.org/flugger/laravel-responder/v/stable?format=flat-square\" alt=\"Latest Stable Version\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://packagist.org/packages/flugger/laravel-responder\"\u003e\u003cimg src=\"https://img.shields.io/packagist/dt/flugger/laravel-responder.svg?style=flat-square\" alt=\"Packagist Downloads\"\u003e\u003c/a\u003e\n    \u003ca href=\"LICENSE.md\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square\" alt=\"Software License\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://travis-ci.org/flugger/laravel-responder\"\u003e\u003cimg src=\"https://img.shields.io/travis/flugger/laravel-responder/master.svg?style=flat-square\" alt=\"Build Status\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://scrutinizer-ci.com/g/flugger/laravel-responder/?branch=master\"\u003e\u003cimg src=\"https://img.shields.io/scrutinizer/g/flugger/laravel-responder.svg?style=flat-square\" alt=\"Code Quality\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://scrutinizer-ci.com/g/flugger/laravel-responder/code-structure/master\"\u003e\u003cimg src=\"https://img.shields.io/scrutinizer/coverage/g/flugger/laravel-responder.svg?style=flat-square\" alt=\"Test Coverage\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_donations\u0026business=PRMC9WLJY8E46\u0026lc=NO\u0026item_name=Laravel%20Responder\u0026currency_code=USD\u0026bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted\"\u003e\u003cimg src=\"https://img.shields.io/badge/donate-PayPal-yellow.svg?style=flat-square\" alt=\"Donate\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nLaravel Responder is a package for building API responses, integrating [Fractal](https://github.com/thephpleague/fractal) into Laravel and Lumen. It can transform your data using transformers, create and serialize success- and error responses, handle exceptions and assist you with testing your responses.\n\n# Table of Contents\n\n- [Introduction](#introduction)\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Usage](#usage)\n    - [Creating Responses](#creating-responses)\n    - [Creating Success Responses](#creating-success-responses)\n    - [Creating Transformers](#creating-transformers)\n    - [Transforming Data](#transforming-data)\n    - [Creating Error Responses](#creating-error-responses)\n    - [Handling Exceptions](#handling-exceptions)\n- [Contributing](#contributing)\n- [Donating](#contributing)\n- [License](#license)\n\n# Introduction\n\nLaravel lets you return models directly from a controller method to convert it to JSON. This is a quick way to build APIs but leaves your database columns exposed. [Fractal](https://fractal.thephpleague.com), a popular PHP package from [The PHP League](https://thephpleague.com/), solves this by introducing transformers. However, it can be a bit cumbersome to integrate into the framework as seen below:\n\n```php\n public function index()\n {\n    $resource = new Collection(User::all(), new UserTransformer());\n\n    return response()-\u003ejson((new Manager)-\u003ecreateData($resource)-\u003etoArray());\n }\n```\n\nNot _that_ bad, but we all get a little spoiled by Laravel's magic. Wouldn't it be better if we could refactor it to:\n\n```php\npublic function index()\n{\n    return responder()-\u003esuccess(User::all())-\u003erespond();\n}\n```\n\nThe package will allow you to do this and much more. The goal has been to create a high-quality package that feels like native Laravel. A package that lets you embrace the power of Fractal, while hiding it behind beautiful abstractions. There has also been put a lot of focus and thought to the documentation. Happy exploration!\n\n# Requirements\n\nThis package requires:\n- PHP __7.0__+\n- Laravel __5.1__+ or Lumen __5.1__+\n\n# Installation\n\nTo get started, install the package through Composer:\n\n```shell\ncomposer require flugger/laravel-responder\n```\n\n## Laravel\n\n#### Register Service Provider\n\nAppend the following line to the `providers` key in `config/app.php` to register the package:\n\n```php\nFlugg\\Responder\\ResponderServiceProvider::class,\n```\n\n***\n_The package supports auto-discovery, so if you use Laravel 5.5 or later you may skip registering the service provider and facades as they will be registered automatically._\n***\n\n#### Register Facades _(optional)_\n\nIf you like facades, you may also append the `Responder` and `Transformation` facades to the `aliases` key:\n\n```php\n'Responder' =\u003e Flugg\\Responder\\Facades\\Responder::class,\n'Transformation' =\u003e Flugg\\Responder\\Facades\\Transformation::class,\n```\n\n#### Publish Package Assets _(optional)_\n\nYou may additionally publish the package configuration and language file using the `vendor:publish` Artisan command:\n\n```shell\nphp artisan vendor:publish --provider=\"Flugg\\Responder\\ResponderServiceProvider\"\n```\n\nThis will publish a `responder.php` configuration file in your `config` folder. It will also publish an `errors.php` file inside your `lang/en` folder which can be used for storing error messages.\n\n## Lumen\n\n#### Register Service Provider\n\nAdd the following line to `app/bootstrap.php` to register the package:\n\n```php\n$app-\u003eregister(Flugg\\Responder\\ResponderServiceProvider::class);\n```\n\n#### Register Facades _(optional)_\n\nYou may also add the following lines to `app/bootstrap.php` to register the facades:\n\n```php\nclass_alias(Flugg\\Responder\\Facades\\Responder::class, 'Responder');\nclass_alias(Flugg\\Responder\\Facades\\Transformation::class, 'Transformation');\n```\n\n#### Publish Package Assets _(optional)_\n\nSeeing there is no `vendor:publish` command in Lumen, you will have to create your own `config/responder.php` file if you want to configure the package.\n\n# Usage\n\nThis documentation assumes some knowledge of how [Fractal](https://github.com/thephpleague/fractal) works.\n\n## Creating Responses\n\nThe package has a `Responder` service class, which has a `success` and `error` method to build success- and error responses respectively. To use the service and begin creating responses, pick one of the options below:\n\n#### Option 1: Inject `Responder` Service\n\nYou may inject the `Flugg\\Responder\\Responder` service class directly into your controller methods:\n\n```php\npublic function index(Responder $responder)\n{\n    return $responder-\u003esuccess();\n}\n```\n\nYou can also use the `error` method to create error responses:\n\n```php\nreturn $responder-\u003eerror();\n```\n\n#### Option 2: Use `responder` Helper\n\nIf you're a fan of Laravel's `response` helper function, you may like the `responder` helper function:\n\n```php\nreturn responder()-\u003esuccess();\n```\n```php\nreturn responder()-\u003eerror();\n```\n\n#### Option 3: Use `Responder` Facade\n\nOptionally, you may use the `Responder` facade to create responses:\n\n```php\nreturn Responder::success();\n```\n```php\nreturn Responder::error();\n```\n\n#### Option 4: Use `MakesResponses` Trait\n\nLastly, the package provides a `Flugg\\Responder\\Http\\MakesResponses` trait you can use in your controllers:\n\n```php\nreturn $this-\u003esuccess();\n```\n\n```php\nreturn $this-\u003eerror();\n```\n\n***\n_Which option you pick is up to you, they are all equivalent, the important thing is to stay consistent. The helper function (option 2) will be used for the remaining of the documentation._\n***\n\n### Building Responses\n\nThe `success` and `error` methods return a `SuccessResponseBuilder` and `ErrorResponseBuilder` respectively, which both extend an abstract `ResponseBuilder`, giving them common behaviors. They will be converted to JSON when returned from a controller, but you can explicitly create an instance of `Illuminate\\Http\\JsonResponse` with the `respond` method:\n\n```php\nreturn responder()-\u003esuccess()-\u003erespond();\n```\n\n```php\nreturn responder()-\u003eerror()-\u003erespond();\n```\n\nThe status code is set to `200` by default, but can be changed by setting the first parameter. You can also pass a list of headers as the second argument:\n\n```php\nreturn responder()-\u003esuccess()-\u003erespond(201, ['x-foo' =\u003e true]);\n```\n\n```php\nreturn responder()-\u003eerror()-\u003erespond(404, ['x-foo' =\u003e false]);\n```\n\n***\n_Consider always using the `respond` method for consistency's sake._\n***\n\n### Casting Response Data\n\nInstead of converting the response to a `JsonResponse` using the `respond` method, you can cast the response data to a few other types, like an array:\n\n```php\nreturn responder()-\u003esuccess()-\u003etoArray();\n```\n\n```php\nreturn responder()-\u003eerror()-\u003etoArray();\n```\n\nYou also have a `toCollection` and `toJson` method at your disposal.\n\n### Decorating Response\n\nA response decorator allows for last minute changes to the response before it's returned. The package comes with two response decorators out of the box adding a `status` and `success` field to the response output. The `decorators` key in the configuration file defines a list of all enabled response decorators:\n\n```php\n'decorators' =\u003e [\n    \\Flugg\\Responder\\Http\\Responses\\Decorators\\StatusCodeDecorator::class,\n    \\Flugg\\Responder\\Http\\Responses\\Decorators\\SuccessFlagDecorator::class,\n],\n```\n\nYou may disable a decorator by removing it from the list, or add your own decorator extending the abstract class `Flugg\\Responder\\Http\\Responses\\Decorators\\ResponseDecorator`. You can also add additional decorators per response:\n\n```php\nreturn responder()-\u003esuccess()-\u003edecorator(ExampleDecorator::class)-\u003erespond();\n```\n```php\nreturn responder()-\u003eerror()-\u003edecorator(ExampleDecorator::class)-\u003erespond();\n```\n\n***\n\nThe package also ships with some situational decorators disabled by default, but which can be added to the decorator list: \n- `PrettyPrintDecorator` decorator will beautify the JSON output;\n\n```php\n\\Flugg\\Responder\\Http\\Responses\\Decorators\\PrettyPrintDecorator::class,\n```\n\n- `EscapeHtmlDecorator` decorator, based on the \"sanitize input, escape output\" concept, will escape HTML entities in all strings returned by your API. You can securely store input data \"as is\" (even malicious HTML tags) being sure that it will be outputted as un-harmful strings. Note that, using this decorator, printing data as text will result in the wrong representation and you must print it as HTML to retrieve the original value.\n\n```php\n\\Flugg\\Responder\\Http\\Responses\\Decorators\\EscapeHtmlDecorator::class,\n```\n\n***\n\n## Creating Success Responses\n\nAs briefly demonstrated above, success responses are created using the `success` method:\n\n```php\nreturn responder()-\u003esuccess()-\u003erespond();\n```\n\nAssuming no changes have been made to the configuration, the above code would output the following JSON:\n\n```json\n{\n    \"status\": 200,\n    \"success\": true,\n    \"data\": null\n}\n```\n\n### Setting Response Data\n\nThe `success` method takes the response data as the first argument:\n\n```php\nreturn responder()-\u003esuccess(Product::all())-\u003erespond();\n```\n\nIt accepts the same data types as you would normally return from your controllers, however, it also supports query builder and relationship instances:\n\n```php\nreturn responder()-\u003esuccess(Product::where('id', 1))-\u003erespond();\n```\n\n```php\nreturn responder()-\u003esuccess(Product::first()-\u003eshipments())-\u003erespond();\n```\n\n***\n_The package will run the queries and convert them to collections behind the scenes._\n***\n\n### Transforming Response Data\n\nThe response data will be transformed with Fractal if you've attached a transformer to the response. There are two ways to attach a transformer; either _explicitly_ by setting it on the response, or _implicitly_ by binding it to a model. Let's look at both ways in greater detail.\n\n#### Setting Transformer On Response\n\nYou can attach a transformer to the response by sending a second argument to the `success` method. For instance, below we're attaching a simple closure transformer, transforming a list of products to only output their names:\n\n```php\nreturn responder()-\u003esuccess(Product::all(), function ($product) {\n    return ['name' =\u003e $product-\u003ename];\n})-\u003erespond();\n```\n\nYou may also transform using a dedicated transformer class:\n\n```php\nreturn responder()-\u003esuccess(Product::all(), ProductTransformer::class)-\u003erespond();\n```\n\n```php\nreturn responder()-\u003esuccess(Product::all(), new ProductTransformer)-\u003erespond();\n```\n\n***\n_You can read more about creating dedicated transformer classes in the [Creating Transformers](#creating-transformers) chapter._\n***\n\n#### Binding Transformer To Model\n\nIf no transformer is set, the package will search the response data for an element implementing the `Flugg\\Responder\\Contracts\\Transformable` interface to resolve a transformer from. You can take use of this by implementing the `Transformable` interface in your models:\n\n```php\nclass Product extends Model implements Transformable {}\n```\n\nYou can satisfy the contract by adding a `transformer` method that returns the corresponding transformer:\n\n```php\n/**\n * Get a transformer for the class.\n *\n * @return \\Flugg\\Responder\\Transformers\\Transformer|string|callable\n */\npublic function transformer()\n{\n    return ProductTransformer::class;\n}\n```\n\n***\n_You're not limited to returning a class name string, you can return a transformer instance or closure transformer, just like the second parameter of the `success` method._\n***\n\nInstead of implementing the `Transformable` contract for all models, an alternative approach is to bind the transformers using the `bind` method on the `TransformerResolver` class. You can place the code below within `AppServiceProvider` or an entirely new `TransformerServiceProvider`:\n\n```php\nuse Flugg\\Responder\\Contracts\\Transformers\\TransformerResolver;\n\npublic function boot()\n{\n    $this-\u003eapp-\u003emake(TransformerResolver::class)-\u003ebind([\n        \\App\\Product::class =\u003e \\App\\Transformers\\ProductTransformer::class,\n        \\App\\Shipment::class =\u003e \\App\\Transformers\\ShipmentTransformer::class,\n    ]);\n}\n```\n\nAfter you've bound a transformer to a model you can skip the second parameter and still transform the data:\n\n```php\nreturn responder()-\u003esuccess(Product::all())-\u003erespond();\n```\n\n***\n_As you might have noticed, unlike Fractal, you don't need to worry about creating resource objects like `Item` and `Collection`. The package will make one for you based on the data type, however, you may wrap your data in a resource object to override this._\n***\n\n### Setting Resource Key\n\nIf the data you send into the response is a model or contains a list of models, a resource key will implicitly be resolved from the model's table name. You can overwrite this by adding a `getResourceKey` method to your model:\n\n```php\npublic function getResourceKey(): string {\n    return 'products';\n}\n```\n\nYou can also explicitly set a resource key on a response by sending a third argument to the ´success` method:\n\n```php\nreturn responder()-\u003esuccess(Product::all(), ProductTransformer::class, 'products')-\u003erespond();\n```\n\n### Paginating Response Data\n\nSending a paginator to the `success` method will set pagination meta data and transform the data automatically, as well as append any query string parameters to the paginator links.\n\n```php\nreturn responder()-\u003esuccess(Product::paginate())-\u003erespond();\n```\n\nAssuming there are no products and the default configuration is used, the JSON output would look like:\n\n```json\n{\n    \"success\": true,\n    \"status\": 200,\n    \"data\": [],\n    \"pagination\": {\n        \"total\": 0,\n        \"count\": 0,\n        \"perPage\": 15,\n        \"currentPage\": 1,\n        \"totalPages\": 1,\n        \"links\": []\n    }\n}\n```\n\n#### Setting Paginator On Response\n\nInstead of sending a paginator as data, you may set the data and paginator seperately, like you traditionally would with Fractal. You can manually set a paginator using the `paginator` method, which expects an instance of `League\\Fractal\\Pagination\\IlluminatePaginatorAdapter`:\n\n```php\n$paginator = Product::paginate();\n$adapter = new IlluminatePaginatorAdapter($paginator);\n\nreturn responder()-\u003esuccess($paginator-\u003egetCollection())-\u003epaginator($adapter)-\u003erespond();\n```\n\n#### Setting Cursor On Response\n\nYou can also set cursors using the `cursor` method, expecting an instance of `League\\Fractal\\Pagination\\Cursor`:\n\n```php\nif ($request-\u003ehas('cursor')) {\n    $products = Product::where('id', '\u003e', request()-\u003ecursor)-\u003etake(request()-\u003elimit)-\u003eget();\n} else {\n    $products = Product::take(request()-\u003elimit)-\u003eget();\n}\n\n$cursor = new Cursor(request()-\u003ecursor, request()-\u003eprevious, $products-\u003elast()-\u003eid ?? null, Product::count());\n\nreturn responder()-\u003esuccess($products)-\u003ecursor($cursor)-\u003erespond();\n```\n\n### Including Relationships\n\nIf a transformer class is attached to the response, you can include relationships using the `with` method:\n\n```php\nreturn responder()-\u003esuccess(Product::all())-\u003ewith('shipments')-\u003erespond();\n```\n\nYou can send multiple arguments and specify nested relations using dot notation:\n\n```php\nreturn responder()-\u003esuccess(Product::all())-\u003ewith('shipments', 'orders.customer')-\u003erespond();\n```\n\nAll relationships will be automatically eager loaded, and just like you would when using `with` or `load` to eager load with Eloquent, you may use a callback to specify additional query constraints. Like in the example below, where we're only including related shipments that hasn't yet been shipped:\n\n```php\nreturn responder()-\u003esuccess(Product::all())-\u003ewith(['shipments' =\u003e function ($query) {\n    $query-\u003ewhereNull('shipped_at');\n}])-\u003erespond();\n```\n\n#### Including From Query String\n\nRelationships are loaded from a query string parameter if the `load_relations_parameter` configuration key is set to a string. By default, it's set to `with`, allowing you to automatically include relations from the query string:\n\n```\nGET /products?with=shipments,orders.customer\n```\n\n#### Excluding Default Relations\n\nIn your transformer classes, you may specify relations to automatically load. You may disable any of these relations using the `without` method:\n\n```php\nreturn responder()-\u003esuccess(Product::all())-\u003ewithout('comments')-\u003erespond();\n```\n\n### Filtering Transformed Data\n\nThe technique of filtering the transformed data to only return what we need is called sparse fieldsets and can be specified using the `only` method:\n\n```php\nreturn responder()-\u003esuccess(Product::all())-\u003eonly('id', 'name')-\u003erespond();\n```\n\nWhen including relationships, you may also want to filter fields on related resources as well. This can be done by instead specifying an array where each key represents the resource keys for the resources being filtered\n\n```php\nreturn responder()-\u003esuccess(Product::all())-\u003ewith('shipments')-\u003eonly([\n    'products' =\u003e ['id', 'name'],\n    'shipments' =\u003e ['id']\n])-\u003erespond();\n```\n\n#### Filtering From Query String\n\nFields will automatically be filtered if the `filter_fields_parameter` configuration key is set to a string. It defaults to `only`, allowing you to filter fields from the query string:\n\n```\nGET /products?only=id,name\n```\n\nYou may automatically filter related resources by setting the parameter to a key-based array:\n\n```\nGET /products?with=shipments\u0026only[products]=id,name\u0026only[shipments]=id\n```\n\n### Adding Meta Data\n\nYou may want to attach additional meta data to your response. You can do this using the `meta` method:\n\n```php\nreturn responder()-\u003esuccess(Product::all())-\u003emeta(['count' =\u003e Product::count()])-\u003erespond();\n```\n\nWhen using the default serializer, the meta data will simply be appended to the response array:\n\n```json\n{\n    \"success\": true,\n    \"status\": 200,\n    \"data\": [],\n    \"count\": 0\n}\n```\n\n### Serializing Response Data\n\nAfter the data has been transformed, it will be serialized using the specified success serializer in the configuration file, which defaults to the package's own `Flugg\\Responder\\Serializers\\SuccessSerializer`. You can overwrite this on your responses using the `serializer` method:\n\n```php\nreturn responder()-\u003esuccess()-\u003eserializer(JsonApiSerializer::class)-\u003erespond();\n```\n\n```php\nreturn responder()-\u003esuccess()-\u003eserializer(new JsonApiSerializer())-\u003erespond();\n```\n\nAbove we're using Fractal's `JsonApiSerializer` class. Fractal also ships with an `ArraySerializer` and `DataArraySerializer` class. If none of these suit your taste, feel free to create your own serializer by extending `League\\Fractal\\Serializer\\SerializerAbstract`. You can read more about it in [Fractal's documentation](http://fractal.thephpleague.com/serializers/).\n\n## Creating Transformers\n\nA dedicated transformer class gives you a convenient location to transform data and allows you to reuse the transformer at multiple places. It also allows you to include and transform relationships. You can create a transformer using the `make:transformer` Artisan command:\n\n```shell\nphp artisan make:transformer ProductTransformer\n```\n\nThe command will generate a new `ProductTransformer.php` file in the `app/Transformers` folder:\n\n```php\n\u003c?php\n\nnamespace App\\Transformers;\n\nuse App\\User;\nuse Flugg\\Responder\\Transformers\\Transformer;\n\nclass ProductTransformer extends Transformer\n{\n    /**\n     * List of available relations.\n     *\n     * @var string[]\n     */\n    protected $relations = [];\n\n    /**\n     * A list of autoloaded default relations.\n     *\n     * @var array\n     */\n    protected $load = [];\n\n    /**\n     * Transform the model.\n     *\n     * @param  \\App\\Product $product\n     * @return array\n     */\n    public function transform(Product $product): array\n    {\n        return [\n            'id' =\u003e (int) $product-\u003eid,\n        ];\n    }\n}\n```\n\nIt will automatically resolve a model name from the name provided. For instance, the package will extract `Product` from `ProductTransformer` and assume the models live directly in the `app` folder (as per Laravel's convention). If you store them somewhere else, you can use the `--model` (or `-m`) option to override it: \n\n```shell\nphp artisan make:transformer ProductTransformer --model=\"App\\Models\\Product\"\n```\n\n#### Creating Plain Transformers\n\nThe transformer file generated above is a model transformer expecting an `App\\Product` model for the `transform` method. However, we can create a plain transformer by applying the `--plain` (or `-p`) modifier:\n\n```shell\nphp artisan make:transformer ProductTransformer --plain\n```\n\nThis will remove the typehint from the `transform` method and add less boilerplate code.\n\n### Setting Relationships\n\nThe `$relations` and `$load` properties in the transformer are the equivalent to Fractal's own `$availableIncludes` and `$defaultIncludes`. In addition to the slight name change, the package uses the `$relations` and `$load` properties to map out all available relationships for eager loading, so in contrast to Fractal, you should map the relationship to their corresponding transformer:\n\n```php\nprotected $relations = [\n    'shipments' =\u003e ShipmentTransformer::class,\n];\n```\n\n***\n_You can choose to skip the mapping and just pass the strings like with Fractal, but that means the package wont be able to eager load relationships automatically._\n***\n\n#### Setting Whitelisted Relationships\n\nThe `$relations` property specifies a list of relations available to be included. You can set a list of relations mapped to their corresponding transformers:\n\n```php\nprotected $relations = [\n    'shipments' =\u003e ShipmentTransformer::class,\n    'orders' =\u003e OrderTransformer::class,\n];\n```\n\n#### Setting Autoloaded Relationships\n\nThe `$load` property specifies a list of relations to be autoloaded every time you transform data with the transformer:\n\n```php\nprotected $load = [\n    'shipments' =\u003e ShipmentTransformer::class,\n    'orders' =\u003e OrderTransformer::class,\n];\n```\n\n***\n_You don't have to add relations to both `$relations` and `$load`, all relations in `$load` will be available by nature._\n***\n\n### Including Relationships\n\nWhile Fractal requires you to to create a method in your transformer for every included relation, this package lets you skip this when transforming models, as it will automatically fetch relationships from the model. You may of course override this functionality by creating an \"include\" method:\n\n```php\n/**\n * Include related shipments.\n *\n * @param  \\App\\Product $product\n * @return mixed\n */\npublic function includeShipments(Product $product)\n{\n    return $product-\u003eshipments;\n}\n```\n\nUnlike Fractal you can just return the data directly without wrapping it in an `item` or `collection` method.\n\n***\n_You should be careful with executing database calls inside the include methods as you might end up with an unexpected amount of hits to the database._\n***\n\n#### Using Include Parameters\n\nFractal can parse query string parameters which can be used when including relations. For more information about how to format the parameters see Fractal's [documentation on parameters](https://fractal.thephpleague.com/transformers/#include-parameters). You may access the parameters by adding a second parameter to the \"include\" method:\n\n```php\npublic function includeShipments(Product $product, Collection $parameters)\n{\n    return $product-\u003eshipments-\u003etake($parameters-\u003eget('limit'));\n}\n```\n\n***\n_To be as decoupled from Fractal as possible the parameters (which are normally accessed using `League\\Fractal\\ParamBag`) are accessed as Laravel collections instead._\n***\n\n#### Adding Query Constraints\n\nJust as you can specify a query constraint when including a relationship with the `with` method, you can also add query constraints as a \"load\" method on the transformer. This will automatically be applied when extracting relationships for eager loading.\n\n```php\n/**\n * Load shipments with constraints.\n *\n * @param  \\Illuminate\\Database\\Eloquent\\Builder $query\n * @return \\Illuminate\\Database\\Eloquent\\Builder\n */\npublic function loadShipments($query)\n{\n    return $query-\u003ewhereNull('shipped_at');\n}\n```\n\n***\n_Note: You cannot mix \"include\" and \"load\" methods because the package doesn't eager load relationships included with an \"include\" method._\n***\n\n### Filtering Relationships\n\nAfter a relation has been included, you can make any last second changes to it using a filter method. For instance, below we're filtering the list of related shipments to only include shipments that has not been shipped:\n\n```php\n/**\n * Filter included shipments.\n *\n * @param  \\Illuminate\\Database\\Eloquent\\Collection $shipments\n * @return \\Illuminate\\Support\\Collection\n */\npublic function filterShipments($shipments)\n{\n    return $shipments-\u003efilter(function ($shipment) {\n        return is_null($shipment-\u003eshipped_at);\n    });\n}\n```\n\n## Transforming Data\n\nWe've looked at how to transform response data of success responses, however, there may be other places than your controllers where you want to transform data. An example is broadcasted events where you're exposing data using websockets instead of HTTP. You just want to return the transformed data, not an entire response. \n\nIt's possible to simply transform data by newing up the transformer and calling `transform`:\n\n```php\nreturn (new ProductTransformer)-\u003etransform(Product::first());\n```\n\nHowever, this approach might become a bit messy when building transformations with relationships:\n\n```php\nreturn array_merge((new ProductTransformer)-\u003etransform($product = Product::first()), [\n    'shipments' =\u003e $product-\u003eshipments-\u003emap(function ($shipment) {\n        return (new ShipmentTransformer)-\u003etransform($shipment);\n    })\n]);\n```\n\nYuck! Imagine that with multiple nested relationships. Let's explore a simpler way to handle this.\n\n### Building Transformations\n\nThe `SuccessResponseBuilder` actually delegates all of the transformation work to a dedicated `Flugg\\Responder\\TransformBuilder` class. We can use this class ourself to transform data. For instance, if the product and shipment transformers were bound to the models, we could replicate the code above in the following way:\n\n```php\npublic function index(TransformBuilder $transformation)\n{\n    return $transformation-\u003eresource(Product::all())-\u003ewith('shipments')-\u003etransform();\n}\n```\n\nInstead of using the `success` method on the `Responder` service, we use the `resource` method on the `TransformBuilder` with the same method signature. We also use `transform` to execute the transformation instead of `respond` as we did when creating responses. In addition to the `with` method, you also have access to the other transformation methods like `without`, `only`, `meta` and `serializer`.\n\n***\n_Using `toArray` on the `Responder` service is almost the same as the code above, however, it will also include response decorators which might not be desired._\n***\n\n### Transforming Without Serializing\n\nWhen using the `TransformBuilder` to transform data it will still serialize the data using the configured serializer. Fractal requires the use of a serializer to transform data, but sometimes we're just interested in the raw transformed data. The package ships with a `Flugg\\Responder\\Serializers\\NoopSerializer` to solve this, a no-op serializer which leaves the transformed data untouched:\n\n```php\nreturn $transformation-\u003eresource(Product::all())-\u003eserializer(NoopSerializer::class)-\u003etransform();\n```\n\nIf you think this is looking messy, don't worry, there's a quicker way. In fact, you will probably never even need to utilize the `NoopSerializer` or `TransformBuilder` manually, but it helps to know how it works. The `Flugg\\Responder\\Transformation` is a class which can be used for quickly transforming data without serializing.\n\n#### Option 1: The `Transformation` Service\n\nThe `Transformation` class utilizes the `TransformBuilder` class to build a transformation using the `NoopSerializer`. You can inject the `Transformation` class and call `make` to obtain an instance of `TransformBuilder` which gives you access to all of the chainable methods including `with`, like below:\n\n```php\npublic function __construct(Transformation $transformation)\n{\n    $transformation-\u003emake(Product::all())-\u003ewith('shipments')-\u003etransform();\n}\n```\n\n#### Option 2: The `transformation` Helper\n\nYou can use the `transformation` helper function to transform data without serializing:\n\n```php\ntransformation(Product::all())-\u003ewith('shipments')-\u003etransform();\n```\n\n#### Option 3: The `Transformation` Facade\n\nYou can also use the `Transformation` facade to achieve the same thing:\n\n```php\nTransformation::make(Product::all())-\u003ewith('shipments')-\u003etransform();\n```\n\n### Transforming To Camel Case\n\nModel attributes are traditionally specified in snake case, however, you might prefer to use camel case for the response fields. A transformer makes for a perfect location to convert the fields, as seen from the `soldOut` field in the example below:\n\n```php\nreturn responder()-\u003esuccess(Product::all(), function ($product) {\n    return ['soldOut' =\u003e (bool) $product-\u003esold_out];    \n})-\u003erespond();\n```\n\n#### Transforming Request Parameters\n\nAfter responding with camel case, you probably want to let people send in request data using camel cased parameters as well. The package provides a `Flugg\\Responder\\Http\\Middleware\\ConvertToSnakeCase` middleware you can append to the `$middleware` array in `app/Http/Kernel.php` to convert all parameters to snake case automatically:\n\n```php\nprotected $middleware = [\n    // ...\n    \\Flugg\\Responder\\Http\\Middleware\\ConvertToSnakeCase::class,\n];\n```\n\n***\n_The middleware will run before request validation, so you should specify your validation rules in snake case as well._\n***\n\n## Creating Error Responses\n\nWhenever a consumer of your API does something unexpected, you can return an error response describing the problem. As briefly shown in a previous chapter, an error response can be created using the `error` method:\n\n```php\nreturn responder()-\u003eerror()-\u003erespond();\n```\n\nThe error response has knowledge about an error code, a corresponding error message and optionally some error data. With the default configuration, the above code would output the following JSON:\n\n```json\n{\n    \"success\": false,\n    \"status\": 500,\n    \"error\": {\n        \"code\": null,\n        \"message\": null\n    }\n}\n```\n\n### Setting Error Code \u0026 Message\n\nYou can fill the first parameter of the `error` method to set an error code:\n\n```php\nreturn responder()-\u003eerror('sold_out_error')-\u003erespond();\n```\n\n***\n_You may optionally use integers for error codes._\n***\n\nIn addition, you may set the second parameter to an error message describing the error:\n\n```php\nreturn responder()-\u003eerror('sold_out_error', 'The requested product is sold out.')-\u003erespond();\n```\n\n#### Set Messages In Language Files\n\nYou can set the error messages in a language file, which allows for returning messages in different languages. The configuration file has an `error_message_files` key defining a list of language files with error messages. By default, it is set to `['errors']`, meaning it will look for an `errors.php` file inside `resources/lang/en`. You can use these files to map error codes to corresponding error messages:\n\n```php\nreturn [\n    'sold_out_error' =\u003e 'The requested product is sold out.',\n];\n```\n\n#### Register Messages Using `ErrorMessageResolver`\n\nInstead of using language files, you may alternatively set error messages directly on the `ErrorMessageResolver` class. You can place the code below within `AppServiceProvider` or an entirely new `TransformerServiceProvider`:\n\n```php\nuse Flugg\\Responder\\ErrorMessageResolver;\n\npublic function boot()\n{\n    $this-\u003eapp-\u003emake(ErrorMessageResolver::class)-\u003eregister([\n        'sold_out_error' =\u003e 'The requested product is sold out.',\n    ]);\n}\n```\n\n### Adding Error Data\n\nYou may want to set additional data on the error response. Like in the example below, we're returning a list of shipments with the `sold_out` error response, giving the consumer information about when a new shipment for the product might arrive.\n\n```php\nreturn responder()-\u003eerror('sold_out')-\u003edata(['shipments' =\u003e Shipment::all()])-\u003erespond();\n```\n\nThe error data will be appended to the response data. Assuming we're using the default serializer and there are no shipments in the database, the code above would look like:\n\n```json\n{\n    \"success\": false,\n    \"status\": 500,\n    \"error\": {\n        \"code\": \"sold_out\",\n        \"message\": \"The requested product is sold out.\",\n        \"shipments\": []\n    }\n}\n```\n\n### Serializing Response Data\n\nSimilarly to success responses, error responses will be serialized using the specified error serializer in the configuration file. This defaults to the package's own `Flugg\\Responder\\Serializers\\ErrorSerializer`, but can of course be changed by using the `serializer` method:\n\n```php\nreturn responder()-\u003eerror()-\u003eserializer(ExampleErrorSerializer::class)-\u003erespond();\n```\n\n```php\nreturn responder()-\u003esuccess()-\u003eserializer(new ExampleErrorSerializer())-\u003erespond();\n```\n\nYou can create your own error serializer by implementing the `Flugg\\Responder\\Contracts\\ErrorSerializer` contract.\n\n## Handling Exceptions\n\nNo matter how much we try to avoid them, exceptions do happen. Responding to the exceptions in an elegant manner will improve the user experience of your API. The package can enhance your exception handler to automatically turn exceptions in to error responses. If you want to take use of this, you can either use the package's exception handler or include a trait as described in further details below.\n\n#### Option 1: Replace `Handler` Class\n\nTo use the package's exception handler you need to replace the default import in `app/Exceptions/Handler.php`:\n\n```php\nuse Illuminate\\Foundation\\Exceptions\\Handler as ExceptionHandler;\n```\n\nWith the package's handler class:\n\n```php\nuse Flugg\\Responder\\Exceptions\\Handler as ExceptionHandler;\n```\n\n***\nThis will not work with Lumen as its exception handler is incompatible with Laravel's. Look instead at the second option below.\n***\n\n#### Option 2: Use `ConvertsExceptions` Trait\n\nThe package's exception handler uses the `Flugg\\Responder\\Exceptions\\ConvertsExceptions` trait to load of most of its work. Instead of replacing the exception handler, you can use the trait in your own handler class. To replicate the behavior of the exception handler, you would also have to add the following code to the `render` method:\n\n```php\npublic function render($request, Exception $exception)\n{\n    $this-\u003econvertDefaultException($exception);\n\n    if ($exception instanceof HttpException) {\n        return $this-\u003erenderResponse($exception);\n    }\n\n    return parent::render($request, $exception);\n}\n```\n\nIf you only want to return JSON error responses on requests actually asking for JSON, you may wrap the code above in a `wantsJson` check as seen below:\n\n```php\nif ($request-\u003ewantsJson()) {\n    $this-\u003econvertDefaultException($exception);\n\n    if ($exception instanceof HttpException) {\n        return $this-\u003erenderResponse($exception);\n    }\n}\n```\n\n### Converting Exceptions\n\nOnce you've implemented one of the above options, the package will convert some of Laravel's exceptions to an exception extending `Flugg\\Responder\\Exceptions\\Http\\HttpException`. It will then convert these to an error response. The table below shows which Laravel exceptions are converted and what they are converted to. All the exceptions on the right is under the `Flugg\\Responder\\Exceptions\\Http` namespace and extends `Flugg\\Responder\\Exceptions\\Http\\HttpException`. All exceptions extending the `HttpException` class will be automatically converted to an error response. \n\n| Caught Exceptions                                               | Converted To                 |\n| --------------------------------------------------------------- | ---------------------------- |\n| `Illuminate\\Auth\\AuthenticationException`                       | `UnauthenticatedException`   |\n| `Illuminate\\Auth\\Access\\AuthorizationException`                 | `UnauthorizedException`      |\n| `Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException`  | `PageNotFoundException`      |\n| `Illuminate\\Database\\Eloquent\\ModelNotFoundException`           | `PageNotFoundException`      |\n| `Illuminate\\Database\\Eloquent\\RelationNotFoundException`        | `RelationNotFoundException`  |\n| `Illuminate\\Validation\\ValidationException`                     | `ValidationFailedException`  |\n\nYou can disable the conversions of some of the exceptions above using the `$dontConvert` property:\n\n```php\n/**\n * A list of default exception types that should not be converted.\n *\n * @var array\n */\nprotected $dontConvert = [\n    ModelNotFoundException::class,\n];\n```\n\n***\nIf you're using the trait option, you can disable all the default conversions by removing the call to `convertDefaultException` in the `render` method.\n***\n\n#### Convert Custom Exceptions\n\nIn addition to letting the package convert Laravel exceptions, you can also convert your own exceptions using the `convert` method in the `render` method:\n\n```php\n$this-\u003econvert($exception, [\n    InvalidValueException =\u003e PageNotFoundException,\n]);\n```\n\nYou can optionally give it a closure that throws the new exception, if you want to give it constructor parameters: \n\n```php\n$this-\u003econvert($exception, [\n    MaintenanceModeException =\u003e function ($exception) {\n        throw new ServerDownException($exception-\u003eretryAfter);\n    },\n]);\n```\n\n### Creating HTTP Exceptions\n\nAn exception class is a convenient place to store information about an error. The package provides an abstract exception class `Flugg\\Responder\\Exceptions\\Http\\HttpException`, which has knowledge about status code, an error code and an error message. Continuing on our product example from above, we could create our own `HttpException` class:\n\n```php\n\u003c?php\n\nnamespace App\\Exceptions;\n\nuse Flugg\\Responder\\Exceptions\\Http\\HttpException;\n\nclass SoldOutException extends HttpException\n{\n    /**\n     * The HTTP status code.\n     *\n     * @var int\n     */\n    protected $status = 400;\n\n    /**\n     * The error code.\n     *\n     * @var string|null\n     */\n    protected $errorCode = 'sold_out_error';\n\n    /**\n     * The error message.\n     *\n     * @var string|null\n     */\n    protected $message = 'The requested product is sold out.';\n}\n```\n\nYou can also add a `data` method returning additional error data:\n\n```php\n/**\n * Retrieve additional error data.\n *\n * @return array|null\n */\npublic function data()\n{\n    return [\n        'shipments' =\u003e Shipment::all()\n    ];\n}\n```\n\nIf you're letting the package handle exceptions, you can now throw the exception anywhere in your application and it will automatically be rendered to an error response.\n\n```php\nthrow new SoldOutException();\n```\n\n# Contributing\n\nContributions are more than welcome and you're free to create a pull request on Github. You can run tests with the following command:\n\n```shell\nvendor/bin/phpunit\n```\n\nIf you find bugs or have suggestions for improvements, feel free to submit an issue on Github. However, if it's a security related issue, please send an email to flugged@gmail.com instead.\n\n# Donating\n\nThe package is completely free to use, however, a lot of time has been put into making it. If you want to show your appreciation by leaving a small donation, you can do so by clicking [here](https://www.paypal.com/cgi-bin/webscr?cmd=_donations\u0026business=PRMC9WLJY8E46\u0026lc=NO\u0026item_name=Laravel%20Responder\u0026currency_code=USD\u0026bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted). Thanks!\n\n# License\n\nLaravel Responder is free software distributed under the terms of the MIT license. See [license.md](license.md) for more details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflugg%2Flaravel-responder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflugg%2Flaravel-responder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflugg%2Flaravel-responder/lists"}