2017 © Pedro Peláez
 

library dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

image

aedart/dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  • Saturday, March 3, 2018
  • by aedart
  • Repository
  • 4 Watchers
  • 19 Stars
  • 3,081 Installations
  • PHP
  • 1 Dependents
  • 1 Suggesters
  • 1 Forks
  • 1 Open issues
  • 13 Versions
  • 113 % Grown

The README.md

Build Status Latest Stable Version Total Downloads Latest Unstable Version License, (*1)

Deprecated - Data Transfer Object (DTO)

Package has been replaced by aedart/athenaeum, (*2)

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). A DTO is nothing more than an object that can hold some data. Most commonly it is used for for transporting that data between systems, e.g. a client and a server., (*3)

This package provides an abstraction for such DTOs., (*4)

If you don't know about DTOs, I recommend you to read Martin Fowler's description of DTO, and perhaps perform a few Google searches about this topic., (*5)

Contents

When to use this

  • When there is a strong need to interface DTOs, e.g. what properties must be available via getters and setters
  • When you need to encapsulate data that needs to be communicated between systems and or component instances

Nevertheless, using DTOs can / will increase complexity of your project. Therefore, you should only use it, when you are really sure that you need them., (*6)

How to install

composer require aedart/dto

This package uses composer. If you do not know what that is or how it works, I recommend that you read a little about, before attempting to use this package., (*7)

Quick start

Custom Interface for your DTO

Start off by creating an interface for your DTO. Below is an example for a simple Person interface, (*8)

<?php
use Aedart\DTO\Contracts\DataTransferObject as DataTransferObjectInterface;

interface PersonInterface extends DataTransferObjectInterface
{
    /**
     * Set the person's name
     *
     * @param string|null $name
     */
    public function setName(?string $name);

    /**
     * Get the person's name
     *
     * @return string
     */
    public function getName() : ?string;

    /**
     * Set the person's age
     *
     * @param int $age
     */
    public function setAge(?int $age);

    /**
     * Get the person's age
     *
     * @return int
     */
    public function getAge() : ?int;
}

Concrete implementation of your DTO

Create a concrete implementation of your interface. Let it extend the default DataTransferObject abstraction., (*9)

<?php
declare(strict_types=1);

use Aedart\DTO\DataTransferObject;

class Person extends DataTransferObject implements PersonInterface
{

    protected $name = '';

    protected $age = 0;

    /**
     * Set the person's name
     *
     * @param string $name
     */
    public function setName(?string $name)
    {
        $this->name = $name;
    }

    /**
     * Get the person's name
     *
     * @return string
     */
    public function getName() : ?string
    {
        return $this->name;
    }

    /**
     * Set the person's age
     *
     * @param int $age
     */
    public function setAge(?int $age)
    {
        $this->age = $age;
    }

    /**
     * Get the person's age
     *
     * @return int
     */
    public function getAge() : ?int
    {
        return $this->age;
    } 

}

Now you are ready to use the DTO. The following sections will highlight some of the usage scenarios., (*10)

Property overloading

Each defined property is accessible in multiple ways, if a getter and or setter method has been defined for that given property., (*11)

For additional information, please read about Mutators and Accessor, PHP's overloading, and PHP's Array-Access, (*12)

<?php

// Create a new instance of your DTO
$person = new Person();

// Name can be set using normal setter methods
$person->setName('John');

// But you can also just set the property itself
$person->name = 'Jack'; // Will automatically invoke setName()

// And you can also set it, using an array-accessor
$person['name'] = 'Jane'; // Will also automatically invoke setName()

// ... //

// Obtain age using the regular getter method
$age = $person->getAge();

// Can also get it via invoking the property directly
$age = $person->age; // Will automatically invoke getAge()

// Lastly, it can also be access via an array-accessor
$age = $person['age']; // Also invokes the getAge()

Tip: PHPDoc's property-tag

If you are using a modern IDE, then it will most likely support PHPDoc., (*13)

By adding a @property tag to your interface or concrete implementation, your IDE will be able to auto-complete the overloadable properties., (*14)

Populating via an array

You can populate your DTO using an array., (*15)

<?php

// property-name => value array
$data = [
    'name' => 'Timmy Jones',
    'age'  => 32
];

// Create instance and invoke populate
$person = new Person();
$person->populate($data); // setName() and setAge() are invoked with the given values

If you are extending the default DTO abstraction, then you can also pass in an array in the constructor, (*16)

<?php

// property-name => value array
$data = [
    'name' => 'Carmen Rock',
    'age'  => 25
];

// Create instance and invoke populate
$person = new Person($data); // invokes populate(...), which then invokes the setter methods

Export properties to array

Each DTO can be exported to an array., (*17)

<?php

// Provided that you have a populated instance, you can export those properties to an array 
$properties = $person->toArray();

var_dump($properties);  // Will output a "property-name => value" list
                        // Example:
                        //  [
                        //      'name'  => 'Timmy'
                        //      'age'   => 16
                        //  ]

Serialize to Json

All DTOs are Json serializable, meaning that they inherit from the JsonSerializable interface. This means that when using json_encode(), the DTO automatically ensures that its properties are serializable by the encoding method., (*18)

