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. jesusslim/cain

ActiveLibrary

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

mix service &amp; closure to workflow

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

Since Jun 13Pushed 8y ago1 watchersCompare

[ Source](https://github.com/jesusslim/cain)[ Packagist](https://packagist.org/packages/jesusslim/cain)[ RSS](/packages/jesusslim-cain/feed)WikiDiscussions master Synced 2d 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 43% 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

3257d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/8c7f383d1fbc7d01247ec7740bc2fe00036335c9227dab341b1fccdd10cfe0f3?d=identicon)[jesusslim](/maintainers/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

[league/container

A fast and intuitive dependency injection container.

86387.8M343](/packages/league-container)[symfony/workflow

Provides tools for managing a workflow or finite state machine

62842.3M170](/packages/symfony-workflow)[yohang/finite

A simple PHP Finite State Machine

1.3k3.5M10](/packages/yohang-finite)[mollie/mollie-api-php

Mollie API client library for PHP. Mollie is a European Payment Service provider and offers international payment methods such as Mastercard, VISA, American Express and PayPal, and local payment methods such as iDEAL, Bancontact, SOFORT Banking, SEPA direct debit, Belfius Direct Net, KBC Payment Button and various gift cards such as Podiumcadeaukaart and fashioncheque.

59914.4M62](/packages/mollie-mollie-api-php)[prettus/laravel-validation

Laravel Validation Service

40710.8M52](/packages/prettus-laravel-validation)[mollie/laravel-mollie

Mollie API client wrapper for Laravel &amp; Mollie Connect provider for Laravel Socialite

3624.1M28](/packages/mollie-laravel-mollie)

PHPackages © 2026

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