Data Transfer Objects help in «structuring» the data coming from different types of requests ( Http request, Webhook request etc. ) into single form which we can use in various parts of our application. With DTOs, we have confidence that we will not get unexpected data in our application logic.
Example
class CheckoutData extends DataTransferObject
{
public int $checkout_id;
public Carbon $completed_at;
public static function fromRequest(Request $request){ ... }
public static function fromWebhook(array $params)
{
return new self([
'checkout_id' => $params['id'],
'completed_at' => $params['completed_at']
]);
}
}
NOTE: Above code is valid only for PHP 7.4
We can then use this data object in other classes which are responsible for storing this information into database.
Credits
Before PHP7.4, we had to use a package by awesome spatie. You can read its documentation about how it works with mentioning «types» in doc blocks.
All the logic that I am using is taken from this package.
How do we construct a DTO?
First thought would be to use __construct
method and pass parameters for each property on DTO class. But this would get out of hand pretty quickly once we start adding more parameters.
static constructors
to the rescue.
As you can see in above example of CheckoutData
, fromWebhook
method returns a new instance of this class by passing an array and letting it construct itself.
In order to see what is really going on, let’s have a look at the DataTransferObject
base class.
abstract class DataTransferObject
{
public function __construct(array $parameters = [])
{
$class = new ReflectionClass(static::class);
foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $reflectionProperty){
$property = $reflectionProperty->getName();
$this->{$property} = $parameters[$property];
}
}
}
By leveraging PHP’s Reflection API
, we are getting every public property on CheckoutData
class and initializing it with value passed in parameters array.
This is how we can easily construct our Data Transfer Objects with PHP7.4.