<?php

$person = new Person([
    'name' => 'Rian Dou',
    'age' => 29
]);

echo json_encode($person);

The above example will output the following;, (*19)

``` json { "name":"Rian Dou", "age":29 }, (*20)


You can also perform json serialization directly on the DTO, by invoking the `toJson()` method. ```php <?php $person = new Person([ 'name' => 'Rian Dou', 'age' => 29 ]); echo $person->toJson(); // The same as invoking json_encode($person);

Advanced usage

Inversion of Control (IoC) / Dependency Injection

In this interpretation of the DTO design pattern, each instance must hold a reference to an IoC service container., (*21)

If you do not know what this means or how this works, please start off by reading the wiki-article about it., (*22)

Bootstrapping a service container

If you are using this package inside a Laravel application, then you can skip this part; it is NOT needed!, (*23)

<?php

use Aedart\DTO\Providers\Bootstrap;

// Invoke the bootstrap's boot method, before using any DTOs
// Ideally, this should happen along side your application other bootstrapping logic
Bootstrap::boot(); // A default service container is now available 

Nested instances

Imagine that your Person DTO accepts more complex properties, e.g. an address;, (*24)

NOTE: This example will only work if;, (*25)

a) You are using the DTO inside a Laravel application, (*26)

or, (*27)

b) You have invoked the Bootstrap::boot() method, before using the given DTO (...once again this is not needed, if you are using this package inside a Laravel application), (*28)

<?php
declare(strict_types=1);

use Aedart\DTO\DataTransferObject;

// None-interfaced DTO class is on purpose for this example
class Address extends DataTransferObject
{

    protected $street = '';

    /**
     * Set the street
     *
     * @param string $street
     */
    public function setStreet(?string $street)
    {
        $this->street = $street;
    }

    /**
     * Get the street
     *
     * @return string
     */
    public function getStreet() : ?string
    {
        return $this->street;
    }
}

// You Person DTO now accepts an address object
class Person extends DataTransferObject implements PersonInterface
{

    protected $name = '';

    protected $age = 0;

    protected $address = null;

    // ... getters and setters for name and age not shown ... //

     /**
      * Set the address
      *
      * @param Address $address
      */
     public function setAddress(?Address $address)
     {
         $this->address = $address;
     }

     /**
      * Get the address
      *
      * @return Address
      */
     public function getAddress() : ?Address
     {
         return $this->address;
     }
}

// ... some place else, in your application ... //

// Data for your Person DTO
$data = [
    'name' => 'Arial Jackson',
    'age' => 42,

    // Notice that we are NOT passing in an instance of Address, but an array instead!
    'address' => [
        'street' => 'Somewhere str. 44'
    ]
];

$person = new Person($data);                                    
$address = $person->getAddress();   // Instance of Address - Will automatically be resolved (if possible).

In the above example, Laravel's Service Container attempts to find and create any concrete instances that are expected., (*29)

Furthermore, the default DTO abstraction (Aedart\DTO\DataTransferObject) will attempt to automatically populate that instance., (*30)

Interface bindings

If you prefer to use interfaces instead, then you need to bind those interfaces to concrete instances, before the DTOs / service container can handle and resolve them., (*31)

Outside Laravel Application

If you are outside a Laravel application, then you can bind interfaces to concrete instances, in the following way;, (*32)

<?php

// Somewhere in your application's bootstrapping logic

use Aedart\DTO\Providers\Bootstrap;

// Boot up the service container
Bootstrap::boot(); 

// Register / bind your interfaces to concrete instances
Bootstrap::getContainer()->bind(CityInterface::class, function($app){
    return new City();
});

Inside Laravel Application

Inside your application's service provider (or perhaps a custom service provider), you can bind your DTO interfaces to concrete instances;, (*33)

<?php

// ... somewhere inside your service provider

// Register / bind your interfaces to concrete instances
$this->app->bind(CityInterface::class, function($app){
    return new City();
});

Example

Given that you have bound your interfaces to concrete instances, then the following is possible, (*34)

<?php
use Aedart\DTO\Contracts\DataTransferObject as DataTransferObjectInterface;
use Aedart\DTO\DataTransferObject;

// Interface for a City
interface CityInterface extends DataTransferObjectInterface
{
    /**
     * Set the city's name
     *
     * @param string $name
     */
    public function setName(string $name) : void;

    /**
     * Get the city's name
     *
     * @return string
     */
    public function getName() : string;
}

// Concrete implementation of City
class City extends DataTransferObject implements CityInterface
{
    protected $name = '';

    // ... getter and setter implementation not shown ... //
}

// Address class now also accepts a city property, of the type CityInterface
class Address extends DataTransferObject
{

    protected $street = '';

    protected $city = null;

    // ... street getter and setter implementation not shown ... //

     /**
      * Set the city
      *
      * @param CityInterface $address
      */
     public function setCity(?CityInterface $city)
     {
         $this->city = $city;
     }

     /**
      * Get the city
      *
      * @return CityInterface
      */
     public function getCity() : ?CityInterface
     {
         return $this->city;
     }
}

