rocket-php/rocket-rule

Installs: 23

Dependents: 2

Suggesters: 0

Security: 0

Stars: 0

Watchers: 1

Forks: 0

Open Issues: 0

pkg:composer/rocket-php/rocket-rule

v1.0.60 2025-10-14 12:14 UTC

README

Quality Gate Status Bugs Code Smells Coverage Lines of Code Maintainability Rating Reliability Rating Security Rating

RocketRule

RocketRule est un moteur de règles et de workflows écrit en PHP. Il permet de décrire, d'exécuter et de superviser des processus métier à l'aide d'un DSL lisible et d'actions extensibles. Le moteur s'appuie sur une définition JSON unique qui centralise règles, étapes et actions.

Sommaire

  • Aperçu
  • Installation
  • Première exécution
  • Structure d'un workflow
  • Catalogue d'actions
  • DSL des conditions
  • Types d'étapes
  • Contexte et sorties
  • Extensibilité
  • Tests et qualité
  • Licence

Aperçu

RocketRule cible les cas d'usage où la logique métier doit être configurée plutôt que codée en dur : segmentation client, campagnes marketing, vérifications réglementaires, automatisations internes. Chaque workflow est décrit dans un document JSON qui associe un jeu de règles à exécuter, les actions à invoquer et les conditions qui pilotent le cheminement.

