gergonzalez/lumen-fractal
Lumen service provider integrating League Fractal for clean API responses. Adds transformers/serializers support to format Eloquent data into consistent JSON structures, with simple configuration and container bindings for quick setup in Lumen microservices.
Installation
composer require gergonzalez/lumen-fractal
Add the service provider to bootstrap/app.php:
$app->register(\Gergonzalez\LumenFractal\FractalServiceProvider::class);
First Use Case
Define a simple transformer (e.g., app/Transformers/UserTransformer.php):
namespace App\Transformers;
use League\Fractal\TransformerAbstract;
class UserTransformer extends TransformerAbstract
{
public function transform($user)
{
return [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
];
}
}
Use it in a Lumen route:
use Gergonzalez\LumenFractal\Facades\Fractal;
Route::get('/users/{id}', function ($id) {
$user = User::findOrFail($id);
return Fractal::item(new UserTransformer(), $user)->toArray();
});
Key Files to Review
config/fractal.php (default config, if provided).app/Transformers/ (custom transformers).Gergonzalez\LumenFractal\Facades\Fractal (main facade).API Resource Transformation
Use Fractal::item() for single resources or Fractal::collection() for lists:
// Single resource
return Fractal::item(new PostTransformer(), $post)->toArray();
// Collection
return Fractal::collection(new PostTransformer(), Post::all())->toArray();
Nested Transformations Define relationships in transformers:
class UserTransformer extends TransformerAbstract
{
public function transform($user)
{
return [
'id' => $user->id,
'posts' => $this->lineItems($user->posts, new PostTransformer()),
];
}
}
Customizing Serialization Override default serialization (e.g., JSON) via config or facade:
Fractal::parseIncludes($request->input('include', []));
return Fractal::item($transformer, $model)->toArray();
Middleware Integration Attach Fractal logic to middleware for consistent responses:
$app->middleware([
\Gergonzalez\LumenFractal\Middleware\FractalMiddleware::class,
]);
FractalMiddleware to add pre-processing (e.g., auth checks).Fractal facade in PHPUnit:
$this->app->instance(\Gergonzalez\LumenFractal\Facades\Fractal::class, MockFractal::new());
Facade Initialization
Ensure the FractalServiceProvider is registered before using the facade. Lumen’s lazy loading may cause Undefined class errors if misconfigured.
Transformer Autoloading
The package doesn’t auto-discover transformers. Manually register them in FractalServiceProvider or use a naming convention (e.g., *Transformer).
Lumen vs. Laravel Quirks
RouteServiceProvider, so bind transformers manually:
$app->singleton(UserTransformer::class);
Route::resource(); use explicit routes for fine-grained Fractal control.Error Handling Fractal throws exceptions for invalid includes or missing transformers. Wrap calls in try-catch:
try {
return Fractal::item($transformer, $model)->toArray();
} catch (\League\Fractal\Manager::class $e) {
return response()->json(['error' => $e->getMessage()], 400);
}
Fractal::parseIncludes() to debug malformed include query params.dd($transformer->transform($model));
config/fractal.php to adjust default behavior (e.g., default_includes).Custom Serializers
Extend League\Fractal\Serializer\SerializerAbstract and bind it:
$app->singleton(\League\Fractal\Serializer\SerializerAbstract::class, CustomSerializer::class);
Resource Naming Dynamically set resource keys (e.g., for polymorphic relationships):
Fractal::item($transformer, $model, 'dynamic_key')->toArray();
Event Listeners
Listen for fractal.transforming events to modify payloads:
$app->on('fractal.transforming', function ($payload) {
$payload->setData(['custom_field' => true]);
});
How can I help you explore Laravel packages today?