Chevere Action 1.0

Convention for working with Parameter

rodber
rodber   GitHub

New from Chevere is the Action package. This software provides an object oriented convention around Parameter.

The package source is available at chevere/action.

# What it does?

Consider the class MyAction as described below.

class MyAction
{
    public function main(string $var): int
    {
        if (! preg_match('/^ok/', $var)) {
            throw new InvalidArgumentException();
        }
        $return = mb_strlen($var);
        if ($return < 0 || $return > 100) {
            throw new InvalidArgumentException();
        }

        return $return;
    }
}

$action = new MyAction();
$action->main($value);

For the code above validation for $var argument and $return value is expressed within the function body.

Using the Action package the code above could be transformed and leverage the function body in a single line.

use Chevere\Action\Action;
use Chevere\Parameter\Attributes\IntAttr;
use Chevere\Parameter\Attributes\ReturnAttr;
use Chevere\Parameter\Attributes\StringAttr;

class MyAction extends Action
{
    #[ReturnAttr(
        new IntAttr(min: 0, max: 100)
    )]
    protected function main(
        #[StringAttr('/^ok/')]
        string $var
    ): int {
        return mb_strlen($var);
    }
}

$action = new MyAction();
$action($var);

Validation rules are the same, what changes is how and where you define those.

# How it works?

The Action package wraps a convention around Parameter which denotes the usage of a main method which will be called at __invoke where I sandwich (1) Arguments validation, (2) Run main logic, (3) Return value validation.

// src/Traits/ActionTrait.php
public function __invoke(mixed ...$argument): mixed
{

    try {
        // Assert no logic errors in Parameter rules
        $reflection = static::assert();
        // (1) Arguments validation
        $arguments = $reflection->parameters()->__invoke(...$argument);
    } catch (Throwable $e) {
        throw new ActionException();
    }
    // (2) Run main logic
    $result = $this->main(...$arguments->toArray());

    try {
        // (3) Return value validation
        $reflection->return()->__invoke($result);
    } catch (Throwable $e) {
        throw new ActionException();
    }

    return $result;
}

The ActionException is a special exception forwarding file:code location for the conflicting argument, not the wrapped call.

# Building block

The Action package is extensible and can be used to build on top of it. For example, at the Workflow package every Job is defined from an Action.

In the Http package every HTTP controller extends Controller class which extends Action to restrict main parameters for type string.

# Wrapping up

The convention on Action is simple to follow and provides a predictable, tested way to work with Parameter. Its application is trivial and it can fit many different use needs.

Rodolfo blogging since 2012.