Search code examples
phparraysrecursionmultidimensional-array

Simplify a multidimensional array of filtering conditions using recursion


I have this array

Array
(
    [condition] => AND
    [rules] => Array
        (
            [0] => Array
                (
                    [type] => query-builder-rule
                    [query] => Array
                        (
                            [id] => transactionDate
                            [field] => transactionDate
                            [type] => date
                            [input] => datepicker
                            [operator] => equal
                            [value] => 2017-05-02 00:00 - 2017-05-03 00:00
                            [rule] => transactionDate
                        )

                )

            [1] => Array
                (
                    [type] => query-builder-group
                    [query] => Array
                        (
                            [condition] => OR
                            [rules] => Array
                                (
                                    [0] => Array
                                        (
                                            [type] => query-builder-rule
                                            [query] => Array
                                                (
                                                    [id] => firstname
                                                    [field] => firstname
                                                    [type] => string
                                                    [input] => text
                                                    [operator] => equal
                                                    [value] => Doe
                                                    [rule] => firstname
                                                )

                                        )

                                    [1] => Array
                                        (
                                            [type] => query-builder-rule
                                            [query] => Array
                                                (
                                                    [id] => lastname
                                                    [field] => lastname
                                                    [type] => string
                                                    [input] => text
                                                    [operator] => equal
                                                    [value] => Doe
                                                    [rule] => lastname
                                                )

                                        )

                                    [2] => Array
                                        (
                                            [type] => query-builder-rule
                                            [query] => Array
                                                (
                                                    [id] => email
                                                    [field] => email
                                                    [type] => string
                                                    [input] => text
                                                    [operator] => equal
                                                    [value] => Doe
                                                    [rule] => email
                                                )

                                        )

                                )

                        )

                )

        )

)

I need this transformed into this array

Array
(
    [condition] => AND
    [rules] => Array
        (
        [0] => Array
                (
                    [id] => transactionDate
                    [field] => transactionDate
                    [type] => date
                    [input] => datepicker
                    [operator] => equal
                    [value] => 2017-05-02 00:00 - 2017-05-03 00:00
                    [rule] => transactionDate
            )

            [1] => Array
                (
                    [condition] => OR
                    [rules] => Array
                        (
                            [0] => Array
                                (
                                    [id] => firstname
                                    [field] => firstname
                                    [type] => string
                                    [input] => text
                                    [operator] => equal
                                    [value] => Doe
                                    [rule] => firstname
                                )

                            [1] => Array
                                (
                                    [id] => lastname
                                    [field] => lastname
                                    [type] => string
                                    [input] => text
                                    [operator] => equal
                                    [value] => Doe
                                    [rule] => lastname
                                )

                            [2] => Array
                                (
                                    [id] => email
                                    [field] => email
                                    [type] => string
                                    [input] => text
                                    [operator] => equal
                                    [value] => Doe
                                    [rule] => email
                                )

                        )

                )



        )

)

I am trying to do this recursively but i hit the wall.

My current code is this but it's not really correct.

public function transform($request)
{
    $request = json_decode($request, true);

    foreach ($request as $key => $value) {
        if ($key == 'rules') {
            foreach ($value as $rKey => $rValue) {
                if (!is_array($rValue['query']['rules'])) {
                    $this->parsedRequest[$key] = $rValue['query'];
                } else {
                    $this->transform(json_encode($rValue['query']));
                }
            }
        }

        $this->parsedRequest[$key] = $value;
    }
}

This just overwrites existing values. I can't get my head around it. I tried using array_walk_recursive but i couldn't get it to work. Any help is appreciated.

P.S. I need this recursively because i don't know how much layers will there be. These arrays are only examples.

EDIT: var_export

first array:

