Expression language Symfony live

Expression language Symfony live

A32bed1dd9bd897088eda9637eaf1780?s=128

Hussein Abbas

April 10, 2016
Tweet

Transcript

  1. COIFFARD Xavier ABBAS Hussein Expression language @ Sell Secure

  2. Hussein ABBAS Ingénieur d’études et développement @habbas92 L’accent est Libanais

    Xavier Coiffard Lead Developer SELL SECURE @angezanetti http://angezanetti.com About us
  3. COIFFARD Xavier ABBAS Hussein SellSecure ?

  4. Sell Secure • Lutte contre la fraude à la CB

    sur les stores e- commerce • Start up ! • 4 dev / 4 analystes / 15 enqueteurs / 2 bizdev • MVP ftw!
  5. Sell Secure

  6. • Analyser des centaines de datas • Déclencher un traitement

    statistique • Scorer une transaction: Go/Nogo livraison Un moteur de règle ?
  7. COIFFARD Xavier ABBAS Hussein Historique !

  8. Task force TAAASSK FORCE

  9. Un choix constestable… • Choix de Ruler contestable • Coder

    vite vite • Plus personne après 100 jours
  10. None
  11. • Dette technique • Construire à chaque fois le même

    objet (temps de traitement énorme) • Petit projet opensource Problématiques techniques
  12. Problématiques métiers • Compléxité des règles demandées par le métier

    qui explose • Les métiers écrivent du JSON dans la BDD….
  13. COIFFARD Xavier ABBAS Hussein Et ça marche ?

  14. Un OR et un AND ?… !

  15. ·Petit projet Open Source (pas maintenu, en version bêta)

  16. Des alternatives ?

  17. hallelujah !

  18. COIFFARD Xavier ABBAS Hussein Expression Language

  19. • Component Symfony symfony/expression-language • Evaluer/Compiler des expressions • Basé

    sur l’expression syntaxe de twig • Simple à mettre en place Expression langage
  20. Exemple class Order { public $amount; } $order = new

    Order(); $order->amount = 150;
  21. Exemple class Order { public $amount; } $order = new

    Order(); $order->amount = 150; $language->evaluate( ‘order.amount in 100..200', array( 'order' => $order, ) );
  22. COIFFARD Xavier ABBAS Hussein Ok, mais en vrai ?

  23. Est-ce la bonne solution? • Répond à nos besoins •

    Valider par les métiers • Extensible
  24. public function rulesTreatment($rules, $context, $isbref)
 {
 foreach ($rules as $expression)

    {
 try {
 $return
 = $this->expressionLanguage->evaluate(
 $expression,
 $context
 ); if ($return === true) { //On déclenche la règle }
 } catch (SyntaxError $e) {
 }
 }
 } Implémentation
  25. Surcharge du composant class ExpressionLanguage extends BaseExpressionLanguage
 {
 /**
 *

    @param GetListElementsFunction $elementsList ;the object
 * @param ParserCacheInterface|null $parser
 * @param array $providers
 */
 public function __construct(
 GetListElementsFunction $elementsList,
 ParserCacheInterface $parser = null,
 array $providers = array()
 ) {
 // prepend the default provider to let users override it easily
 array_unshift($providers, $elementsList);
 
 parent::__construct($parser, $providers);
 }
 }
  26. COIFFARD Xavier ABBAS Hussein Avant / Après:

  27. [
 {
 "type": "group",
 "logical": "and",
 "children": [
 {
 "type":

    "condition",
 "variable": "var1",
 "operator": "lists-NotIn",
 "parameter": [
 "2"
 ]
 },
 {
 "type": "condition",
 "variable": "var2",
 "operator": "lists-NotIn",
 "parameter": [
 "3"
 ]
 },
 {
 "type": "condition",
 "variable": "var3",
 "operator": "lists-NotIn",
 "parameter": [
 "4"
 ]
 },
 {
 "type": "condition",
 "variable": "var4",
 "operator": "lists-NotIn",
 "parameter": [
 "5"
 ]
 },
 {
 "type": "condition",
 "variable": "var5",
 "operator": "lists-NotIn",
 "parameter": [
 "6"
 ]
 },
 {
 "type": "condition",
 "variable": "var6",
 "operator": "lists-NotIn",
 "parameter": [
 "15"
 ]
 }
 ]
 }
 ] var1 not in getListElement(2)
 and var2 not in getListElement(3)
 and var3 not in getListElement(4)
 and var4 not in getListElement(5)
 and var5 not in getListElement(6)
 and var6 not in getListElement(15) Les règles:
  28. <?php
 
 
 namespace WS\RESTBundle\Services\jsonBuilder;
 
 use Symfony\Component\DependencyInjection\ContainerInterface as Container;


    use Ruler\RuleBuilder;
 
 /**
 * Class InsertRulesObjectDB
 *
 * @category Treatment_Standard_Data
 * @package WS\RESTBundle\Services\jsonBuilder
 * @author deploiement <deploiement@sellsecure.com>
 * @license copyright SellSecure
 * @version Release: <2.0>
 * @link www.sellsecure.com
 */
 class InsertRulesObjectDB
 {
 private $_container;
 private $_connexion;
 private $_tableTransaction;
 private $_arrayDecisionRuler;
 private $_arrayRulesScoreRuler;
 
 /**
 * Method constructor
 *
 * @param connexion $connexion :connection to database
 * @param Container $container :container object
 */
 public function __construct($connexion, Container $container)
 {
 $this->_container = $container;
 $this->_connexion = $connexion;
 $this->_tableTransaction
 = $this->_container->getParameter('ISB_TRANSACTIONS');
 }
 
 
 /**
 * Insert rules object into DB
 *
 * @return void
 */
 public function insertObjectDB()
 {
 $rules = $this->getRulesFromDB();
 $this->rulesTreatment($rules);
 $this->insertRuleObjectDB($this->_arrayDecisionRuler);
 $this->insertRuleObjectDB($this->_arrayRulesScoreRuler);
 }
 
 
 /**
 * Get all rules from the DB
 *
 * @return Array
 */
 public function getRulesFromDB()
 {
 $sql = 'Select *
 FROM ' . $this->_tableTransaction . '.REGLES
 WHERE version = :version
 AND actif = :actif';
 
 $queryFlux = $this->_connexion->prepare($sql);
 $queryFlux->bindValue("version", 0);
 $queryFlux->bindValue("actif", 1);
 $queryFlux->execute();
 $rules = $queryFlux->fetchAll();
 
 return $rules;
 }
 
 
 /**
 * Separate the rules in 2 categories, for simple rules & decision
 *
 * @param Array $rules :the Array of the rules
 *
 * @return void
 */
 public function rulesTreatment($rules)
 {
 $arrayJsonRuler = array();
 $arrayDecisionRuler = array();
 foreach ($rules as $rule) {
 if ($rule['UTILISATION_SCORE'] == 1) {
 $arrayJsonRuler[]
 = $this->returnArrayRuler(
 $rule['JSON'],
 $rule['EMPLACEMENT'],
 $rule['NOM'],
 $rule['ID'],
 $rule['MOTIF'],
 $rule['SCORE']
 );
 } elseif ($rule['UTILISATION_SCORE'] == 2) {
 $arrayDecisionRuler[]
 = $this->returnArrayRuler(
 $rule['JSON'],
 $rule['EMPLACEMENT'],
 $rule['NOM'],
 $rule['ID'],
 $rule['MOTIF'],
 $rule['SCORE']
 );
 }
 }
 $this->_arrayRulesScoreRuler = $arrayJsonRuler;
 $this->_arrayDecisionRuler = $arrayDecisionRuler;
 }
 
 /**
 * Insert the object of rules into DB
 *
 * @param Array $rules :the json of rules to insert the object
 *
 * @return void;
 */
 public function insertRuleObjectDB($rules)
 {
 $jsonToRuleBuilder
 = $this->_container->get('JsonToRulerBuilder');
 
 foreach ($rules as $rule) {
 $ruleBuilder = new RuleBuilder();
 $parameters
 = $jsonToRuleBuilder->jsonToRuleBuilder(
 $rule,
 $ruleBuilder
 );
 
 
 $serializeRules = serialize($rule);
 $encodeRules = base64_encode($serializeRules);
 
 $serializeParameters = serialize($parameters);
 $encodeParameters = (base64_encode($serializeParameters));
 
 $sql = "DECLARE
 vClobVal varchar2(32767) := '$encodeParameters';
 vClobVal1 varchar2(32767) := '$encodeRules';
 begin ";
 
 $sql .= "UPDATE "
 . $this->_tableTransaction
 . ".REGLES SET PARAMETERS = vClobVal,
 RULES = vClobVal1 WHERE ID = '"
 . utf8_decode($rule[0]['id']) . "'; end;";
 
 
 $query = $this->_connexion->prepare($sql);
 $query->execute();
 }
 }
 
 
 /**
 * Convert the rules into an array
 *
 * @param string $json_ruler :the rule to convert
 * @param string $emplacement :the emplacement of the rule
 * @param string $name :the name of the rule
 * @param string $id :the name of the rule
 * @param string $motif :the motif of the rule
 * @param string $score :the score of the rule
 *
 * @return Array
 */
 public function returnArrayRuler(
 $json_ruler,
 $emplacement = '',
 $name = '',
 $id = '',
 $motif = '',
 $score = ''
 ) {
 $jsonInfosRule
 = ',"emplacement":"'
 . $emplacement
 . '","nom":"'
 . $name
 . '","id":"'
 . $id
 . '","motif":"'
 . $motif
 . '","score":"'
 . $score . '"}]';
 $jsonRuler = substr($json_ruler, 0, -2) . $jsonInfosRule;
 $objectRuler = json_decode($jsonRuler);
 $arrayRuler = json_decode(json_encode($objectRuler), true);
 
 return $arrayRuler;
 }
 }
 Plus de 450 lignes de codes 15 lignes de code Le code : public function rulesTreatment($rules, $context, $isbref)
 {
 foreach ($rules as $expression) {
 try {
 $return
 = $this->expressionLanguage->evaluate(
 $expression,
 $context
 ); if ($return === true) { //On déclenche la règle }
 } catch (SyntaxError $e) {
 }
 }
 }
  29. temps en ms 0 200 400 600 800 Avant Après

    ms ms Les perfs :
  30. One more thing…

  31. COIFFARD Xavier ABBAS Hussein DEMOOO !

  32. Bilan ! • Ca va vite ! • Le métier

    est content • To be continued…
  33. COIFFARD Xavier ABBAS Hussein Questions ?