1. Go to this page and download the library: Download minfrastructure/chains library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
minfrastructure / chains example snippets
use Minfra\Chains\EventExecutor;
use Minfra\Chains\EventInterface;
use Minfra\Chains\Result;
use Minfra\Chains\Meta;
use Minfra\Chains\BasicResultInterface;
//A simple example with real world application.
class Product {
protected string $price;
function setPrice(string $price): BasicResultInterface {
return EventExecutor::run($this, 'set_price', Meta::make(price: $price), [
EventInterface::ON_MID => [$this, '_set_price'], // or a single hook (any callable)
]);
}
protected function _set_price(Meta $meta): void {
$meta->this->price = $meta->price; // $meta->this refers to the current object.
// We could also do `return true;` or do `Result::true($meta)` or `Result::true()` or `Result::true(<ANYTHING>)`
// when returning true or returning null(or no return at all). it automatically passes the $meta to the next phase.
}
}
// The above example, but even simpler
class Product {
protected string $price;
function setPrice(string $price): BasicResultInterface {
return EventExecutor::run($this, 'set_price', ...CommonEvents::setter(['price' => $price])); // CommonEvents provides wheels for working with properties
}
}
// The same as above example, but with more hooks[pipeline]
class Product {
protected string $price;
function setPrice(string $price): BasicResultInterface {
list($meta, $setter_cb) = CommonEvents::setter(['price' => $price]);
return EventExecutor::run($this, 'set_price', $meta, [
EventInterface::ON_BEFORE => [[$this, "_ensure_correct_price"], [$this, "_ensure_correct_decimal_price"]],
EventInterface::ON_MID => [[$this, "_set_price"]],
EventInterface::ON_OK => fn(Meta $meta) => error_log("price is: {$meta->price}"),
]);
}
protected function _ensure_correct_price(Meta $meta): BasicResultInterface|true {
if (!is_numeric($meta->price)) {
return Result::false("invalid_price", $meta); // Or simply: Result::false("invalid_price");
}
return true; // when returning true. it automatically passes the $meta to the next phase.
}
protected function _ensure_correct_decimal_price(Meta $meta): void {
$meta->price = bcmath($meta->price, '1', 2);
}
protected function _set_price(Meta $meta): void {
$meta->this->price = $meta->price; // $meta->this refers to the current object.
// We could also do `return true;` or do `Result::true($meta)` or `Result::true()` or `Result::true(<ANYTHING>)`
// when returning null(or no return at all). it automatically passes the $meta to the next phase.
}
}
// The same as above example, but make it pluggable(register external callbacks)
use Minfra\Chains\EventExecutor;
use Minfra\Chains\EventInterface;
use Minfra\Chains\CallbackTrait;
use Minfra\Chains\CommonEvents;
use Minfra\Chains\Result;
use Minfra\Chains\BasicResultInterface;
use Minfra\Chains\Meta;
class Product implements \Minfra\Chains\CallbackInterface {
use CallbackTrait;
protected string $price;
protected int $type;
const EVENT_ON_SET_TYPE = "set_type";
const EVENT_ON_GET_TYPE = "get_type";
const EVENT_ON_SET_PRICE = "set_price";
const EVENT_ON_GET_PRICE = "get_price";
function setType(int $type): BasicResultInterface {
return EventExecutor::run($this, static::EVENT_ON_SET_TYPE, ...CommonEvents::setter(['type' => $type]));
}
function getType(): Result {
$type = $this->type ?? null;
return EventExecutor::run($this, static::EVENT_ON_GET_TYPE, ...CommonEvents::getter('type', $type));
}
function setPrice(string $price): BasicResultInterface {
list($meta, $setter_cb) = CommonEvents::setter(['price' => $price]);
return EventExecutor::run($this, static::EVENT_ON_SET_PRICE, $meta, [
EventInterface::ON_BEFORE => [[$this, "_ensure_correct_price"], [$this, "_ensure_correct_decimal_price"]],
EventInterface::ON_MID => [$setter_cb],
EventInterface::ON_OK => fn(Meta $meta) => error_log("price is: {$meta->price}"),
]);
}
function getPrice(): Result {
$price = $this->price ?? null;
return EventExecutor::run($this, static::EVENT_ON_GET_PRICE, ...CommonEvents::getter('price', $price));
}
protected function _ensure_correct_price(Meta $meta): BasicResultInterface|true {
if (!is_numeric($meta->price)) {
return Result::false("invalid_price", $meta); // Or simply: Result::false("invalid_price");
}
return true; // when returning true. it automatically passes the $meta to the next phase.
}
protected function _ensure_correct_decimal_price(Meta $meta): BasicResultInterface|true {
// $meta->price = bcmath($meta->price, '1', 2);
return true;
}
}
$product = new Product();
$product->appendCallback((new \Minfra\Chains\CallbackEntry($product::EVENT_ON_SET_PRICE, \Minfra\Chains\CallbackEntryInterface::EVENT_PRE))->setCallback(function(Meta $meta) {
/** @var Product $product */
$product = $meta->this;
if ($product->getType()->data()->type === 222) {
if ($meta->price > "20") {
return Result::false("invalid_product_222_issue", ['reason' => 'cannot be higher than 20']);
// or if you prefer using meta: return Result::false("invalid_product_222_issue", Meta::make(reason: 'cannot be higher than 20'));
}
}
return true;
}));
$product->appendCallback((new \Minfra\Chains\CallbackEntry($product::EVENT_ON_SET_PRICE, \Minfra\Chains\CallbackEntryInterface::EVENT_POST))->setCallback(function(Meta $meta) {
var_dump("I got the price: {$meta->price}. let's do something with it.");
}));
$product->setType(222);
var_dump($product->setPrice('21')->ok()); // false
var_dump($product->setPrice('19')->ok()); // true
class Order implements CallbackInterface {
use CallbackTrait;
function __construct() {
$this->appendCallback(
(new CallbackEntry('save', 'pre'))
->setCallback(function (Meta $d) {
// validate before save
return true;
}),
(new CallbackEntry('save', 'post'))
->setCallback(function (Meta $d) {
// notify after save
return Result::true($d, completed: true);
}),
);
}
}
$policy = new DefaultEventExecutorPolicy(
jump_on_failure: true, // continue chain after a failed step
jump_on_incomplete: false, // stop on incomplete results
keep_running_on_done: false, // stop when done flag is set
ignore_failed_data_on_jump: true, // don't forward failed data
mark_incomplete_as_failed: true, // treat incomplete as failure
again_limit: 1, // max retries per callback
);
EventExecutor::run($instance, 'event', policy: $policy, ...);
function (Meta $d) {
if ($transientFailure) {
return Result::true($d)->setAgain();
}
return Result::true($d, completed: true);
}
bash
# Run all examples
php examples/run_all.php
# Run a single example
php examples/01_minimal.php
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.