A simple stateless production rules engine for PHP 5.3+

Related tags

Architectural Ruler
Overview

Ruler

Ruler is a simple stateless production rules engine for PHP 5.3+.

Package version Build status

Ruler has an easy, straightforward DSL

... provided by the RuleBuilder:

$rb = new RuleBuilder;
$rule = $rb->create(
    $rb->logicalAnd(
        $rb['minNumPeople']->lessThanOrEqualTo($rb['actualNumPeople']),
        $rb['maxNumPeople']->greaterThanOrEqualTo($rb['actualNumPeople'])
    ),
    function() {
        echo 'YAY!';
    }
);

$context = new Context(array(
    'minNumPeople' => 5,
    'maxNumPeople' => 25,
    'actualNumPeople' => function() {
        return 6;
    },
));

$rule->execute($context); // "Yay!"

Of course, if you're not into the whole brevity thing

... you can use it without a RuleBuilder:

$actualNumPeople = new Variable('actualNumPeople');
$rule = new Rule(
    new Operator\LogicalAnd(array(
        new Operator\LessThanOrEqualTo(new Variable('minNumPeople'), $actualNumPeople),
        new Operator\GreaterThanOrEqualTo(new Variable('maxNumPeople'), $actualNumPeople)
    )),
    function() {
        echo 'YAY!';
    }
);

$context = new Context(array(
    'minNumPeople' => 5,
    'maxNumPeople' => 25,
    'actualNumPeople' => function() {
        return 6;
    },
));

$rule->execute($context); // "Yay!"

But that doesn't sound too fun, does it?

Things you can do with your Ruler

Compare things

// These are Variables. They'll be replaced by terminal values during Rule evaluation.

$a = $rb['a'];
$b = $rb['b'];

// Here are bunch of Propositions. They're not too useful by themselves, but they
// are the building blocks of Rules, so you'll need 'em in a bit.

$a->greaterThan($b);                      // true if $a > $b
$a->greaterThanOrEqualTo($b);             // true if $a >= $b
$a->lessThan($b);                         // true if $a < $b
$a->lessThanOrEqualTo($b);                // true if $a <= $b
$a->equalTo($b);                          // true if $a == $b
$a->notEqualTo($b);                       // true if $a != $b
$a->stringContains($b);                   // true if strpos($b, $a) !== false
$a->stringDoesNotContain($b);             // true if strpos($b, $a) === false
$a->stringContainsInsensitive($b);        // true if stripos($b, $a) !== false
$a->stringDoesNotContainInsensitive($b);  // true if stripos($b, $a) === false
$a->startsWith($b);                       // true if strpos($b, $a) === 0
$a->startsWithInsensitive($b);            // true if stripos($b, $a) === 0
$a->endsWith($b);                         // true if strpos($b, $a) === len($a) - len($b)
$a->endsWithInsensitive($b);              // true if stripos($b, $a) === len($a) - len($b)
$a->sameAs($b);                           // true if $a === $b
$a->notSameAs($b);                        // true if $a !== $b

Math even more things

$c = $rb['c'];
$d = $rb['d'];

// Mathematical operators are a bit different. They're not Propositions, so
// they don't belong in rules all by themselves, but they can be combined
// with Propositions for great justice.

$rb['price']
  ->add($rb['shipping'])
  ->greaterThanOrEqualTo(50)

// Of course, there are more.

$c->add($d);          // $c + $d
$c->subtract($d);     // $c - $d
$c->multiply($d);     // $c * $d
$c->divide($d);       // $c / $d
$c->modulo($d);       // $c % $d
$c->exponentiate($d); // $c ** $d
$c->negate();         // -$c
$c->ceil();           // ceil($c)
$c->floor();          // floor($c)

Reason about sets

$e = $rb['e']; // These should both be arrays
$f = $rb['f'];

// Manipulate sets with set operators

