Search code examples
phparrayskeyelementsub-array

Combine some php sub-arrays, with condition


$routes array:

[admin/login] => Array
    (
        [0] => POST|AJAX
        [1] => admin/login
        [2] => admin/login
    )

[admin/logout] => Array
    (
        [0] => POST
        [1] => admin/logout
        [2] => admin/logout
    )

[admin/dashboard] => Array
    (
        [0] => GET
        [1] => admin/dashboard
        [2] => admin/dashboard
    )

[admin/products] => Array
    (
        [0] => GET
        [1] => admin/products/[:pag]
        [2] => admin/products/all
    )

[admin/products/add] => Array
    (
        [0] => GET
        [1] => admin/product/add
        [2] => admin/products/add
    )

[admin/products/insert] => Array
    (
        [0] => POST
        [1] => admin/product/insert
        [2] => admin/products/insert
    )

[admin/products/show] => Array
    (
        [0] => GET
        [1] => admin/product/[i:id]
        [2] => admin/products/show
    )

[admin/products/edit] => Array
    (
        [0] => GET
        [1] => admin/product/[i:id]/edit
        [2] => admin/products/edit
    )

[admin/products/update] => Array
    (
        [0] => POST
        [1] => admin/product/update
        [2] => admin/products/update
    )

[admin/products/delete] => Array
    (
        [0] => POST
        [1] => admin/product/delete
        [2] => admin/products/delete
    )

[admin/categories] => Array
    (
        [0] => GET
        [1] => admin/categories
        [2] => admin/categories/all
    )

[admin/categories/add] => Array
    (
        [0] => GET
        [1] => admin/category/add
        [2] => admin/categories/add
    )

[admin/categories/insert] => Array
    (
        [0] => POST
        [1] => admin/category/insert
        [2] => admin/categories/insert
    )

[admin/categories/show] => Array
    (
        [0] => GET
        [1] => admin/category/[i:id]
        [2] => admin/categories/show
    )

[admin/categories/edit] => Array
    (
        [0] => GET
        [1] => admin/category/[i:id]/edit
        [2] => admin/categories/edit
    )

[admin/categories/update] => Array
    (
        [0] => POST
        [1] => admin/category/update
        [2] => admin/categories/update
    )

[admin/categories/delete] => Array
    (
        [0] => POST
        [1] => admin/category/delete
        [2] => admin/categories/delete
    )

[admin/api] => Array
    (
        [0] => GET
        [1] => admin/api
        [2] => admin/api/all
    )


[admin/filter/sessions] => Array
    (
        [0] => POST|AJAX
        [1] => admin/filter/sessions
        [2] => admin/filters/sessions
    )

This is $admin_routes array (build from $routes):

[login] => Array
    (
        [0] => admin/login
    )

[logout] => Array
    (
        [0] => admin/logout
    )

[dashboard] => Array
    (
        [0] => admin/dashboard
    )

[products] => Array
    (
        [0] => admin/products
        [1] => admin/products/add
        [2] => admin/products/insert
        [3] => admin/products/show
        [4] => admin/products/edit
        [5] => admin/products/update
        [6] => admin/products/delete
    )

[api] => Array
    (
        [0] => admin/api
    )

[filter] => Array
    (
        [0] => admin/filter/sessions
    )

[categories] => Array
    (
        [0] => admin/categories
        [1] => admin/categories/add
        [2] => admin/categories/insert
        [3] => admin/categories/show
        [4] => admin/categories/edit
        [5] => admin/categories/update
        [6] => admin/categories/delete
    )

I need some help from you guys about $admin_routes. I want to combine all sub-arrays from $admin_routes, from same area, which has only one element, in a new sub-array with key name formed from their key names. Also i want the new sub-array to have same 'position' in line.

My imperfect solution:

// creating $admin_routes
$admin_routes = [];
foreach ($routes as $name => $route) {
    if (preg_match('/^admin\/(.*)$/', $name))
        $admin_routes[explode('/', $name)[1]][] = $name;
}

// imperfect solution for what i want
$single = false;
$waiting = [];
foreach ($admin_routes as $section => $routes) {
    if (count($routes) == 1) { // remember all sub-arrays, with one single element, from same area
        $single = true;

        $waiting[$section] = $routes;
    }
    else if ($single) { // if found all sub-arrays, with one single element, from same area
        $name = '';
        $subarray = [];
        foreach ($waiting as $section => $routes) {
            // creating only one sub-array
            $name .= ($section . ' ');
            $subarray = array_merge($subarray, $routes);
            unset($admin_routes[$section]);
        }

        // the problem is, sub-array it's added at the end of $admin_routes
        // (not where sub-array's elements were before)
        $admin_routes[$name] = $subarray;

        $single = false;
        $waiting = [];
    }
}

The problem is, the new sub-arrays are placed at the end.

If you have any idea, please help me. Thx.


Solution

  • Using your actual result $admin_routes, you could loop through them and rebuild the desired array:

    $real_routes    = [];   // The new array
    $singles_key    = '';   // The key for combined sub-arrays
    $singles_routes = [];   // The routes for combined sub-arrays
    
    foreach ($admin_routes as $name => $r) {
    
        /* If this route array has a single entry,
           add its name and value to our temp vars */
        if (count($r) === 1) {
            $singles_key .= $name . ' ';
            $singles_routes = array_merge($singles_routes, $r);
        } else {
    
            /* If then a route array has multiple value,
               save the combined singles and then save this one */
            if (!empty($singles_key)) {
                $real_routes[trim($singles_key)] = $singles_routes;
                $singles_key = '';
                $singles_routes = [];
            }
            $real_routes[$name] = $r;
        }
    }
    
    /* If the loop ends but the temp vars aren't empty,
       save the lasts combined singles */
    if (!empty($singles_key)) {
        $real_routes[trim($singles_key)] = $singles_routes;
    }
    
    // Then to output:
    echo '<pre>' . print_r($real_routes, true) . '</pre>';