apie/type-converter
Apie Type Converter converts values and objects to other types, ideal for mapping between DTOs and domain objects. Includes a default converter factory and lets you register custom converters to handle your own conversion rules.
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' => 'john@example.com'
], 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?