apie/type-converter
Apie type converter converts PHP objects into other objects, ideal for mapping DTOs to domain objects and back. It ships with default converters and lets you easily write your own.
Installation:
composer require apie/type-converter
Add to composer.json if using Laravel’s autoloader:
"autoload": {
"psr-4": {
"App\\": "app/",
"Apie\\TypeConverter\\": "vendor/apie/type-converter/src/"
}
}
Run composer dump-autoload.
First Use Case:
Convert a simple array to a Laravel Carbon instance:
use Apie\TypeConverter\DefaultConvertersFactory;
use Carbon\Carbon;
$converter = DefaultConvertersFactory::create();
$result = $converter->convert(['year' => 2023, 'month' => 1], Carbon::class);
// Returns: Carbon instance for January 2023
Key Classes:
DefaultConvertersFactory: Bootstraps default converters.ConverterInterface: Core interface for type conversion.Converter: Default implementation (extend for custom logic).Instantiate Converter:
$converter = DefaultConvertersFactory::create();
Or customize with a Converter instance:
$converter = new Converter();
$converter->addConverter(new CustomConverter());
Basic Conversion:
// Convert array to Eloquent model
$user = $converter->convert([
'name' => 'John Doe',
'email' => '[email protected]'
], User::class);
Nested Conversions:
// Convert array with nested objects
$data = [
'user' => ['name' => 'Alice'],
'posts' => [['title' => 'Hello']]
];
$result = $converter->convert($data, [
'user' => User::class,
'posts' => [Post::class] // Array of Post models
]);
Laravel Integration:
public function rules() {
return [
'user' => ['required', Rule::exists('users')->converter($this->converter)]
];
}
public function toArray($request) {
return $this->converter->convert($this->resource, UserResource::class);
}
Service Container Binding (Laravel):
$this->app->singleton(ConverterInterface::class, function ($app) {
$converter = DefaultConvertersFactory::create();
$converter->addConverter(new CustomDateConverter());
return $converter;
});
Circular References:
User ↔ Post) will throw RecursionException.Converter::setMaxDepth() or implement CircularReferenceHandlerInterface.Type Mismatches:
string → Carbon) silently fails unless a converter is registered.Converter::setStrictMode(true) to throw exceptions on failures.Default Converters:
array → Carbon, array → DateTime), but no Eloquent model support by default.$converter->addConverter(new ModelConverter(User::class));
Performance:
$converter->setLogger(new Monolog\Logger('converter'));
$converter->getConverters(); // List all registered converters
Custom Converters:
class CustomConverter implements ConverterInterface {
public function canConvert($source, $target): bool {
return is_array($source) && $target === CustomModel::class;
}
public function convert($source, $target) {
return new CustomModel($source['data']);
}
}
$converter->addConverter(new CustomConverter());
Override Default Behavior:
Converter and override convert() or getConverter() methods.Laravel Service Provider:
public function register() {
$this->app->extend(ConverterInterface::class, function () {
$converter = DefaultConvertersFactory::create();
$converter->addConverter(new EloquentConverter());
return $converter;
});
}
Illuminate\Routing\Router::bind() with a custom resolver:
$router->bind('user', function ($value, $route) {
return app(ConverterInterface::class)->convert($value, User::class);
});
Rule::exists() for type-safe database lookups:
Rule::exists('users')->converter($this->converter)
How can I help you explore Laravel packages today?