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='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',
];
$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);
\Illuminate\Http\JsonResponse
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).\Illuminate\Http\JsonResponse
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 response 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
<?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:othername
method
: 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