mohamedhabibwork / laravel-model-transformers
Easy transformation layer for complex model attributes.
Requires
- php: >=5.3.0
- illuminate/support: ~5|~6|~7|~8|~9|~10
Requires (Dev)
- orchestra/testbench: >=3
- phpunit/phpunit: >=4
This package is auto-updated.
Last update: 2024-11-09 17:41:15 UTC
README
This package helps API developers to easily transform Eloquent models into arrays that are convertible to JSON.
Here's how you use it, let's say you have a model with the following data:
{ "name": "iPhone", "type": 1 }
Here you use a numerical value to represent the different types, you also have a mutator in the model that maps the numerical value to a string.
Inside the controller we can transform the model to be represented into more API friendly structure.
<?php class SomeController{ function getIndex(){ $product = Product::find(1); return response([ "product" => ProductTransformer::transform($product) ]); } }
The above code will result a JSON string that may look like this:
{ "product": { "name": "iPhone", "type": { "key": 1, "name": "Mobile Phone" } } }
Installation
Begin by installing the package through Composer. Run the following command in your terminal:
composer require themsaid/laravel-model-transformers
Once composer is done, add the package service provider in the providers array in config/app.php
Themsaid\Transformers\TransformersServiceProvider::class
Finally publish the config file:
php artisan vendor:publish --provider="Themsaid\Transformers\TransformersServiceProvider"
That's all what we need.
Usage
Create a model transformer class by extending the AbstractTransformer class:
<?php class CategoryTransformer extends Themsaid\Transformers\AbstractTransformer { public function transformModel(Model $item) { $output = [ 'name' => $item->name, 'type' => [ 'key' => $item->type, 'name' => $item->typeName ], ]; return $output; } }
Now you can call the transformer from any controller:
<?php return response( CategoryTransformer::transform( Category::find(1) ) );
You can also pass a collection and the result will be an array of transformed models:
<?php return response( CategoryTransformer::transform( Category::all() ) );
Dealing with relationships
The package contains two helpful methods for dealing with relationships, the first one helps you know if a specific relation is eager-loaded:
isRelationshipLoaded()
<?php class ProductTransformer extends AbstractTransformer { public function transformModel(Model $item) { $output = array_only($item->toArray(), ['name', 'id']); if ($this->isRelationshipLoaded($item, 'tags')) { $output['tags'] = TagTransformer::transform($item->tags); } return $output; } }
Now only if the tags are eager-loaded they will be presented in the $output array, this helps reminding you to eager-load when querying models with relationships.
isLoadedFromPivotTable()
This method helps you know if the model is loaded from a ManyToMany relationship, it's helpful when there are pivot data in the table and you would like to present them, example for that:
<?php class TagTransformer extends AbstractTransformer { public function transformModel(Model $item) { $output = array_only($item->toArray(), ['name', 'id']); if ($this->isLoadedFromPivotTable($item, 'products_tags')) { $output['relationship_data'] = [ 'is_active' => $item->pivot->is_active, ]; } return $output; } }
Passing options to the transformer
You may need to pass some options from the controller to the transformer, you can do that by providing an array of options to the transform()
method as a second parameter:
<?php CategoryTransformer::transform($category, ['hide_admin_id' => true])
Now from inside the CategoryTransformer you can check the options parameter:
<?php class CategoryTransformer extends AbstractTransformer { public function transformModel(Model $item) { $output = []; if (@$this->options['hide_admin_id']) { unset($output['admin_id']); } return $output; } }
Using the shorthand method
This package is shipped with a shorthand method for applying transformation for a Model or a Collection:
<?php class SomeController{ function getIndex(){ $product = Product::find(1); return response([ "product" => transform($product) ]); } }
Using the transform()
method, the package locates the suitable transformer based on the Model or the Collection passed as the first argument.
By default it assumes that all transformers are located under the App\Transformers
namespace, you can change this behaviour in the config file.
You may also pass options to the transformer as a second argument:
<?php transform(Model::find(1), ['use_nl2br' => true])