flolefebvre / serializer
Installs: 25
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/flolefebvre/serializer
Requires
- laravel/framework: ^12.3
- laravel/sanctum: ^4.0
Requires (Dev)
- orchestra/testbench: ^10.1
- pestphp/pest: ^3.7
- pestphp/pest-plugin-laravel: ^3.1
README
A zero‑boilerplate, attribute‑driven serializer / DTO helper for Laravel 10 & 11
Built for PHP ≥ 8.2 — lighter than 20 KB.
Table of Contents
- Why another serializer?
- Features
- Requirements
- Installation
- Quick start
- Advanced usage
- Performance & Limitations
- Contributing
- License
Why another serializer?
flolefebvre/serializer focuses on simplicity and strictness:
- DTOs are just classes extending
Serializable. - Validation occurs before the object exists — no invalid state can persist.
- No generated code or heavy reflection caches; your build stays ultra‑fast.
Features
| ✅ Constructor‑promoted DTOs only | ✅ Automatic validation via #[Rule] |
| ✅ Pure attribute configuration | ✅ Typed arrays (#[ArrayType]) |
| ✅ Laravel DI & Request auto‑binding | ✅ Custom type‑casts (TypeCast interface) |
| ✅ Eloquent JSON cast (single / list) | ✅ JsonResponse ready to return |
Requirements
- PHP 8.2+
- Laravel 10 / 11
ext-json
Installation
composer require flolefebvre/serializer
Quick start
Create a DTO:
<?php namespace App\DTO; use Flolefebvre\Serializer\Serializable; use Flolefebvre\Serializer\Attributes\Rule; class PostData extends Serializable { public function __construct( public string $title, #[Rule('nullable|string|max:280')] public ?string $excerpt, #[Rule('required|url')] public string $url, ) {} }
Bind it in a route:
use App\DTO\PostData; use Illuminate\Support\Facades\Route; Route::post('/posts', function (PostData $data) { // $data is a fully validated DTO. // ... return $data; // => JsonResponse 201 });
Try it:
curl -X POST http://localhost/api/posts -H "Content-Type: application/json" -d '{"title":"Hello","excerpt":null,"url":"https://example.com"}'
Response:
{
"title": "Hello",
"excerpt": null,
"url": "https://example.com",
"_type": "App\\DTO\\PostData"
}
Advanced usage
Custom TypeCast
use Ramsey\Uuid\UuidInterface; use Flolefebvre\Serializer\Attributes\CastTypeWith; use Flolefebvre\Serializer\Casts\TypeCast; use Ramsey\Uuid\Uuid; class UuidCast implements TypeCast { // How the value will appear once serialized public string $serializedType = 'uuid'; public function serialize(mixed $value): mixed { return (string) $value; } public function unserialize(mixed $value): mixed { return Uuid::fromString($value); } } class OrderData extends Serializable { public function __construct( #[CastTypeWith(UuidCast::class)] public UuidInterface $id, ) {} }
Arrays of DTOs
use Flolefebvre\Serializer\Attributes\ArrayType; class BlogData extends Serializable { public function __construct( #[ArrayType(CommentData::class)] public array $comments, ) {} }
Performance & Limitations
| Topic | Notes |
|---|---|
| Reflection | Metadata is rebuilt on every call → enable OPcache and/or add a static cache for high‑traffic endpoints. |
| Union/Intersection Types | Not yet supported — contributions welcome. |
| Polymorphism | The _type field is required for subclasses during deserialization. |
Contributing
- Fork & clone
composer install && composer test- Create your feature branch (
git checkout -b feature/my-feature) - Push and open a PR
- Ensure tests pass and follow PSR‑12.
License
Released under the MIT License — see LICENSE.