Array DTO
While the Dto
abstraction is good for situations where you must adhere to interfaces that define getters and setters, it can be a bit cumbersome to maintain a large number classes. This can especially be true, if you must create DTOs to represent all the resources available for a large scale API.
In such situations, the ArrayDto
abstraction is perhaps better suited. As it's name suggests, it uses an array
to keep track of it's properties. It functions almost the exact same way, as the Dto
abstraction.
Creating an Array-Dto
Extend the ArrayDto
abstraction and declare your DTO's properties, via the $allowed
variable.
The keys of the $allowed
variable correspond to your property's name, whereas the values correspond to the property's data type.
Whenever your DTO is populated, it will automatically ensure to cast the property to it's decalred type.
use Aedart\Dto\ArrayDto;
class Organisation extends ArrayDto
{
protected array $allowed = [
'name' => 'string',
'employees' => 'int',
'hasInsurance' => 'bool',
'profitScore' => 'float',
'boardMembers' => 'array',
'started' => 'date',
];
}
Working with Array-Dto
Once you have created your DTO instance, you can work with it just like the Dto
abstraction.
$dto = new Organisation([
'name' => 'Acme Ltd',
'employees' => 134,
'hasInsurance' => true,
'profitScore' => 33.8,
'boardMembers' => [ 'Sawyer', 'Stine', 'Jim' ],
'started' => '2018-06-15 10:00:00'
]);
echo $dto->name; // Acme Ltd
$dto['employees'] = 136; // 'employees' property set to 136
echo $dto->toJson(); // Json representation of dto
Supported Types
By default, each declared property is nullable
, meaning that a property is either of the declared data type or null
.
The following are the supported data types:
string
int
float
,bool
array
date
(property is parsed into aCarbon
instance)
Note
You can change how each type is casted or converted, by overwriting the castPropertyValue()
method.
Alternatively, you can overwrite each type's individual casting method, e.g. castAsDate()
, castAsBoolean()
, castAsString()
, ...etc.
For more information, please review the source code of \Aedart\Dto\Partials\CastingPartial
trait, which is used by the ArrayDto
.
Nested DTOs
In order to work with nested DTOs, you must declare their class path in the $allowed
property.
Other than that, the populate mechanism works in same way, as previously mentioned.
use Aedart\Dto\ArrayDto;
use Acme\Dto\Address;
class Organisation extends ArrayDto
{
protected array $allowed = [
'name' => 'string',
'address' => Address::class,
];
}
Union Types
The same union type handling is supported by the ArrayDto
abstraction, as for the regular Dto
.
class Article extends ArrayDto
{
protected array $allowed = [
'id' => 'string|int|float|bool|null',
'content' => 'array|null',
'createdAt' => 'date|null',
'author' => ['string', Person::class, Organisation::class, 'null'],
];
}
Review the DTO "Union Types" documentation for details and additional examples.
Getters and Setters
Should you require to mutate a property, then you can do so by defining an accessor or mutator method.
The naming rules, for your property getter or setter method, are the same as for overloading.
use Aedart\Dto\ArrayDto;
class Organisation extends ArrayDto
{
protected array $allowed = [
'name' => 'string', // Type ignored!
];
public function setName(?string $name)
{
$this->properties['name'] = strtoupper($name);
return $this;
}
public function getName() : ?string
{
return $this->properties['name'] ?? null;
}
}
Warning
When you define accessor or mutator method for a property, it's initial type declaration and casting is ignored. If special casting or converting is required, then you must manually handle such in your methods.