Laravel Smokescreen is a package for transforming your Laravel models, and other entities.
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.
<?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.app('smokescreen') as shown above.Responsable interface, you can simply return smokescreen from any controller method.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.
To publish the configuration file to your app/config folder, run the following command:
php artisan vendor:publish --provider='RexlabsLaravelSmokescreenProvidersServiceProvider --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' => 'AppTransformers',
// 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',
];$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->item(mixed $item, mixed $transformer = null);
<?php
$smokescreen->item(Post::find(1));
$smokescreen->item(Post::find(1), new SomeOtherTransformer);transform() but only accepts a item.$smokescreen->collection(mixed $collection, mixed $transformer = null);
<?php
$smokescreen->collection(Post::all());
$smokescreen->collection(Post::paginate());
$smokescreen->collection(Post::paginate(), new SomeOtherTransformer);transform() but only accepts a collection.$smokescreen->transformWith(TransformerInterface|callable $transformer);
<?php
$smokescreen->transform(Post::find(1))
->transformWith(new SomeOtherTransformer);<?php
$smokescreen->serializeWith(new MyCustomSerializer);DefaultSerializer as the default, it returns collections nested under a "data" node, and an item
resource without any nesting.SerializerInterface interface.$smokescreen->loadRelationsVia(RelationsLoaderInterface $loader);
<?php
$smokescreen->loadRelationsVia(new MyRelationsLoader);RelationsLoader as the default which eager-loads relationships for collection resources.RelationsLoaderInterface interface and provide a load() method.$smokescreen->loadTransformersVia(TransformerResolverInterface $loader);
<?php
$smokescreen->loadTransformersVia(new MyTransformerResolver);smokescreen.transformer_namespace path, and instantiates it via the app container.TransformersLoaderInterface interface and provide a resolve(ResourceInterface) method.$response = $smokescreen->response(int $statusCode = 200, array $headers = [], int $options = 0);
<?php
$smokescreen->response()
->header('X-Custom-Header', 'boo')
->setStatusCode(405);IlluminateHttpJsonResponse object so it is not chainable.JsonResponse methods can be applied.response() directly from your controller since it is a JsonResponse object.withResponse($callback) to apply changes, and still support chainability.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 use clearResponse() or manipulate the
JsonResponse object directly.$response = $smokescreen->freshResponse(int $statusCode = 200, array $headers = [], int $options = 0);
response() this method returns a fresh non-cached JsonResponse object (by calling clearResponse() first).IlluminateHttpJsonResponse object so it is not chainable. See withResponse() for a
chainable method.JsonResponse methods can be applied.$smokescreen->withResponse(callable $apply);
<?php
$smokescreen->withResponse(function (JsonResponse $response) {
$response->header('X-Crypto-Alert', 'all your coins are worthless!');
});JsonResponse object and manipulates the responseresponse()$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<?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);
}
}$includes arraydefault: 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 as relation:othernamemethod: By default the include key is mapped to include{IncludeKey} you can provide the method
to be used insteadtransform() method should return an array.include{IncludeKey}(Model) - they should return either a
collection() or an item()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 be null if there is no user_id set on the $post object.Pull-requests are welcome. Please ensure code is PSR compliant. Github Repository