Skip to content

DTOs

Paquete para generar "DTOs" (data transfer objects) a partir de arrays. La idea me surgió porque quería tener "arrays tipados" y en PHP no es posible, pero con una clase relativamente sencilla, se puede conseguir.

Como se usa

Para crear un DTO se debe extender de la clase \Bittacora\Dtos\Dto. Esta clase abstracta tiene el código necesario para recibir un array (con las claves en snake_case, kebab-case o camelCase), hacer los casts necesarios, y llamar a su constructor, que deberá tener todos sus parámetros tipados y preferiblemente readonly. Es decir, si tenemos un dto como:

<?php  
// ...
use Bittacora\Dtos\Dto;  

final class MiDto extends Dto  
{  
    public function __construct(  
        public readonly int $intParameter,  
        public readonly string $stringParameter,  
        public readonly float $floatParameter,  
        public readonly bool $boolParameter,  
    ) {  
    }  
}

Podremos construirlo a partir de un array (por ejemplo, los datos de un Request de Laravel después de validarlos) de esta forma:

$dto = MiDto::fromArray([  
    'int-parameter' => '1',  
    'string_parameter' => 'cadena de texto',  
    'float_parameter' => '11.99',  
    'bool-parameter' => '1',  
]);

Y tendremos un objeto MiDto con todos sus tipos, etc.

Condiciones

Los nombre de los parámetros del constructor deberán ser iguales que los del array que se pase como parámetro. Se puede usar un array con las claves en snake_case, kebab-case o camelCase porque se convertirán automáticamente a camelCase.

Casts personalizados

Por tipo

Si se necesita cambiar la forma de castear a string (por ejemplo), tendremos que definir en nuestro DTO como queremos hacerlo. Para ello hay que sobreescribir el método getCustomTypeCast en nuestro DTO, y debe devolver un array de callables. Declararíamos lo siguiente en nuestro DTO (la clase MiDto del ejemplo):

protected static function getCustomTypeCast(): array  
{  
    return [  
        'string' => self::customStringCast(...),  
    ];  
}

Lógicamente también tendríamos que definir customStringCast en nuestro DTO. Por supuesto, se puede usar cualquier callable.

Las claves del array pueden contener el nombre completo de una clase, por si usamos tipos personalizados.

Ver apartado siguiente para ver los argumentos que reciben los callables.

Por campo

También podemos personalizar de forma individual cómo se hace el cast de un campo en concreto, de forma similar al punto anterior:

protected static function getCustomFieldCasts(): array  
{  
    return [  
        'customField' => self::castToCustomType(...)  
    ];  
}

Los argumentos que recibirán los callables son: string $field, string $type, mixed $value, bool $allowsNull