Caractéristiques principales :

  • Description déclarative des workflows et des règles.
  • DSL de conditions riche, couvrant l'arithmétique, les dates, les tableaux et les combinaisons logiques.
  • Catalogue d'actions prêtes à l'emploi (mathématiques, manipulation d'objets, journalisation, appels externes, etc.) et possibilité d'en ajouter.
  • Étapes séquentielles, conditionnelles, parallèles et de boucle.
  • Contexte partagé passé par référence et mis à jour au fil de l'exécution.

Installation

  1. Prérequis : PHP 8.1 ou supérieur et Composer.
  2. Ajouter la dépendance :
    composer require rocketphp/rocketrule
  3. Optionnel : installer PHPUnit pour exécuter la suite de tests incluse.

Première exécution

L'exemple suivant illustre un workflow minimal qui incrémente l'âge d'un utilisateur lorsque la condition est satisfaite.

use RocketPhp\RocketRule\WorkflowEngine;

$workflowDefinition = <<<'JSON'
{
    "workflow": {
        "rules": [
            {
                "name": "Validation KYC",
                "description": "Vérifie que l'utilisateur a fourni les pièces requises avant d'activer son compte",
                "condition": "((kyc.status,'==','pending') AND (kyc.documents,'all',{status,'==','validated'}))",
                "true_step": {
                    "steps": [
                        {
                            "action": "ObjectAction",
                            "field": "kyc.status",
                            "operation": "set",
                            "value": "approved"
                        },
                        {
                            "action": "ExternalAction",
                            "external_action": "App\\Notification\\SendEmail",
                            "data": {
                                "template": "KYC_APPROVED",
                                "subject": "Votre compte est activé"
                            }
                        }
                    ]
                }
            }
        ]
    }
}
JSON;

$context = [
    'email' => 'client@example.com',
    'kyc' => [
        'status' => 'pending',
        'documents' => [
            ['type' => 'id_card', 'status' => 'validated'],
            ['type' => 'proof_of_address', 'status' => 'validated']
        ]
    ]
];

$engine = new WorkflowEngine($workflowDefinition, $context);
$engine->execute();

// $context['kyc']['status'] vaut désormais "approved"

Structure d'un workflow

Un workflow est décrit par un document JSON composé de deux sections principales :

  • actions (optionnel) : dictionnaire d'actions réutilisables par nom.
  • rules : liste de règles évaluées dans l'ordre. Chaque règle contient :
    • name et description (facultatifs mais recommandés).
    • condition : expression DSL évaluée sur le contexte.
    • true_step et false_step : étapes à exécuter selon le résultat de la condition.

Exemple complet

{
  "workflow": {
    "actions": {
      "enrichUser": {
        "action": "ObjectAction",
        "field": "profile.tags",
        "operation": "push",
        "value": "vip"
      },
      "notify": {
        "action": "ExternalAction",
        "external_action": "App\\Notification\\SendSms",
        "data": {"template": "WELCOME"}
      }
    },
    "rules": [
      {
        "name": "Clients fidèles",
        "condition": "((orders.sum,'>=',500) AND (country,'==','FR'))",
        "true_step": {
          "type": "WhileStep",
          "condition": "(pendingTodos,'not empty',true)",
          "steps": ["enrichUser", "notify"]
        },
        "false_step": {
          "steps": [
            {
              "action": "LogAction",
              "field": "audit",
              "operation": "info",
              "value": "Client non éligible"
            }
          ]
        }
      }
    ]
  }
}

Réutilisation des actions

Une action définie dans workflow.actions peut être référencée dans n'importe quel bloc steps par son nom. Les actions définies inline via un tableau associatif sont instanciées à la volée.

Catalogue d'actions

Action Description rapide Paramètres principaux
MathAction Opérations arithmétiques (add, subtract, multiply). field, operation, value
ObjectAction Manipulation de structures (set, unset, push, merge, etc.). field, operation, value
LogAction Enregistre ou signale des messages (info, warning, exception). field, operation, value
ExternalAction Appelle une classe externe disposant d'une méthode execute. external_action, data
MethodAction Appelle une méthode sur une classe métier ou un service. method, arguments
EntityAction Opérations orientées entités (selon vos implémentations). field, operation, value
GenericAction Point d'extension générique pour vos besoins spécifiques. dépend de votre implémentation

Chaque action reçoit : le contexte (par référence), l'indice de l'action dans l'étape et la sortie précédente (previousOutput) si nécessaire.

DSL des conditions

Le DSL se présente sous la forme (champ, 'operateur', valeur) ou combinaisons logiques.

Champs et valeurs

  • Les champs peuvent cibler des chemins imbriqués : profile.address.city.
  • Référence au contexte courant : @champ.
  • Référence au contexte système : SYS:variable.
  • Les valeurs peuvent être : entiers, chaînes (entre quotes), booléens (true / false), tableaux ([val1,val2]) ou sous-conditions ({ ... }).

Opérateurs principaux

Type Opérateurs
Comparaisons ==, ===, !=, >, <, >=, <=
Collections in, not in, any, all, none, length, greater than length, less than length, unique
Chaînes contains, does not contain, starts with, ends with, like, not like, regex, not regex
Dates before, after, between, between dates, within, date equals, day of week
Nombres mod, even, odd, within range, sum, average, min, max
Divers is null, is not null, empty, not empty, implies

Combinaisons logiques

  • AND, OR et NOT peuvent envelopper n'importe quelle condition.
  • Les sous-conditions pour any, all, none se décrivent entre accolades : {field,'==','value'}.

Types d'étapes

Étape Usage principal
Step Exécute une liste d'actions séquentielles.
ConditionalStep Évalue une condition interne et route vers un sous-step vrai/faux.
WhileStep Répète les actions tant que la condition reste vraie.
UntilStep Répète jusqu'à ce que la condition devienne vraie.
SwitchStep Sélectionne un ensemble d'actions selon une valeur de référence.
ParallelStep Lance plusieurs branches en parallèle via Fibers PHP.

Chaque étape reçoit le contexte partagé. Les étapes retournent un tableau d'outputs cumulés si leurs actions en produisent.

Contexte et sorties

  • Le contexte fourni au moteur est passé par référence : toutes les modifications sont visibles après exécution.
  • Les actions peuvent s'appuyer sur l'argument $previousOutput pour accéder au résultat de l'action précédente.
  • En cas d'exception non interceptée dans une action, l'étape capture l'erreur et pousse ['exception' => message] dans sa sortie.

Extensibilité

Ajouter une action personnalisée

  1. Étendre RocketPhp\RocketRule\Action\Action.
  2. Implémenter la méthode execute(&$context, $actionIndex, $previousOutput).
  3. Ajouter la classe à votre autoloader et référencer son nom dans la définition JSON.
namespace App\Workflow\Action;

use RocketPhp\RocketRule\Action\Action;

class SendEmailAction extends Action
{
    public function execute(&$context, $actionIndex = 1, $previousOutput = null): void
    {
        // Votre logique d'envoi d'e-mail ici
    }
}

Étendre le DSL

Les opérateurs du DSL sont centralisés dans Condition et ConditionBuilder. Vous pouvez les enrichir en ajoutant vos propres opérateurs ou en dérivant la logique de résolution de valeurs.

Tests et qualité

La suite de tests PHPUnit illustre les capacités du moteur et sert de garde-fou lors de vos évolutions.

./vendor/bin/phpunit

Vous pouvez également intégrer phpunit-watcher (configuration fournie) pour lancer automatiquement les tests.

Licence

Ce projet est distribué sous licence MIT. Consultez LICENSE pour plus de détails.