$e->union($f);
$e->intersect($f);
$e->complement($f);
$e->symmetricDifference($f);
$e->min();
$e->max();

// And use set Propositions to include them in Rules.

$e->containsSubset($f);
$e->doesNotContainSubset($f);
$e->setContains($a);
$e->setDoesNotContain($a);

Combine Rules

// Create a Rule with an $a == $b condition
$aEqualsB = $rb->create($a->equalTo($b));

// Create another Rule with an $a != $b condition
$aDoesNotEqualB = $rb->create($a->notEqualTo($b));

// Now combine them for a tautology!
// (Because Rules are also Propositions, they can be combined to make MEGARULES)
$eitherOne = $rb->create($rb->logicalOr($aEqualsB, $aDoesNotEqualB));

// Just to mix things up, we'll populate our evaluation context with completely
// random values...
$context = new Context(array(
    'a' => rand(),
    'b' => rand(),
));

// Hint: this is always true!
$eitherOne->evaluate($context);

Combine more Rules

$rb->logicalNot($aEqualsB);                  // The same as $aDoesNotEqualB :)
$rb->logicalAnd($aEqualsB, $aDoesNotEqualB); // True if both conditions are true
$rb->logicalOr($aEqualsB, $aDoesNotEqualB);  // True if either condition is true
$rb->logicalXor($aEqualsB, $aDoesNotEqualB); // True if only one condition is true

evaluate and execute Rules

evaluate() a Rule with Context to figure out whether it is true.

$context = new Context(array(
    'userName' => function() {
        return isset($_SESSION['userName']) ? $_SESSION['userName'] : null;
    }
));

$userIsLoggedIn = $rb->create($rb['userName']->notEqualTo(null));

if ($userIsLoggedIn->evaluate($context)) {
    // Do something special for logged in users!
}

If a Rule has an action, you can execute() it directly and save yourself a couple of lines of code.

$hiJustin = $rb->create(
    $rb['userName']->equalTo('bobthecow'),
    function() {
        echo "Hi, Justin!";
    }
);

$hiJustin->execute($context);  // "Hi, Justin!"

Even execute a whole grip of Rules at once

$hiJon = $rb->create(
    $rb['userName']->equalTo('jwage'),
    function() {
        echo "Hey there Jon!";
    }
);

$hiEveryoneElse = $rb->create(
    $rb->logicalAnd(
        $rb->logicalNot($rb->logicalOr($hiJustin, $hiJon)), // The user is neither Justin nor Jon
        $userIsLoggedIn                                     // ... but a user nonetheless
    ),
    function() use ($context) {
        echo sprintf("Hello, %s", $context['userName']);
    }
);

$rules = new RuleSet(array($hiJustin, $hiJon, $hiEveryoneElse));

// Let's add one more Rule, so non-authenticated users have a chance to log in
$redirectForAuthentication = $rb->create($rb->logicalNot($userIsLoggedIn), function() {
    header('Location: /login');
    exit;
});

$rules->addRule($redirectForAuthentication);

// Now execute() all true Rules.
//
// Astute readers will note that the Rules we defined are mutually exclusive, so
// at most one of them will evaluate to true and execute an action...
$rules->executeRules($context);

Dynamically populate your evaluation Context

Several of our examples above use static values for the context Variables. While that's good for examples, it's not as useful in the Real World. You'll probably want to evaluate Rules based on all sorts of things...

You can think of the Context as a ViewModel for Rule evaluation. You provide the static values, or even code for lazily evaluating the Variables needed by your Rules.

$context = new Context;

// Some static values...
$context['reallyAnnoyingUsers'] = array('bobthecow', 'jwage');

// You'll remember this one from before
$context['userName'] = function() {
    return isset($_SESSION['userName']) ? $_SESSION['userName'] : null;
};

// Let's pretend you have an EntityManager named `$em`...
$context['user'] = function() use ($em, $context) {
    if ($userName = $context['userName']) {
        return $em->getRepository('Users')->findByUserName($userName);
    }
};

