I'm trying to convert an array to condition-like expression string that will be used in the JS Filtrex library. The JS part is irrelevant for this question.
Following is a sample PHP array that I'm trying to work with.
$condition = array(
'and',
array(
array(
'field' => 'show_image',
'compare' => '==',
'value' => 1
),
),
array(
'or',
array(
'field' => 'filter',
'compare' => '!=',
'value' => 1
),
array(
'field' => 'align',
'compare' => '==',
'value' => 'left'
)
)
);
The resulting string will be something like this :
show_image == 1 and ( filter != 1 or align == "left" )
I'm not sold on the array structure so you're free to modify the array as long as it can be extended with more conditions.
Thanks in advance.
You just need to recurse such a structure, and switch according to the first element:
If it's a string, then treat the remaining arguments as operands/expressions, join
ed by operator
For associative arrays, just concat field/compare/value into a string
For example:
function join_expr($opts) {
if (isset($opts["compare"])) { // optional ↓↓↓ caretaking of value type(!)
return "($opts[field] $opts[compare] '$opts[value]')";
}
elseif (gettype($opts[0]) == "string") {
$op = array_shift($opts);
return join(
" $op ",
array_map("join_expr", $opts) // recurse on operands/subexpressions
);
}
elseif (count($opts) == 1) { // somewhat redundant
return "(" . join_expr($opts[0]) . ")";
}
else {
trigger_error("wrong struct");
}
}
i don't know if it works on all cases, but on yours it works well ( i guess )
what I advise you is to delete the nested array $condition[1]
and write directly $condition[1][0]
array ( the new array structure is in the code below )
<?php
$condition = array(
'and',
array(
'field' => 'show_image',
'compare' => '==',
'value' => 1
),
array(
'or',
array(
'field' => 'filter',
'compare' => '!=',
'value' => 1
),
array(
'field' => 'align',
'compare' => '==',
'value' => 'left'
)
)
);
function generateExpression( Array $condition ) : String
{
return $condition['field'] . " " . $condition['compare'] . " " . $condition['value'];
}
function generateConditionExpression ( Array $conditionTree ) : String
{
if ( array_key_exists("field",$conditionTree) )
{
return generateExpression($conditionTree);
}
//else
return "(" . generateConditionExpression( $conditionTree[1] ) . " " . $conditionTree[0] . " " . generateConditionExpression( $conditionTree[2] ) . ")";
}
echo generateConditionExpression($condition);
One way to do it with nested foreach()
,
<?php
$condition = array(
'AND',
array(
array(
'field' => 'grid_enable',
'compare' => '==',
'value' => 1
),
),
array(
array(
'field' => 'grid_column',
'compare' => '>=',
'value' => 3
),
),
array(
'OR',
array(
'field' => 'filter',
'compare' => '!=',
'value' => 1
),
array(
'field' => 'align',
'compare' => '==',
'value' => 'left'
)
),
array(
array(
'field' => 'grid_gutter',
'compare' => '==',
'value' => 'large'
),
),
);
$final_result = '';
$double = false;
foreach($condition as $k=>$v){
$result = [];
if(!is_array($v)){
$operator_out = $v;
}else{
foreach($v as $k1=>$v1){
if(!is_array($v1)){
$operator_inn = $v1;
}else{
$result[] = implode(' ',array_values($v1));
}
}
}
if(count($result) == 1){
if($double){
$final_result.= " ".$operator_out." ".$result[0];
}else{
$final_result.= $result[0]." ".$operator_out." ";
}
}
else if(count($result) == 2){
$final_result.= "(".implode(" $operator_inn " , $result).")";
$double= true;
}
}
echo $final_result;
?>
DEMO: https://3v4l.org/BWmus