PHPackages                             jesusslim/cain - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. jesusslim/cain

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

jesusslim/cain
==============

mix service &amp; closure to workflow

1.2.0(9y ago)35MITPHPPHP &gt;=5.6.0

Since Jun 13Pushed 9y ago1 watchersCompare

[ Source](https://github.com/jesusslim/cain)[ Packagist](https://packagist.org/packages/jesusslim/cain)[ RSS](/packages/jesusslim-cain/feed)WikiDiscussions master Synced 2w ago

READMEChangelogDependencies (1)Versions (2)Used By (0)

cain
====

[](#cain)

mix service &amp; closure to workflow

install
-------

[](#install)

```
composer require jesusslim/cain

```

example of basic flow
---------------------

[](#example-of-basic-flow)

```
Class Test{

    protected $sid;

    public function __construct($sid)
    {
        $this->sid = $sid;
    }
    public function getNickname(){
        return 'foo'.$this->sid;
    }

    public function getInfo(){
        $id = $this->sid;
        $nickname = $this->getNickname();
        return compact('id','nickname');
    }
}

/*********************************************/
/* the workflows,[class,function] or closure */

$flows = [
    'test_info' => [Test::class,'getInfo'],
    'test_closure' => function($foo){
        return ++$foo;
    }
];

/*********************************************/
/* result_injs will inject the datas of result(or the whole result) to container,so that the next workflow can use them */
/* the key is the keyname in result,the value is the keyname that we want to set to container. */

$result_injs = [
    'test_info' => [
        'id' => 'foo', //means container.foo = result.id
//        \Cain\Flow::PARAMS_NAME_SELF => 'whole'
    ]
];

/*********************************************/
/* result_checkers will check the result,every result_checker should be a closure like function($result){}.*/
/* If check ok,return true,then the next workflow can be run.*/
/* If the return of this closure is not true,the whole workflow will be blocked,and we can use isFinished/isError to check the status,and use getError to get the error info.  */

$result_checkers = [
    'test_closure' => function($result){
        if ($result != 100) return 'bar';
        return true;
    }
];
$fl = new \Cain\Flow($flows,$result_checkers,$result_injs);
var_dump($fl->run(['sid' => 12345]));
var_dump($fl->isFinished());
var_dump($fl->isError());
var_dump($fl->getError());

/*********************************************/
/* use flush to clear status & errors */

$fl->flush();

/*********************************************/
/* use InjectorInterface to get the container */

$fl->flow('test_get_container',function(\Inject\InjectorInterface $injector){
    return $injector->produce('nick');
});

var_dump($fl->run(['sid' => 99]));

```

example of router flow
----------------------

[](#example-of-router-flow)

```
/*********************************************/
/* the workflows,[class,function] or closure */

$flows = [
    'test_info' => [Test::class,'getInfo'],
    'test_closure' => function($foo){
        return ++$foo;
    },
    'math_foo' => function($foo,$bar = 100){
        return $foo * $bar;
    },
    'math_bar' => function($foo,$bar = 100){
        return $foo / $bar;
    },
];

/*********************************************/
/* the routes logic */
/* key is the source route flow key */
/* value is the next route flow key or a Closure that return the next route flow key. */

$routes = [
    'test_info' => 'test_closure',
    'test_closure' => function($foo){
        return $foo % 2 == 1 ? 'math_foo' : 'math_bar';
    }
];

/*********************************************/
/* checkers & injs , same in basic flow */

$result_checkers = [
    'test_closure' => function($result){
        //if ($result != 100) return 'bar';
        var_dump("result is $result");
        return true;
    }
];

$result_injs = [
    'test_info' => [
        'id' => 'foo',
        'nickname' => 'nick',
        //        \Cain\Flow::PARAMS_NAME_SELF => 'whole'
    ]
];

/*********************************************/
/* RouterFlow extends Flow,need routes(workflow routes logic) & root_key(the start flow key) */
/* RouterFlow will return when the workflow blocked by checkers or it can't find the next flow key */

$fl = new \Cain\RouterFlow($flows,$result_checkers,$result_injs,null,$routes,'test_info');
var_dump($fl->run(['sid' => 99]));
$fl->flush();
var_dump($fl->run(['sid' => 100]));

```

###  Health Score

26

—

LowBetter than 41% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity7

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity58

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

3304d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/12554966?v=4)[Slim](/maintainers/jesusslim)[@jesusslim](https://github.com/jesusslim)

---

Top Contributors

[![jesusslim](https://avatars.githubusercontent.com/u/12554966?v=4)](https://github.com/jesusslim "jesusslim (6 commits)")

---

Tags

workflowserviceworkflow

### Embed Badge

![Health badge](/badges/jesusslim-cain/health.svg)

```
[![Health](https://phpackages.com/badges/jesusslim-cain/health.svg)](https://phpackages.com/packages/jesusslim-cain)
```

###  Alternatives

[symfony/workflow

Provides tools for managing a workflow or finite state machine

62944.6M239](/packages/symfony-workflow)[yohang/finite

A simple PHP Finite State Machine

1.3k3.6M10](/packages/yohang-finite)[franzl/studio

Develop your Composer libraries with style

1.1k638.2k16](/packages/franzl-studio)[ecotone/ecotone

Enterprise architecture layer for Laravel and Symfony — CQRS, Event Sourcing, Durable Workflows (Sagas, Orchestrators), Projections, and Outbox messaging via PHP attributes.

562565.8k42](/packages/ecotone-ecotone)[zerodahero/laravel-workflow

Integerate Symfony Workflow component into Laravel.

204864.3k7](/packages/zerodahero-laravel-workflow)[phpmentors/workflower

A BPMN 2.0 workflow engine for PHP

70654.8k4](/packages/phpmentors-workflower)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
