vertigolabs/mandate

运行一系列命令

dev-master 2014-08-05 05:35 UTC

This package is auto-updated.

Last update: 2024-09-05 18:43:58 UTC


README

Build Status Coverage Status

一个支持命令优先级、命令链、每个命令多个处理程序和工件的任务队列

Mandate 非常简单易用。

用法

文件

以下是在示例中将要使用的所有文件

NumberCommand.php

<?php

use VertigoLabs\Mandate\Command;

class NumberCommand extends Command
{
    protected $number;
    
    public function __construct($number)
    {
        $this->number = $number;
    }
}

*AddTwoHandler.php

<?php

use VertigoLabs\Mandate\Command;
use VertigoLabs\Mandate\Handler;

class AddTwoHandler extends Handler
{
    public function handle(Command $command)
    {
        if (!is_numeric($command->number)) {
            throw new \InvalidArgumentException('Number must be numeric');
        }

        // we'll just var_dump to get output.. as you should not return data from a handler
        var_dump($command->number + 2);
        
        return true;
    }
}

一个非常基础的例子

用法

按顺序运行命令
$mandate = new \VertigoLabs\Mandate\Mandate();

$addTwoHandler = new AddTwoHandler();

$command1 = new NumberCommand(1);
$command1->addHandler($addTwoHandler);

$command2 = new NumberCommand(2);
$command2->addHandler($addTwoHandler);

$mandate->queue($command1)
	->queue($command2)
    ->execute();

这将产生以下输出

int(3)
int(4)
按优先级运行命令

优先级越高,运行越快

$mandate = new \VertigoLabs\Mandate\Mandate();

$addTwoHandler = new AddTwoHandler();

$command1 = new NumberCommand(1);
$command1->addHandler($addTwoHandler);

$command2 = new NumberCommand(2);
$command2->addHandler($addTwoHandler);

$command3 = new NumberCommand(4);
$command3->addHandler($addTwoHandler);

$mandate->queue($command1,1)
    ->queue($command2,4)
    ->queue($command3,2)
    ->execute();

这将产生以下输出


	int(4)
	int(6)
	int(3)

注意运行顺序是 $command2, $command3, $command1

重用命令

您甚至可以多次重新发布一个命令:优先级越高,运行越快

$mandate = new \VertigoLabs\Mandate\Mandate();

$addTwoHandler = new AddTwoHandler();

$command1 = new NumberCommand(1);
$command1->addHandler($addTwoHandler);

$command2 = new NumberCommand(2);
$command2->addHandler($addTwoHandler);

$command3 = new NumberCommand(4);
$command3->addHandler($addTwoHandler);

$mandate->queue($command1,1)
	->queue($command2,4)
	->queue($command3,2)
	->queue($command2,7)
	->queue($command2,0)
	->execute();

这将产生以下输出

int(4)
int(4)
int(6)
int(3)
int(4)

命令回调

用法

命令可以在成功执行或失败时运行回调函数

闭包作为回调
$command1 = new NumberCommand(1);
$command1->onSuccess(
    function(){
	    echo "Command 1 completed successfully!";
    }
);
$command1 = new NumberCommand(1);
$command1->onFailure(
    function(){
		echo "Oops! I failed :(";
	}
);
方法作为回调
$command1 = new NumberCommand(1);
$command1->onSuccess(['myObject','myMethod'])
	->onFailure(['otherObject','anotherMethod']);

工件

工件仍然是实验性的

传统上,命令/处理程序模式不允许返回值,至少我看到的大多数都不允许,如果我有误,请纠正我。无论如何,Mandate 在“返回数据”方面采取了一种完全不同的方法。

Mandate 使用 工件。工件基本上是从处理程序返回的数据。处理程序会 发出 工件。处理程序可以发出多个工件。每个工件都有一个名称,以便可以访问。

简单工件使用

对于这个例子,您需要另一个处理程序文件

addThreeHandler.php

<?php

use VertigoLabs\Mandate\Command;
use VertigoLabs\Mandate\Handler;

