Good day. I would like to know if you can somehow implement the following:

There is an array with parts of the conditions that must be met.

$clauses=array( array( 'clause_name' => 'ext_dna_status', 'clause_sign' => '==', 'clause_value' => 0 ), array( 'clause_name' => 'end_date', 'clause_sign' => '>=', 'clause_value' => '2017-07-20' ) ); 

This array will be passed to the function (not yet written), which will have to check that all the conditions described in the array are met in the array of other data. A separate variable of the function is transferred to separate the parts of the conditions - and, or. Universality from the function is not required - it is designed to simply reduce the number of the same type of code.

For example, a function receives an array with data (below) and a separator at the input. Those. in fact, for each part of the array with data, you need to check each condition from the array with conditions - (I did not translate dates for clarity in unixtime) if ($ext_dna_status==1 and $end_date>=2017-07-20) .

 $in=array( array( 'ext_dna_status' => 0, 'end_date' => '2017-07-20' ), array( 'ext_dna_status' => 1, 'end_date' => '2017-07-20' ), array( 'ext_dna_status' => 0, 'end_date' => '2017-07-25' ) ); 

The question is how to glue together parts of the conditions from the array so that they "work"? You can iterate over all elements of an array with conditions and change the value of a flag variable if the condition is met, for example. But how can parts of a condition be transformed into this very condition? Those. $clause=$clauses[0]['clause_name'].$clauses[0]['clause_sign'].$clauses[0]['clause_value']; treat as a condition ?

  • Comparison operators a limited number of php.net/manual/ru/language.operators.comparison.php . Check clause_sign (in switch , for example) and compare the contents of ['clause_value'] and the element from $in in the corresponding branch of the switch . - Visman
  • But if it is possible to make a variable $ {$ str} from the text, is it possible to do so with the comparison operator? - n.osennij
  • one
    There is, of course, the eval() function php.net/manual/ru/function.eval.php but it is not recommended to use it. - Visman
  • @ n.osennij I liked your task, I solved it through creating an array of functions based on the data from the $clauses array. If interested =) - Andrey Mindubaev
  • @ n.osennij well, and as usual, there is a ready-made library that allows you to reach your goal (I wanted to try it for a long time, my hands did not reach =) - Andrey Mindubaev

2 answers 2

The second solution is to use the symfony/expression-language package.

First you need to install this library through composer require symfony/expression-language

The solution is four lines of code. More versatile solution than any samopisny bicycle.

 <?php require_once __DIR__ . "/vendor/autoload.php"; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; $language = new ExpressionLanguage(); $condition = "ext_dna_status == 0 and end_date >= '2017-07-20'"; 

Here we make up the expression that needs to be processed and evaluated. All this will be done by the object $language

Example of use:

 var_export([ $language->evaluate($condition, [ 'ext_dna_status' => 0, 'end_date' => '2017-07-20' ]), $language->evaluate($condition, [ 'ext_dna_status' => 1, 'end_date' => '2017-07-20' ]), $language->evaluate($condition, [ 'ext_dna_status' => 0, 'end_date' => '2017-07-25' ]), ]); 

Work result

 array ( 0 => true, 1 => false, 2 => true, ) 

    The first solution to the problem is a self-made bike

     <?php class Expression { const CLUE_AND = "and"; const CLUE_OR = "or"; protected $clauses = array(); public static function createInstance() { return new static(); } public function add($name, $sign, $value) { switch ($sign) { case "==": $clause = function(array $data) use ($name, $value) { return $data[$name] == $value; }; break; case ">=": $clause = function(array $data) use ($name, $value) { return $data[$name] >= $value; }; break; default: $clause = function() { return false; }; } $this->clauses[] = $clause; return $this; } public function check(array $data, $clue) { if (!sizeof($this->clauses)) { return null; } if ($clue == self::CLUE_AND) { $check = true; } elseif ($clue == self::CLUE_OR) { $check = false; } else { return null; } foreach ($this->clauses as $clause) { $result = $clause($data); if ($clue == self::CLUE_AND && !$result) { $check = false; break; } elseif ($clue == self::CLUE_OR && $result) { $check = true; break; } } return $check; } } 

    Here, when the add function is called, a new function is added to the list, with only one argument: an array with data. The output function returns a boolean value. There is also a check function that traverses the list of conditions and, depending on the separator and / or, returns and returns the total result.

    Example of use:

     $expr = Expression::createInstance() ->add("ext_dna_status", "==", "0") ->add("end_date", ">=", "2017-07-20"); var_export([ $expr->check([ 'ext_dna_status' => 0, 'end_date' => '2017-07-20' ], Expression::CLUE_AND), $expr->check([ 'ext_dna_status' => 1, 'end_date' => '2017-07-20' ], Expression::CLUE_AND), $expr->check([ 'ext_dna_status' => 0, 'end_date' => '2017-07-25' ], Expression::CLUE_AND), ]); 

    It works only with == and >= , you need to expand the functionality =) Here we create an empty logical expression, add conditions to it and get the result of the work:

     array ( 0 => true, 1 => false, 2 => true, )