$context['orderCount'] = function() use ($em, $context) {
    if ($user = $context['user']) {
        return $em->getRepository('Orders')->findByUser($user)->count();
    }

    return 0;
};

Now you have all the information you need to make Rules based on Order count or the current User, or any number of other crazy things. I dunno, maybe this is for a shipping price calculator?

If the current User has placed 5 or more orders, but isn't "really annoying", give 'em free shipping.

$rb->create(
    $rb->logicalAnd(
        $rb['orderCount']->greaterThanOrEqualTo(5),
        $rb['reallyAnnoyingUsers']->doesNotContain($rb['userName'])
    ),
    function() use ($shipManager, $context) {
        $shipManager->giveFreeShippingTo($context['user']);
    }
);

Access variable properties

As an added bonus, Ruler lets you access properties, methods and offsets on your Context Variable values. This can come in really handy.

Say we wanted to log the current user's name if they are an administrator:

// Reusing our $context from the last example...

// We'll define a few context variables for determining what roles a user has,
// and their full name:

$context['userRoles'] = function() use ($em, $context) {
    if ($user = $context['user']) {
        return $user->roles();
    } else {
        // return a default "anonymous" role if there is no current user
        return array('anonymous');
    }
};

$context['userFullName'] = function() use ($em, $context) {
    if ($user = $context['user']) {
        return $user->fullName;
    }
};


// Now we'll create a rule to write the log message

$rb->create(
    $rb->logicalAnd(
        $userIsLoggedIn,
        $rb['userRoles']->contains('admin')
    ),
    function() use ($context, $logger) {
        $logger->info(sprintf("Admin user %s did a thing!", $context['userFullName']));
    }
);

That was a bit of a mouthful. Instead of creating context Variables for everything we might need to access in a rule, we can use VariableProperties, and their convenient RuleBuilder interface:

// We can skip over the Context Variable building above. We'll simply set our,
// default roles on the VariableProperty itself, then go right to writing rules:

$rb['user']['roles'] = array('anonymous');