// ... some other place in your application ... //

$addressData = [
    'street' => 'Marshall Street 27',
    'city' => [
        'name' => 'Lincoln'
    ]
];

// Create new instance and populate
$address = new Address($addressData);   // Will attempt to automatically resolve the expected city property,
                                        // of the CityInterface type, by creating a concrete City, using
                                        // the service container, and resolve the bound interface instance

Contribution

Have you found a defect ( bug or design flaw ), or do you wish improvements? In the following sections, you might find some useful information on how you can help this project. In any case, I thank you for taking the time to help me improve this project's deliverables and overall quality., (*35)

Bug Report

If you are convinced that you have found a bug, then at the very least you should create a new issue. In that given issue, you should as a minimum describe the following;, (*36)

  • Where is the defect located
  • A good, short and precise description of the defect (Why is it a defect)
  • How to replicate the defect
  • (A possible solution for how to resolve the defect)

When time permits it, I will review your issue and take action upon it., (*37)

Fork, code and send pull-request

A good and well written bug report can help me a lot. Nevertheless, if you can or wish to resolve the defect by yourself, here is how you can do so;, (*38)

  • Fork this project
  • Create a new local development branch for the given defect-fix
  • Write your code / changes
  • Create executable test-cases (prove that your changes are solid!)
  • Commit and push your changes to your fork-repository
  • Send a pull-request with your changes
  • Drink a Beer - you earned it :)

As soon as I receive the pull-request (_and have time for it_), I will review your changes and merge them into this project. If not, I will inform you why I choose not to., (*39)

Acknowledgement

Versioning

This package follows Semantic Versioning 2.0.0, (*40)

License

BSD-3-Clause, Read the LICENSE file included in this package, (*41)

The Versions

03/03 2018

dev-master

9999999-dev https://github.com/aedart/data-transfer-object-dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  Sources   Download

BSD-3-Clause

The Requires

 

The Development Requires

by Alin Eugen Deac

design pattern dto data transfer object

03/03 2018

5.0.0

5.0.0.0 https://github.com/aedart/data-transfer-object-dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  Sources   Download

BSD-3-Clause

The Requires

 

The Development Requires

by Alin Eugen Deac

design pattern dto data transfer object

05/09 2017

4.0.0

4.0.0.0 https://github.com/aedart/data-transfer-object-dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  Sources   Download

BSD-3-Clause

The Requires

 

The Development Requires

by Alin Eugen Deac

design pattern dto data transfer object

28/01 2017

3.0.0

3.0.0.0 https://github.com/aedart/data-transfer-object-dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  Sources   Download

BSD-3-Clause

The Requires

 

The Development Requires

by Alin Eugen Deac

design pattern dto data transfer object

08/01 2017

2.1.0

2.1.0.0 https://github.com/aedart/data-transfer-object-dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  Sources   Download

BSD-3-Clause

The Requires

 

The Development Requires

by Alin Eugen Deac

design pattern dto data transfer object

28/08 2016

2.0.0

2.0.0.0 https://github.com/aedart/data-transfer-object-dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  Sources   Download

BSD-3-Clause

The Requires

 

The Development Requires

by Alin Eugen Deac

design pattern dto data transfer object

28/08 2016

1.3.1

1.3.1.0 https://github.com/aedart/data-transfer-object-dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  Sources   Download

BSD-3-Clause

The Requires

 

The Development Requires

by Alin Eugen Deac

design pattern dto data transfer object

03/01 2016

1.3.0

1.3.0.0 https://github.com/aedart/data-transfer-object-dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  Sources   Download

BSD-3-Clause

The Requires

 

The Development Requires

by Alin Eugen Deac

design pattern dto data transfer object

17/10 2015

1.2.0

1.2.0.0 https://github.com/aedart/data-transfer-object-dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  Sources   Download

BSD-3-Clause

The Requires

 

The Development Requires

by Alin Eugen Deac

design pattern dto data transfer object

04/10 2015

1.1.1

1.1.1.0 https://bitbucket.org/aedart/data-transfer-object-dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  Sources   Download

BSD-3-Clause

The Requires

 

The Development Requires

by Alin Eugen Deac

design pattern dto data transfer object

04/10 2015

1.1.0

1.1.0.0 https://bitbucket.org/aedart/data-transfer-object-dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  Sources   Download

BSD-3-Clause

The Requires

 

The Development Requires

by Alin Eugen Deac

design pattern dto data transfer object

12/09 2015

1.0.0

1.0.0.0 https://bitbucket.org/aedart/data-transfer-object-dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  Sources   Download

BSD-3-Clause

The Requires

 

The Development Requires

by Alin Eugen Deac

design pattern dto data transfer object

06/09 2015

0.9.0

0.9.0.0 https://bitbucket.org/aedart/data-transfer-object-dto

A variation / interpretation of the Data Transfer Object (DTO) design pattern (Distribution Pattern). Provides an abstraction for such DTOs

  Sources   Download

BSD-3-Clause

The Requires

 

The Development Requires

by Alin Eugen Deac

design pattern dto data transfer object