class AddThreeHandler extends Handler
{
    public function handle(Command $command)
    {
        if (!is_numeric($command->number)) {
            throw new \InvalidArgumentException('Number must be numeric');
        }
        
        $sum3 = $command->number + 3;
        var_dump($sum3);
        $this->emitArtifact('sum3', $sum3);
        
        return true;
    }
}

为了允许处理程序发出工件,它应该被“注册”到处理程序的实例中。这是故意的,这样开发者可以在不深入查看处理程序的情况下看到工件已被注册。

$mandate = new \VertigoLabs\Mandate\Mandate();

// set up the handler
$addThreeHandler = new AddThreeHandler();
$addThreeHandler->produceArtifact('sum3');

// set up the command
$command = new NumberCommand(1);
$command->addHandler($addThreeHandler);

$mandate->queue($command)->execute();

var_dump($addThreeHandler->getArtifacts('sum3'));

这将产生以下输出

int(4) // remember the handler has a var_dump also...
int(4)

复杂工件使用

工件的力量在更复杂的情况下使用时才显现出来。

将工件绑定到命令上

假设您有一个依赖于另一个命令/处理程序输出的命令。在这种情况下,您可以绑定工件到命令!

$mandate = new \VertigoLabs\Mandate\Mandate();

// setup the handler
$addThreeHandler = new AddThreeHandler();
$addThreeHandler->produceArtifact('sum3');

// setup the commands
$command1 = new NumberCommand(1);
$command->addHandler($addThreeHandler);

// here we set up our second command to receive the "sum3" artifact
// we'll insert null into the command's constructor since that value is
// the result of command1 being performed by the handler
$command2 = new NumberCommand(null);
$command2->addHandler($addThreeHandler);

// notice the first parameter is the name of the constructor's parameter
// the second parameter is the name of the artifact
$command2->bindArtifact('number','sum3');

$mandate->queue($command1)
	->queue($command2)
	->execute();

这将产生以下输出

int(4)
int(7) // because the result of $command1 is 4, so we added 3!

当发出具有相同名称的新工件时,工件将被覆盖

$mandate = new \VertigoLabs\Mandate\Mandate();

// setup the handler
$addThreeHandler = new AddThreeHandler();
$addThreeHandler->produceArtifact('sum3');

// setup the commands
$command1 = new NumberCommand(1);
$command->addHandler($addThreeHandler);

$command2 = new NumberCommand(null);
$command2->addHandler($addThreeHandler);
$command2->bindArtifact('number','sum3');

$command3 = new NumberCommand(null);
$command3->addHandler($addThreeHandler);
$command3->bindArtifact('number','sum3');

$mandate->queue($command1)
	->queue($command2)
	->queue($command3)
	->execute();

这将产生以下输出

int(4) // the artifact "sum3" is set to 4 at this point
int(7) // the artifact "sum3" is updated to 7 at this point
int(10) // the artifact "sum3" is updated to 10 at this point
等待工件可用

有时工件在运行命令时并不立即可用。对于这种情况,您可以指示命令等待工件可用。

当命令被指示等待工件时,它将自动重新排队到下一个较低优先级级别

$mandate = new \VertigoLabs\Mandate\Mandate();

// setup the handlers
// remember AddTwoHandler does not produce artifacts
$addTwoHandler = new AddTwoHandler();

$addThreeHandler = new AddThreeHandler();
$addThreeHandler->produceArtifact('sum3');

// setup the commands
$command1 = new NumberCommand(null);
$command1->addHandler($addTwoHandler);
$command1->bindArtifact('number','sum3', true);

$command2 = new NumberCommand(2);
$command2->addHandler($addThreeHandler);

$command3 = new NumberCommand(null);
$command3->addHandler($addThreeHandler);
$command3->bindArtifact('number','sum3');

$mandate->queue($command1)
	->queue($command2)
	->queue($command3)
	->execute();

这将产生以下输出

// the "sum3" artifact is not found, requeued $command1
// $command2 is ran and produces "sum3" with a value of 5
int(5)
// now "sum3" is available so command 1 runs
int(7)
// at this point, "sum3" is still available with a value of 5
int(8)
// the artifact "sum3" still exists, however with a value of 8

等待工件的命令将不断重新排队,直到工件可用。当所有可能的命令都耗尽且工件从未产生时,将抛出异常以通知您工件从未找到。