$rb->create(
    $rb->logicalAnd(
        $userIsLoggedIn,
        $rb['user']['roles']->contains('admin')
    ),
    function() use ($context, $logger) {
        $logger->info(sprintf("Admin user %s did a thing!", $context['user']['fullName']);
    }
);

If the parent Variable resolves to an object, and this VariableProperty name is "bar", it will do a prioritized lookup for:

  1. A method named bar
  2. A public property named bar
  3. ArrayAccess + offsetExists named bar

If the Variable resolves to an array it will return:

  1. Array index bar

If none of the above are true, it will return the default value for this VariableProperty.

Add your own Operators

If none of the default Ruler Operators fit your needs, you can write your own! Just define additional operators like this:

namespace My\Ruler\Operators;

use Ruler\Context;
use Ruler\Operator\VariableOperator;
use Ruler\Proposition;
use Ruler\Value;

class ALotGreaterThan extends VariableOperator implements Proposition
{
    public function evaluate(Context $context)
    {
        list($left, $right) = $this->getOperands();
        $value = $right->prepareValue($context)->getValue() * 10;

        return $left->prepareValue($context)->greaterThan(new Value($value));
    }

    protected function getOperandCardinality()
    {
        return static::BINARY;
    }
}

Then you can use them with RuleBuilder like this:

$rb->registerOperatorNamespace('My\Ruler\Operators');
$rb->create(
    $rb['a']->aLotGreaterThan(10);
);

But that's not all...

Check out the test suite for more examples (and some hot CS 320 combinatorial logic action).

Ruler is plumbing. Bring your own porcelain.

Ruler doesn't bother itself with where Rules come from. Maybe you have a RuleManager wrapped around an ORM or ODM. Perhaps you write a simple DSL and parse static files.

Whatever your flavor, Ruler will handle the logic.

Comments
  • Add Arithemtic Ops and refactor Base Ops

    Add Arithemtic Ops and refactor Base Ops

    Add these operators: Addition Ceil Division Exponentiate Floor Max Min Modulo Negation Subtraction

    Add these Operator Classes: UnaryOperator BinaryOperator MultipleOperator

    Refactor All existing Operators to extend from one of those bases.

    opened by ludicruz 28
  • Issues with using array_unique() in Set object

    Issues with using array_unique() in Set object

    Suppose you have an array of objects...

    array_unique() casts array items to a string for comparison.

    php docs say:

    Note: Two elements are considered equal if and only if (string) $elem1 === (string) $elem2 i.e. when the string representation is the same, the first element will be used.
    

    So, when your object don't contain a __toString() method, you get an exception:

    PHP Catchable fatal error:  Object of class Domain\User\Role\Role could not be converted to string in /vendor/ruler/ruler/src/Ruler/Set.php on line 48
    

    This happens because the default sort_flag parameter value is SORT_STRING. To prevent this the array_unique() needs the second parameter of SORT_REGULAR added to it.

    benchmarks also show that it's often faster to use a foreach than array_unique... so that might be an option

    opened by jaimz22 15
  • Allow Evaluation of Rules in RuleSet

    Allow Evaluation of Rules in RuleSet

    I needed to simply evaluate the Rules in a RuleSet to see if it was a simple pass or fail for all the Rules in the RuleSet as an atomic group.

    Others might find this handy as well considering the idea that you might have a RuleSet that has no actions.

    Additionally I added a fix for my issue #36

    opened by jaimz22 11
  • initial implementation of set operators

    initial implementation of set operators

    Here is an example of using set operators (from the testComplicated SetTest)

    $rb = new RuleBuilder();
    $context = new Context(array(
        'expected' => 'a',
        'foo' => array('a', 'z'),
        'bar' => array('z', 'b'),
        'baz' => array('a', 'z', 'b', 'q'),
    ));
    
    $rb->create(
        $rb['foo']->intersect(
            $rb['bar']->symmetricDifference($rb['baz'])
        )->setContains($rb['expected']),
        function () {
            echo "awesome sauce!\n";
        }
    )->execute($context);
    

    Also, I switched up the contains operator a bit. (I wasn't using it before and otherwise I would have said something :) )

    I think it makes sense to keep the builder contains operators as (haystack, needle) for both even though the underlying implementations, strpos and in_array, are different. this way when you're using the builder it makes more semantic sense:

    $rb['haystack']->setContains($rb['needle']);
    $rb['haystack']->stringContains($rb['needle']);
    
    opened by ludicruz 11
  • Introduce ObjectVariable to allow accessing members of property

    Introduce ObjectVariable to allow accessing members of property

    I've hacked around integrating Ruler with a DSL and came across the requirement to access properties of objects. Here is a hack to do it: https://github.com/lstrojny/RuleDSL/blob/master/src/RuleDSL/Language/Compiler/RulerCompiler.php

    Questions are:

    • Is that something that belongs in Ruler?
    • Should we reuse PropertyPathUtil (https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Form/Util/PropertyPath.php)
    • What about inflection of property and object names (and variable names in general). Is that something that belongs in Ruler core or anywhere else?
    opened by lstrojny 9
  • Class 'Blade' not found

    Class 'Blade' not found

    I just installed ruler package via composer in one of my existing laravel project and it works great. But when i installed in lumen project then upon starting lumen server that is 'php artisan serve' from terminal then it gives error following error :

    PHP Fatal error: Class 'Blade' not found in /var/www/html/test/vendor/zizaco/entrust/src/Entrust/EntrustServiceProvider.php on line 63 [Symfony\Component\Debug\Exception\FatalErrorException]
    Class 'Blade' not found

    Any help would be appreciated.Thanks!

    opened by sakshidebut 6
  • Allow external operator use

    Allow external operator use

    Allowing to implement specific operators using Ruler API and store them in a specific namespace. Implementation can surely be improved.

    Maybe I didn't undersand well how to bring my porcelain :)

    opened by tophsic 6
  • Need help run without namespace use

    Need help run without namespace use

    I have one project which run in cakephp, my problem is i will not use namespace in this project because cakephp doesn't support namepsace. so how can i run rule engine in this project .

    Thanks

    opened by nikunjshingala 5
  • PHP Fatal error:  Class 'Context' not found in line number new Context

    PHP Fatal error: Class 'Context' not found in line number new Context

    Following are the changes made to Context.php, Pimple.php and application: But still failing as: PHP Fatal error: Class 'Context' not found in line number new Context

    Follwoing changes in Context: Added required once for Pimple Removed backslash on Pimple extends

    namespace Ruler; require_once("....../Ruler/Pimple.php");

    /**

    • Ruler Context. *
    • The Context contains facts with which to evaluate a Rule or other Proposition. *
    • @author Justin Hileman [email protected] */ class Context extends Pimple

    Follwoing changes in Pimple Added namespace Added backslash on ArrayAccess implements

    namespace Ruler; /**

    • Pimple main class. *
    • @package pimple
    • @author Fabien Potencier */ class Pimple implements \ArrayAccess

    Following is change in application php:

    include("Ruler/RuleBuilder.php"); include("Ruler/Variable.php"); include("Ruler/RuleBuilder/Variable.php"); include("Ruler/Proposition.php"); include("Ruler/Rule.php"); include("Ruler/Operator/ComparisonOperator.php"); include("Ruler/Operator/NotEqualTo.php"); //include("Ruler/Pimple.php"); require("Ruler/Context.php"); use Ruler\RuleBuilder; use Ruler\Operator;

    function evalExpression($lhs, $operator, $rhs) {
    
        $rb = new RuleBuilder;
    
        $LHS = $rb['LHS'];
        $RHS = $rb['RHS'];
    
        $expressionValue = false;
    
        switch ($operator) {
                case "=":
                        $expression = $rb->create($LHS->equalTo($RHS));
                        $context = new Context(array( 'LHS' => $lhs, 'RHS' => $rhs));
                        $expressionValue = $expression->evaluate($context);
                        break;
                case "<>":
                        $expression = $rb->create($LHS->notEqualTo($RHS));
                        $context = new Context(array( 'LHS' => $lhs, 'RHS' => $rhs));
                        $expressionValue = $expression->evaluate($context);
                        break;
                case ">=":
                        $expression = $rb->create($LHS->greaterThanOrEqualTo($RHS));
                        $context = new Context(array( 'LHS' => $lhs, 'RHS' => $rhs));
                        $expressionValue = $expression->evaluate($context);
                        break;
        }
    
        return $expressionValue;
    
    
    }
    

    Please help.

    opened by snrsamy 4
  • Errbacks anybody?

    Errbacks anybody?

    Not sure if this has been discussed already, but it seems that the rule object would benefit from having a error callback (errback) in addition to its success callback. Currently, we evaluate a rule and if it evaluates to true we call our function, but if it evaluates to false we get crickets. This is great when developing a rewards system where its all or nothing, but leaves a bit to be desired when you care about the false response and the reason behind it. Think about a mortgage application system (not that I'm building one anytime soon) where you configure a gauntlet of conditions in front of a loan approval. If the loan is approved, great, where do I sign? But if the loan is denied a user may wish to know which conditions caused the denial or at least trigger some form of action based on it (i.e. offer additional credit products, log failed applications, etc). Thoughts?

    opened by malaney 4
  • Using Ruler in CodeIgniter application

    Using Ruler in CodeIgniter application

    I am trying to use the Ruler library in my CodeIgniter but it doesn't seem to work. I installed Ruler library using composer and configured composer to work with code igniter as defined in these links. In my controller, I created a new function and added the sample code to echo "YAY". But I get the error that RuleBuilder cannot be resolved. Would appreciate your help in guiding me to get Ruler working. Thanks http://codesamplez.com/development/composer-with-codeigniter

    https://philsturgeon.uk/php/2012/05/07/composer-with-codeigniter/

    opened by sidgitind 3
  • Create a Set of Rules and use it within the project

    Create a Set of Rules and use it within the project

    Looking at the examples, I realized that the rules are created and executed within a function. The variables of the rules are passed as input to the function. How can I separate the creation of Rules and Execution of rules. I want to have a set of library of Rules design for my flows and then use them in the project as per the need. This is what I am trying to do and its not working...The Rule in the Demo function is not executed.

    class Test_Controller extends CI_Controller { public function demo() { echo "demo"; $rb = new RuleBuilder; $rule = $rb->create( $rb->logicalAnd( $rb['minNumPeople']->lessThanOrEqualTo($rb['actualNumPeople']), $rb['maxNumPeople']->greaterThanOrEqualTo($rb['actualNumPeople']) ), function() { echo 'YAY!'; } ); }

    public function test()
    {
    $context = new Context(array(
        'minNumPeople' => 5,
        'maxNumPeople' => 25,
        'actualNumPeople' => function() {
        return 6;
        },
        ));
    //echo "test";
    
    $rule->execute($context); 
    }
    

    }

    Thanks.

    opened by sidgitind 0
  • Make it possible to use nested/shared sub-rules inside context

    Make it possible to use nested/shared sub-rules inside context

    NOT READY TO BE MERGED as the code isn't fully tested and there are no test cases or documentation for it yet.

    This feature allows you to create sub-rules as variables and use those to build new rules. Those sub-rules are only compiled once (into true/false) and are very useful if you have a large set of different rules that get used in multiple locations.

    opened by mahagr 4
  • Incompatibilities between 0.2.0 and 03.0

    Incompatibilities between 0.2.0 and 03.0

    I recently attempted to upgrade from 0.2.0 to 0.3.0 and found that the contains operators are incompatible because the argument orders are reversed.

    This code dumps "true" for version 0.2.0 and "false" for version 0.3.0:

    $haystack = new \Ruler\Variable('haystack');
    $needle = new \Ruler\Variable('needle');
    
    $rule = new Ruler\Rule(new Ruler\Operator\LogicalAnd([
            new Ruler\Operator\Contains($needle, $haystack)
        ])
    );
    
    $context = new \Ruler\Context([
        'haystack' => 'The quick brown fox',
        'needle' => 'quick',
    ]);
    var_dump($rule->evaluate($context));
    

    I realize that in 0.3.0 the contains operator is deprecated. If I replace the contains operator usage above with StringContains, false instead of true is dumped out. The difference appears to be in the class Value and how strpos is called: https://github.com/bobthecow/Ruler/blob/v0.2.0/src/Ruler/Value.php#L73 https://github.com/bobthecow/Ruler/blob/v0.3.0/src/Ruler/Value.php#L92

    I suspect part of the issue is the ambiguity of left/right - clearly the author in 0.2.0 had one idea and the author of 0.3.0 had a different idea about what left/right meant. It would be helpful to clarify this in the documentation and to note the incompatibility so that would be upgraders won't be in for an unpleasant surprise.

    opened by robap 0
  • More practical example

    More practical example

    Hi Justin,

    Would you like to help me? I need your help to understand your rule builder project. I also had to read http://jwage.com/post/31292541379/ruler-a-simple-stateless-production-rules-engine but still not have clear understanding.

    I have case study. My case study is managing large parameters ($_GET) for my search process in my app. How can i use rule builder to solve my case study? Would you like to give me more more practical example using rule builder ?

    Thank You :)

    opened by okaprinarjaya 0
  • Rules language

    Rules language

    Would be awesome if Ruler could do something similar to https://github.com/hoaproject/Ruler, where rules can be defined like so:

    'group in ["customer", "guest"] and points > 30'
    

    This would allow storage of rules within databases or other formats.

    opened by milosdakic 3
  • Result back from the function in the Rule.

    Result back from the function in the Rule.

    Would be nice to have the result back from the function in the Rule. not really an issue but it makes the Ruler more complete :)

    $rb = new RuleBuilder; $rule = $rb->create( $rb->logicalAnd( $rb['minNumPeople']->lessThanOrEqualTo($rb['actualNumPeople']), $rb['maxNumPeople']->greaterThanOrEqualTo($rb['actualNumPeople']) ), function() { return 'YAY!'; } ); $context = new Context(array( 'minNumPeople' => 5, 'maxNumPeople' => 25, 'actualNumPeople' => function() { return 6; }, )); echo $rule->execute($context); // "Yay!"

    this does not work. but if you change line in Rule.php;

    public function execute(Context $context) { if ($this->evaluate($context) && isset($this->action)) { if (!is_callable($this->action)) { throw new \LogicException('Rule actions must be callable.'); }

            **return** call_user_func($this->action);
        }
    
    opened by yayabla 0
Releases(v0.4.0)
  • v0.4.0(Jun 27, 2022)

    Ruler v0.4 improves support for modern PHP. It is API compatible with v0.3.x, and should be a drop-in replacement other than...

    • Drops support for PHP < 7.4. Thanks @DemigodCode!
    • Updated, more complete, types.
    • Deprecated Contains Operator has been removed (in favor of StringContains and SetContains Operators).
    Source code(tar.gz)
    Source code(zip)
  • v0.3.1(Jun 26, 2022)

    • Switch from Travis to GitHub Actions. Thanks @davidmpaz!
    • Fix warnings in PHP7.2+. Thanks @mjrider!
    • Better test and composer.json config. Thanks @peter279k and @flavius!
    • Support StringContainsInsensitive in rulebuilder API. Thanks @ttrajanov-modus!
    • Better Set operations for objects! Thanks @ludicruz!
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Sep 2, 2014)

    • Add Set and Arithmetic Operators. Thanks @ludicruz!
    • Allow registering custom Operators. Thanks @tophsic!
    • Add StartsWith and EndsWith Operators. Thanks @gogume!
    • Add case-insensitive string comparison Operators.
    • Remove dependency on Pimple.
    • Deprecate Contains Operator in favor of discrete StringContains and SetContains Operators.
    Source code(tar.gz)
    Source code(zip)
Owner
Justin Hileman
Justin Hileman
A simple Monad library for PHP

MonadPHP This is a basic Monad library for PHP. Usage Values are "wrapped" in the monad via either the constructor: new MonadPHP\Identity($value) or t

Anthony Ferrara 283 Dec 29, 2022
sample code for several design patterns in PHP 8

DesignPatternsPHP Read the Docs of DesignPatternsPHP or Download as PDF/Epub This is a collection of known design patterns and some sample codes on ho

null 21k Jan 1, 2023
Primitives for functional programming in PHP

Functional PHP: Functional primitives for PHP NOTE: functional-php used to come with a C extension that implemented most of the functions natively. As

Lars Strojny 1.9k Jan 3, 2023
Option Type for PHP

PHP Option Type This package implements the Option type for PHP! Motivation The Option type is intended for cases where you sometimes might return a v

Johannes 2.4k Dec 26, 2022
Powerful implementation of the Specification pattern in PHP

RulerZ The central idea of Specification is to separate the statement of how to match a candidate, from the candidate object that it is matched agains

Kévin Gomez 865 Dec 22, 2022
Stateless HTTP basic auth for Laravel without the need for a database.

Laravel Very Basic Auth Documentation available in: ???? English ???? 日本語 This package allows you to add a HTTP Basic Auth filter on your routes, with

Marcus Olsson 141 Dec 31, 2022
Manage redirects using database rules. Rules are intended to be very similar to Laravel default routes, so syntax is pretty easy to comprehend.

Laravel DB redirector Manage HTTP redirections in Laravel using database Manage redirects using database rules. Rules are intended to be very similar

Vladimir Ković 12 Jul 18, 2022
Phpcs-magento-rules - A set of PHPCS rules used by made.com when hacking Magento

Made.com PHPCS Magento Rules A set of PHPCS rules used by made.com when hacking Magento. Pre-Requisites PHPCS Installation Short Version Clone this re

Made.com Tech Team 26 Jun 3, 2020
Production-ready, stable Kafka client for PHP

PHP Kafka client - php-rdkafka PHP-rdkafka is a stable, production-ready, long term support, and fast Kafka client for PHP based on librdkafka. It sup

Arnaud Le Blanc 1.9k Dec 26, 2022
Rori-PHP is custom non production web application framework inspired by Laravel syntax

Rori-PHP is custom non production web application framework inspired by Laravel syntax. A web framework provides a structure and starting point for your application allowing you to focus on creating something amazing.

UnknownRori 5 Jul 28, 2022
Rubix Server is a library for bringing your trained Rubix ML models into production.

Rubix Server is a library for bringing your trained Rubix ML models into production. Inference servers are stand-alone services that run on your private or public network and wrap your trained estimator in an API that can be queried locally or over the network in real-time using standard protocols. In addition, the library provides async-compatible client implementations for making queries to the server from your PHP applications.

Rubix 50 Aug 15, 2022
Contracts for Rule Doc Generator. Useful for production code with minimum dependencies.

Rule Doc Generator Contracts Contracts for Rule Doc Generator. Useful for production code with minimum dependencies. Install composer require symplify

null 19 Dec 22, 2022
Assets Manager for "Vitewind" Theme, will inject CSS and JS assets for "Vitewind" theme to work properly with viteJS in development and production

Vitewind Manager plugin ?? Windi CSS and ⚡️ Vite, for ?? OctoberCMS & ❄️ WinterCMS Introduction This is a helper plugin for ?? Vitewind theme, don't i

Adil Chehabi 4 May 29, 2022
Production ready Dockerfile for Octane powered Laravelish web services and microservices

Laravel Octane Dockerfile A pretty configurable and production ready multi-stage Dockerfile for Octane powered Laravelish web services and microservic

Exalab.co 245 Dec 26, 2022
Production Ready, Carefully Crafted, Extensive Vuejs Laravel Free Admin Template 🤩

Materio - Vuetify VueJS Laravel Free Admin Template Production ready carefully crafted most comprehensive admin template Introduction If you’re a deve

ThemeSelection 115 Dec 13, 2022
Production-grade rapid controller development with built in love for API and Search

Installation For CakePHP 4.x compatible version: composer require friendsofcake/crud For CakePHP 3.x compatible version: composer require friendsofca

Friends Of Cake 357 Jan 2, 2023
PaaS template based on production template using platform.sh

Shopware for Platform.sh This template builds Shopware on Platform.sh using Composer. To get started on Platform.sh, please visit https://docs.platfor

Shopware 9 Oct 12, 2022
Production ready scalable Magento setup utilizing the docker

Magento docker image Requirements This docker image expects 2 other linked containers to work . Mysqldb or Mariadb linked as 'db' Memcached linked as

Paim pozhil 49 Jun 21, 2021
A dockerized magento 2 community environment ready for development or production.

Painless Magento 2 & 1 A dockerized magento 2 community environment ready for development or production. It supports magento 1.9.x for development Ins

Cocoa Web Studio 10 Apr 23, 2022
Prevents development packages from being added into require and getting into production environment.

production-dependencies-guard Prevents development packages from being added into require and getting into production environment. In practical field

Vladimir Reznichenko 88 Oct 21, 2022