tconway1/mattyrad-support

PHP 支持类和特质的集合

v1.0.0 2024-02-07 14:30 UTC

This package is auto-updated.

Last update: 2024-09-07 17:18:52 UTC


README

Build Status Code Coverage

安装

composer require mattyrad/support

目录

确认特质

从未排序的数组中实例化对象

use MattyRad\Support\Conformation;

class Sample {
    use Conformation;

    private $arg1;
    private $arg2;
    private $arg3;
    private $arg4;
    private $optional1;
    private $optional2;

    private function __construct(
        string $arg1,
        int $arg2,
        bool $arg3,
        float $arg4,
        string $optional1 = '',
        int $optional2 = 1
    ) {
        $this->arg1 = $arg1;
        $this->arg2 = $arg2;
        $this->arg3 = $arg3;
        $this->arg4 = $arg4;
        $this->optional1 = $optional1;
        $this->optional2 = $optional2;
    }
}
$sample = Sample::fromArray([
    'optional2' => 777,
    'arg2' => 1,
    'arg3' => false,
    'arg1' => 'example',
    'arg4' => 2.0,
]);

未能提供所有必要的参数将抛出异常

$sample = Sample::fromArray([
    'arg1' => 'example',
    'arg2' => 1,
]);

PHP 致命错误:未捕获的 InvalidArgumentException:缺少样本关键字:arg3, arg4

结果对象

对于 API 来说,通常需要可扩展的结果对象以处理成功和失败情况,这非常常见。

定义结果

您可以使用通用的成功结果立即开始

$json_response_data = ['user' => ['name' => 'John', 'email' => 'user@example.com', 'posts' => [['name' => 'A'], ['name' => 'B']]]];

$result = new \MattyRad\Support\Result\Success($json_response_data);

$result->isSuccess(); // true
$result->isFailure(); // false
$result->get('user.email'); // dot syntax enabled
$result->get('user.posts.*.name'); // wildcard enabled, ['A', 'B']

为了更高的精度,您可以扩展成功结果

class WidgetPurchased extends Result\Success
{
    public function __construct(Widget $widget)
    {
        $this->widget = $widget;
    }

    public function getWidget(): Widget
    {
        return $this->widget;
    }
}

$result = new Result\Success\WidgetPurchased($widget);

$result->getWidget(); // Widget object
$result->isSuccess(); // true
$result->isFailure(); // false

失败结果需要更加具体

namespace MattyRad\Support\Result\Stripe;

use MattyRad\Support\Result;

class ChargeFailed extends Result\Failure
{
    protected static $message = 'Stripe charge failed, delinquent card';

    public function __construct($last_four_digits)
    {
        $this->last_four_digits = $last_four_digits;
    }

    public function getContext()
    {
        return ['last_four_digits' => $this->last_four_digits];
    }
}

$result->isSuccess(); // false
$result->isFailure(); // true
$result->get('widget.name'); // throws exception with message 'Stripe charge failed, delinquent card'
$result->getWidget(); // also throws exception with message 'Stripe charge failed, delinquent card'
$result->getMessage(); // 'Stripe charge failed, delinquent card'
$result->getContext(); // ['last_four_digits' => '1234']
$result->getReason(); // 'Stripe charge failed, delinquent card; {"last_four_digits":"1234"}'

实例化和返回结果

use MattyRad\Support\Result;

function purchaseWidget($user, string $widget_name): Result
{
    if ($existing_widget = $this->db->getWidgetByName($widget_name)) {
        return new Result\Failure\WidgetExists($existing_widget);
    }

    try {
        $user->charge(100); // API call, this could be any interface to stripe
    } catch (\Stripe\Error\Card $e) {
        return new Result\Failure\Stripe\ChargeFailed($e->getLastFour()); // pretend that getLastFour exists
    }

    $widget = new Widget($widget_name);

    return new Result\Success\WidgetPurchased($widget);
}

消费结果

您可以手动检查失败

$result = purchaseWidget(Auth::user(), 'my_cool_new_widget');

if ($result->isFailure()) {
    return new JsonResponse(['error' => $result->getReason()], 422);
}

return new JsonResponse($result->getWidget());

或者,您可以利用异常并省略成功/失败的检查。尝试从失败结果中访问数据将导致它抛出异常

$result = purchaseWidget(Auth::user(), 'my_cool_new_widget'); // returns ChargeFailed

return new Response($result->getWidget()); // Throws exception

Laravel 的异常处理器默认处理多种异常(如 HttpResponseException),我们可以通过覆盖失败结果的默认 toException 函数来利用这一点

class ChargeFailed extends Result\Failure
{
    // ...

    public function toException()
    {
        $response = new JsonResponse(['error' => static::$message], 422);

        return new HttpResponseException($response);
    }

并且错误处理将内置,我们可以专注于成功路径。任何非内置异常都可以在异常处理器的 render() 函数中捕获。