ibrahimgunduz34/maria-bundle

用于 Symfony 项目的规则引擎实现

v0.4-beta 2019-12-14 11:18 UTC

README

Build Status GitHub release License: MIT

什么是 MariaBundle

Maria 是一个简单灵活的业务规则引擎,您可以通过 Bundle 机制轻松将其集成到您的 Symfony 应用程序中。当输入数据匹配时,它允许根据规则执行操作。您可以通过您定义的触发事件来触发 Maria。它通过规则检查通过触发事件传入的输入参数,并在匹配发生时调用操作处理器。操作处理器可能是一个类或指向依赖注入系统中服务定义的引用。因此,您可以通过 Maria 场景中的操作处理器轻松与其他 Symfony 组件进行通信。

安装

您可以通过 composer 安装 Maria

$ composer require ibrahimgunduz34/maria-bundle

根据您的 Symfony 版本将 Bundle 类添加到 Bundle 列表

对于 Symfony 3.x 用户

AppKernel.php

<?php
///...
public function registerBundles()
{
    $bundles = array(
        //...
        new SweetCode\MariaBundle\MariaBundle(),
        //...
    );
}
//...

对于 Symfony >= 4 用户

config/bundles.php

<?php
return [
  //...
   SweetCode\MariaBundle\MariaBundle::class => ['all' => true],
  //...  
];

配置参考

# config/packages/maria.yaml
maria:
    scenarios_name:
      trigger: <The event name you will trigger>
      handler: <Class name or service reference>
#      handler:
#        reference: <Class or service reference from DI>
#        method: <handler method name, default: onAction>
#        serialize: <true | false, default: false>
      rules:
        # You can define matchers as any, all, none, first or last matcher 
        # in the first line. If you won't an iterable object, you can simply
        # use default or ignore the first line. 
        default: # [any | all | none | first | last | default ]
          # You can define rules by numeric or associative arrays.
          
          # Associative arrays indicate that you will apply AND logic between the 
          # elements in the array
          
          # Numeric arrays indicate that you will apply OR logic between the 
          # elements in the array.
          
          # amount > 100 AND category_id IN [1, 2, 3]
          amount: {gt: 100}
          category_id: { in: [1,2,3] }   
          
          # (amount > AND category_id=1) OR (amount < 500 AND category_id IN [5,6])
          - amount: {gt: 100}
            category_id: { eql: 1 }
          - amount: [lt: 500]
            category_id: { in: [5,6] }
            
          # (category_id IN [1,2] AND amount BETWEEN 100-200) OR (category_id = 3 AND amount >= 200
          - amount: { btw: [100, 200] }
            category_id: { in: [1, 2] }
          - amount: [lte: 200]
            category_id: { eql: 3 }
          
          # Matching by RegExp
          - { category_id: { in: [1,5] }, description: { regex: /awesome/i } }                 

另请参阅

示例用法

将以下配置定义到 config/packages/maria.yaml

maria:
    free_shipment:
        trigger: cart.updated
        handler: App\Handler\FreeShipmentHandler
        rules:
          amount: {gt: 100}
          category_id: {eql: 1}

创建一个处理类,以便执行免费配送操作

<?php
namespace App\Handler;

use SweetCode\MariaBundle\MariaEventArg;

class FreeShipmentHandler
{
    public function onAction(MariaEventArg $eventArg){
        //TODO: Write your magic code to give free shipment.
        // You can reach your original input data by:
        // $eventArg->getData();
    }
}

在项目中更新购物车时触发 Maria

<?php
//...
/** @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface $eventDispatcher */
$eventDispatcher = $container->get('event_dispatcher');
// You can simply send an object or associative array to Maria through event context.
$context = [
    'amount'        => $order->getAmount(),
    'category_id'   => $order->getCategoryId(),
]
$eventDispatcher->dispatch(new \SweetCode\MariaBundle\MariaEventArg($context), 'cart.updated');
//...

异步工作方式

Maria 不提供调用操作处理器的方法。然而,您可以通过使用其他第三方工具(如 RabbitMqBundle)或内置的 Symfony 组件(如 Messenger)轻松使操作处理器异步。您可以通过以下步骤使操作处理器异步:

重要提示:我们强烈建议您遵循 rabbitmq-bundle 存储库中的安装步骤:[https://github.com/php-amqplib/RabbitMqBundle](https://github.com/php-amqplib/RabbitMqBundle)

安装 RabbitMqBundle

$ composer require php-amqplib/rabbitmq-bundle

将 Bundle 类添加到项目中的 Bundle 列表

对于 Symfony 3.x 用户

AppKernel.php

<?php
///...
public function registerBundles()
{
    $bundles = array(
        //...
        new OldSound\RabbitMqBundle\OldSoundRabbitMqBundle(),
        //...
    );
}
//...

对于 Symfony >= 4 用户

config/bundles.php

<?php
return [
  //...
   OldSound\RabbitMqBundle\OldSoundRabbitMqBundle::class => ['all' => true],
  //...  
];

配置 RabbitMq Bundle。

# config/packages/rabbitmq.yaml

old_sound_rabbit_mq:
    connections: 
        host: my.rabbitmq.host
        user: rabbitmq
        password: rabbitmq
        vhost: '/'
        lazy: false
        connection_timeout: 3
        read_write_timeout: 3
        keepalive: false
        heartbeat: 0
        use_socket: true
    producers:
        email_producer:
            connection: default
            exchange_options: {name: 'emails', type: direct}
            service_alias: email_producer # otherwise it gives very long service name
    consumers:
      email_consumer:
        exchange_options: {name: 'emails', type: direct}
        queue_options: {name: 'emails'} 
        # That's the service you need to implement as a consumer.
        # Check the documentation from the repository to see how to implement a consumer:
        # https://github.com/php-amqplib/RabbitMqBundle#consumers
        callback: email_sender_service 

然后,告诉 Maria 使用 email_producer 作为操作处理器。

maria:
    gift-email:
        trigger: some.event
        handler: 
          reference: '@email_producer'
          method: 'publish'
          erialize: true
        rules:
          ##...

享受吧!

待办事项

  • 将场景规则移动到不同的存储提供程序,例如 in_memorydoctrine
  • 配置验证改进。

许可证

您可以通过这里访问许可证文档。

鸣谢

Bundle 结构、扩展测试和文档部分受到 RabbitMqBundle 的启发。