Transporters

Transporters is a name chosen by HiveApi for DTO’s (Data Transfer Objects). The latter are used to pass user data (coming from Requests, Commands, or other components) from one 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 long parameters.

HiveApi relies on this third-party package as DTO. Refer to the dto package wiki for more details.

Rules

  • All Transporters MUST extend from App\Ship\Parents\Transporters\Transporter.

Folder Structure

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

Code Sample

<?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' => '',
        ]
    ];
}

Using a Transporter within a Controller

Normally you would use it like this

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

Hive::call(ApiLogoutAction::class, [$dataTransporter]);

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

<?php
$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 = Hive::call(ProxyApiLoginAction::class, [$dataTransporter]);

Creating a Transporter for Tests

<?php

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

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

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

Automatically 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:

<?php
// "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;

Data Access

Set Data

You can set data of a Transporter in many ways

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

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

<?php
    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')
    ])
);

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.

Instance Access

Set Instances

Passing Objects does not work, because the third-party package cannot hydrate it. In order to pass an instances from one place to another within a Transporter object, you can do the following:

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

Heads up!

Although you can set instances this way, 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 Instances

$console = $data->command_instance;