array ( 'condition' => 'AND', 'rules' => array ( 0 => array ( 'type' => 'query-builder-rule', 'query' => array ( 'id' => 'transactionDate', 'field' => 'transactionDate', 'type' => 'date', 'input' => 'datepicker', 'operator' => 'equal', 'value' => '2017-05-02 00:00 - 2017-05-03 00:00', 'rule' => 'transactionDate', ), ), 1 => array ( 'type' => 'query-builder-group', 'query' => array ( 'condition' => 'OR', 'rules' => array ( 0 => array ( 'type' => 'query-builder-rule', 'query' => array ( 'id' => 'firstname', 'field' => 'firstname', 'type' => 'string', 'input' => 'text', 'operator' => 'equal', 'value' => 'Doe', 'rule' => 'firstname', ), ), 1 => array ( 'type' => 'query-builder-rule', 'query' => array ( 'id' => 'lastname', 'field' => 'lastname', 'type' => 'string', 'input' => 'text', 'operator' => 'equal', 'value' => 'Doe', 'rule' => 'lastname', ), ), 2 => array ( 'type' => 'query-builder-rule', 'query' => array ( 'id' => 'email', 'field' => 'email', 'type' => 'string', 'input' => 'text', 'operator' => 'equal', 'value' => 'Doe', 'rule' => 'email', ), ), ), ), ), ), )

second array:

array ( 'condition' => 'OR', 'rules' => array ( 0 => array ( 'type' => 'query-builder-rule', 'query' => array ( 'id' => 'firstname', 'field' => 'firstname', 'type' => 'string', 'input' => 'text', 'operator' => 'equal', 'value' => 'Doe', 'rule' => 'firstname', ), ), 1 => array ( 'type' => 'query-builder-rule', 'query' => array ( 'id' => 'lastname', 'field' => 'lastname', 'type' => 'string', 'input' => 'text', 'operator' => 'equal', 'value' => 'Doe', 'rule' => 'lastname', ), ), 2 => array ( 'type' => 'query-builder-rule', 'query' => array ( 'id' => 'email', 'field' => 'email', 'type' => 'string', 'input' => 'text', 'operator' => 'equal', 'value' => 'Doe', 'rule' => 'email', ), ), ), )

Solution

  • Here, I wrote the code for you. Function name is simplify, your array is in $arr.

    <?php
    function simplify($arr) {
        if(is_array($arr))
            foreach($arr as $key => &$a) {
                if($key == 'rules') {
                    if(is_array($a))
                        foreach($a as $key2 => &$a2) {
                            if(isset($a2['query'])) {
                                if(isset($a2['query']['rules'])) {
                                    $a2['query'] = simplify($a2['query']);
                                }
                                $a2 = $a2['query'];
                            }
                        }
                }
            }
    
        return $arr;
    }
    
    $arr = array(
        'condition' => 'AND',
        'rules' => array(
            0 => array(
                'type' => 'query-builder-rule',
                'query' => array(
                    'id' => 'transactionDate',
                    'field' => 'transactionDate',
                    'type' => 'date',
                    'input' => 'datepicker',
                    'operator' => 'equal',
                    'value' => '2017-05-02 00:00 - 2017-05-03 00:00',
                    'rule' => 'transactionDate',
                ) ,
            ) ,
            1 => array(
                'type' => 'query-builder-group',
                'query' => array(
                    'condition' => 'OR',
                    'rules' => array(
                        0 => array(
                            'type' => 'query-builder-rule',
                            'query' => array(
                                'id' => 'firstname',
                                'field' => 'firstname',
                                'type' => 'string',
                                'input' => 'text',
                                'operator' => 'equal',
                                'value' => 'Doe',
                                'rule' => 'firstname',
                            ) ,
                        ) ,
                        1 => array(
                            'type' => 'query-builder-rule',
                            'query' => array(
                                'id' => 'lastname',
                                'field' => 'lastname',
                                'type' => 'string',
                                'input' => 'text',
                                'operator' => 'equal',
                                'value' => 'Doe',
                                'rule' => 'lastname',
                            ) ,
                        ) ,
                        2 => array(
                            'type' => 'query-builder-rule',
                            'query' => array(
                                'id' => 'email',
                                'field' => 'email',
                                'type' => 'string',
                                'input' => 'text',
                                'operator' => 'equal',
                                'value' => 'Doe',
                                'rule' => 'email',
                            ) ,
                        ) ,
                    ) ,
                ) ,
            ) ,
        ) ,
    );
    $arr = simplify($arr);