Transporters 本文未发布 发布文章

未匹配的标注

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

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

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.

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 0
发起讨论 只看当前版本


暂无话题~