rexlabs / laravel-smokescreen
Requires
- php: >=7.4 <8.4
- doctrine/dbal: ^2.5|^2.7|^3.0
- laravel/framework: ^8.0|^9.0|^10.0|^11.0
- rexlabs/smokescreen: ^2.3
Requires (Dev)
- orchestra/testbench: ^6.0
- phpunit/phpunit: ^9.0
- roave/security-advisories: dev-master
- squizlabs/php_codesniffer: ^3.5
- dev-master
- 4.0.0
- 3.4.1
- 3.4.0
- 3.3.1
- 3.3.0
- 3.3.0-rc
- 3.2.0
- 3.1.0
- 3.0.0
- 2.0.2
- 2.0.1
- 2.0.0
- 1.3.2
- 1.3.1
- 1.3.0
- 1.2.0
- 1.1.0
- 1.0.1
- 1.0.0
- v0.1.0
- dev-fix/include-key-source
- dev-fix/make-transformer-command-signature-error
- dev-feat/support-laravel-11
- dev-feat/smokescreen-bump-tests
- dev-feat/support-laravel-10
- dev-develop
- dev-feature/document-composition
- dev-feature/json-api
This package is auto-updated.
Last update: 2024-11-06 01:26:01 UTC
README
Overview
Laravel Smokescreen is a package for transforming your Laravel models, and other entities.
- Transform API responses
- Transform Job and Event payloads
- Minimal boiler-plate and bootstrap
- Supports complex relationships for embedded data
- Supports eager loading of relationships
- Allows transforming different types of resources
- Can handle serializing to customisable formats
This package tightly integrates the rexlabs/smokescreen (Vanilla PHP) package with the Laravel framework, to provide the convenience and minimal boilerplate when working with Laravel applications.
Usage
<?php class MyController extends Controller { public function index() { return Smokescreen::transform(Post::paginate()); } public function show(Post $post) { return Smokescreen::transform($post); } }
laravel-smokescreen
is bootstrapped into Laravel's app container, so you can also type-hint it to be injected into your controller's constructor or methods.- Using the facade (as above) is recommended within controller methods, use type-hinting in service classes (if needed)
- You can also use it directly from the container via
app('smokescreen')
as shown above. - Since we implement the
Responsable
interface, you can simply return smokescreen from any controller method.
Requirements
- PHP >= 7.0
- Laravel >= 5.5
Installation
This package is currently hosted on RexSoftware's private packagist repository. First ensure you have configured your
composer.json
to use this repository.
Install package
composer require rexlabs/laravel-smokescreen
This package will be auto-discovered, and no additional configuration is necessary.
Configuration
To publish the configuration file to your app/config
folder, run the following command:
php artisan vendor:publish --provider='Rexlabs\Laravel\Smokescreen\Providers\ServiceProvider --tag=config'
This will create config/smokescreen.php
:
<?php return [ // Set the default namespace for resolving transformers when // they are not explicitly provided. 'transformer_namespace' => 'App\Transformers', // Override the default serializer to be used. // If not specified - the Smokescreen DefaultSerializer will be used. 'default_serializer' => null, // Set the default request parameter key which is parsed for // the list of includes. 'include_key' => 'include', ];
API
transform(): Set resource to be transformed
$smokescreen->transform(mixed $resource, mixed $transformer = null);
<?php $smokescreen->transform(Post::find(1)); $smokescreen->transform(Post::all()); $smokescreen->transform(Post::paginate()); $smokescreen->transform(Post::find(1), new SomeOtherTransformer);
- Smokescreen will automatically determine the type of resource being transformed.
- It will also infer the Transformer class to use if not provided.
item(): Set single item resource to be transformed
$smokescreen->item(mixed $item, mixed $transformer = null);
<?php $smokescreen->item(Post::find(1)); $smokescreen->item(Post::find(1), new SomeOtherTransformer);
- Similar to
transform()
but only accepts a item.
collection(): Set collection resource to be transformed
$smokescreen->collection(mixed $collection, mixed $transformer = null);
<?php $smokescreen->collection(Post::all()); $smokescreen->collection(Post::paginate()); $smokescreen->collection(Post::paginate(), new SomeOtherTransformer);
- Similar to
transform()
but only accepts a collection.
transformWith(): Set the transformer to use on the previously set resource
$smokescreen->transformWith(TransformerInterface|callable $transformer);
<?php $smokescreen->transform(Post::find(1)) ->transformWith(new SomeOtherTransformer);
- It's an alternative to passing the transformer directly to resource methods.
serializeWith(): Override the serializer to be used
<?php $smokescreen->serializeWith(new MyCustomSerializer);
- You only need to set this if you plan to use a different serialize than the default.
- We provide
DefaultSerializer
as the default, it returns collections nested under a"data"
node, and an item resource without any nesting. - Your custom serializer should implement the
SerializerInterface
interface.
loadRelationsVia(): Override the default Laravel relations loader
$smokescreen->loadRelationsVia(RelationsLoaderInterface $loader);
<?php $smokescreen->loadRelationsVia(new MyRelationsLoader);
- You only need to set this if you plan to use a different loader than the default,
- We provide
RelationsLoader
as the default which eager-loads relationships for collection resources. - Your custom loader should implement the
RelationsLoaderInterface
interface and provide aload()
method.
resolveTransformerVia(): Override the default transformer resolver
$smokescreen->loadTransformersVia(TransformerResolverInterface $loader);
<?php $smokescreen->loadTransformersVia(new MyTransformerResolver);
- The resolver is used when a transformer is not explicitly defined on a resource.
- The default resolver in this package tries to find a matching transformer class within the path defined in
smokescreen.transformer_namespace
path, and instantiates it via the app container. - You only need to set this if you plan to use a different resolver than the default.
- Your custom resolver should implement the
TransformersLoaderInterface
interface and provide aresolve(ResourceInterface)
method.
response(): Access the generated response object
$response = $smokescreen->response(int $statusCode = 200, array $headers = [], int $options = 0);
<?php $smokescreen->response() ->header('X-Custom-Header', 'boo') ->setStatusCode(405);
- This method returns an
\Illuminate\Http\JsonResponse
object so it is not chainable. - All supported
JsonResponse
methods can be applied. - You can still return
response()
directly from your controller since it is aJsonResponse
object. - You can alternatively use
withResponse($callback)
to apply changes, and still support chainability. - Note: the first call to
response()
caches the result so that the entire data set is not re-generated every time, this means passing any parameters on subsequent calls will be ignored. You can useclearResponse()
or manipulate theJsonResponse
object directly.
freshResponse(): Generate a fresh Response object
$response = $smokescreen->freshResponse(int $statusCode = 200, array $headers = [], int $options = 0);
- Unlike
response()
this method returns a fresh non-cached JsonResponse object (by callingclearResponse()
first). - This method returns an
\Illuminate\Http\JsonResponse
object so it is not chainable. SeewithResponse()
for a chainable method. - All supported
JsonResponse
methods can be applied.
withResponse(): Apply changes to the generated response object
$smokescreen->withResponse(callable $apply);
<?php $smokescreen->withResponse(function (JsonResponse $response) { $response->header('X-Crypto-Alert', 'all your coins are worthless!'); });
- Provide a callback that accepts a
JsonResponse
object and manipulates the response - This method is chainable unlike
response()
clearResponse(): Clear any cached response
$smokescreen->clearResponse();
<?php $smokescreen->response(); // Data is generated, response object is built and cached $smokescreen->response(500); // NOPE - Cached, wont be changed! $smokescreen->clearResponse(); $smokescreen->response(500); // Response is re-generated
- Reset's any cached response object
Transformers
Example Transformer
<?php class PostTransformer extends AbstractTransformer { protected $includes = [ 'user' => 'default|relation:user|method:includeTheDamnUser', 'comments' => 'relation', ]; public function transform(Post $post): array { return [ 'id' => $post->id, 'user' => $this->when($post->user_id, [ 'id' => $post->user_id, ]), 'title' => $post->title, 'summary' => $post->summary, 'body' => $post->body, 'created_at' => utc_datetime($post->created_at), 'updated_at' => utc_datetime($post->updated_at), ]; } public function includeTheDamnUser(Post $post) { return $this->item($post->user); // Infer Transformer } public function includeComments(Post $post) { return $this->collection($post->comments, new CommentTransformer); } }
- You declare your available includes via the
$includes
array - Each include accepts 0 or more of the following directives:
default
: This include is always enabled regardless of the requested includesrelation
: Indicates that a relation should be eager-loaded. If the relation name is different specify it asrelation:othername
method
: By default the include key is mapped toinclude{IncludeKey}
you can provide the method to be used instead
- Your
transform()
method should return an array. - Define your include methods in the format
include{IncludeKey}(Model)
- they should return either acollection()
or anitem()
when()
is a simple helper method which accepts a condition and returns either the given value when true, or null (by default) when false. In the above example the"user"
node will benull
if there is nouser_id
set on the$post
object.
Contributing
Pull-requests are welcome. Please ensure code is PSR compliant. Github Repository
About
- Author: Jodie Dunlop
- License: MIT
- Copyright (c) 2018 Rex Software Pty Ltd