GitHub Repository

apiato

Definition & Principles

Transporters is a name chosen by Apiato for DTO’s (Data Transfer Objects). Transporters are used to pass user data (coming from Requests, Commands, or other places) from place to another (Actions to Tasks / Controller to Action / Command to Action / …).

They are very useful for reducing the number of parameters in functions, which prevents the duplication of the long parameters.

Apiato uses this package for the DTO. Refer to the dto package wiki for more details.

Rules

Folder Structure

 - App
    - Containers
        - {container-name}
            - Data
                - Transporters
                    - CreateUserTransporter.php
                    - ...

Code Sample

Transporter class

<?php

namespace App\Containers\Authentication\Transporters;

use App\Ship\Parents\Transporters\Transporter;

class ProxyApiLoginTransporter extends Transporter
{

    /**
     * @var array
     */
    protected $schema = [
        'properties' => [
            'email',
            'password',
            'client_id',
            'client_password',
            'grant_type',
            'scope',
        ],
        'required'   => [
            'email',
            'password',
            'client_id',
            'client_password',
        ],
        'default'    => [
            'scope' => '',
        ]
    ];
}

Usage from Controller

Normally you would use it like this

$dataTransporter = new DataTransporter($request);
$dataTransporter->bearerToken = $request->bearerToken();

Apiato::call('Authentication@ApiLogoutAction', [$dataTransporter]);

Since this example above has some required data, that data must be sent to the constructor:

$dataTransporter = new ProxyApiLoginTransporter(
    array_merge($request->all(), [
        'client_id'       => Config::get('authentication-container.clients.web.admin.id'),
        'client_password' => Config::get('authentication-container.clients.web.admin.secret')
    ])
);

$result = Apiato::call('Authentication@ProxyApiLoginAction', [$dataTransporter]);

Creating a Transporter from Test

$data = [
	'foo' => 'bar'
];

$transporter = new DataTransporter($data);
$action = App::make(RegisterUserAction::class);

$user = $action->run($transporter);

Optionally switch between Requests and Transporters

// if you have the following function signature
public function run(DataTransporter $data)

// you would pass a DataTransporter to it
$user = Apiato::call('MyContainer@myAction', [new DataTransporter($request)]);
// if you have the following function signature
public function run(Request $data)

// you would pass a Request to it
$user = Apiato::call('MyContainer@myAction', [$request]);

// if request has Transporter defined on it, it will be the one passed to the Action. So the Action can even type hint the custom Transporter defined on the Request.

Here where the magic happens:

// if you have the following function signature
public function run(Request $data)

// you can pass a DataTransporter to it, only if you are using the magical call function, for the magic to work
$user = Apiato::call('MyContainer@myAction', [new DataTransporter($request)]);
// if you have the following function signature
public function run(DataTransporter $data)

// you can pass a DataTransporter to it, only if you are using the magical call function, for the magic to work
$user = Apiato::call('MyContainer@myAction', [$request]);

// if request has Transporter defined on it, it will be the one passed to the Action. So the Action can even type hint the custom Transporter defined on the Request.

Transforming a Request to a Transporter

If you want to directly transform a Request to a Transporter you can simply call

$transporter = $request->toTransporter();

This method does take the protected $transporter of the Request class into account. If none is defined, a regular DataTransporter will be created.

Note, that $transporter will now have all fields from $request - so you can directly access them. In order to do so, you can call:

// "simple" access via direct properties
$name = $transporter->name;

// complex access via method
$username = $transporter->getInputByKey('your.nested.username.field');

Of course, you can also “sanitize” the data, like you would have done in the Request classes by using sanitizeData(array).

Finally, if you need to access the original Request object, you can access it via

$originalRequest = $transporter->request;

Set Data

You can set data in many ways

$dataTransporter = new DataTransporter($request);
$dataTransporter->bearerToken = $request->bearerToken();

If the data is defined as required like this on the Transporter:

    protected $schema = [
        'type' => 'object',
        'properties' => [
            'email',
            'password',
            'clientId',
            'clientPassword',
        ],
        'required'   => [
            'email',
            'password',
            'clientId',
            'clientPassword',
        ],
    ];

Then can set data on the Transporter like this:

$dataTransporter = new ProxyApiLoginTransporter(
    array_merge($request->all(), [
        'clientId'       => Config::get('authentication-container.clients.web.admin.id'),
        'clientPassword' => Config::get('authentication-container.clients.web.admin.secret')
    ])
);

Set Instance

Passing Objects does not work!, because the third party package cannot hydrate it. So to pass instances from a place to another on the Transporter object, you can do the following:

$transporter = new DataTransporter();
$transporter->setInstance("command_instance", $this);

Warning: you can set instances, but they do not appear when calling toArray() or other similar functions, since they cannot be hydrated. See below how you can get the instance form the Transporter object.

Get Instance:

$console = $data->command_instance;

Get Data

To get all data from the Transporter you can call $data->toArray() or $data->toJson()… there are many other functions on the class.

To get specific data just call the data name, as you would when accessing data from a Request object $data->username.