DEV Community

Zubair Mohsin
Zubair Mohsin

Posted on

Data Transfer Object (DTO) in Laravel with PHP7.4 typed properties

Pre-requisite

Before reading this article, please read Working with Data chapter of Laravel Beyond CRUD series by Brent.

Introduction

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.

Top comments (0)