2

I have categories with a subcategories. I want to make a links but the subcategories should displayed under category.

Following code/result of my DB:

foreach ($v as $k1 => $v1) {
    print_r ($v1); echo  ' <br />';
}

Followoing result:

Array ( [head] => 1 [category_id] => 5 [category] => colors [module_id] => 2 ) 
Array ( [head] => 1 [category_id] => 6 [category] => floors [module_id] => 2 ) 
Array ( [head] => 5 [category_id] => 7 [category] => wandfarbe [module_id] => 2 ) 
Array ( [head] => 5 [category_id] => 8 [category] => bodenfarbe [module_id] => 2 )  
Array ( [head] => 6 [category_id] => 9 [category] => parkett [module_id] => 2 ) 

Is it possible to get or to echo the result:

1 | 5
    5 | 7
    5 | 8
        8 | 10
        8 | 11
1 | 6
    6 | 9

Am I sutpid to do a for loop or foreach loop? Or is it not possible to do subcategory with this array?

craphunter
  • 961
  • 2
  • 13
  • 34

1 Answers1

1

Here is a bit of code that can do what you want, it's not too elegant, but it will get the job done.

Basically it will create a nested array where the Category ID is the array key, and Category Id, Name, as well as sub categories ('cats') are values at that level.

In the example below, $hier is the array containing the category hierarchy.

// Check each level of $hier for a key with 'head' value
// if found, add cat id under it, otherwise return false
function findPlace(&$hier, $data)
{
    // check for existing position on top level
    foreach ($hier as $level => $cats) {
        if ($level == $data['head']) {
            // the category belongs here
            $hier[$level]['cats'][$data['category_id']] = array(
                'id'   => $data['category_id'],
                'name' => $data['category']
            );

            return true;
        }
    }
    // if not found, check next level down if array
    foreach ($hier as $level => $cats) {
        if (is_array($cats)) {
            return findPlace($hier[$level], $data);
        }
    }

    // did not find a place in hierarchy
    return false;
}

// create new entry
function createPlace(&$hier, $data)
{
    $hier[$data['head']]['id']                         = $data['head'];
    $hier[$data['head']]['cats'][$data['category_id']] = array(
        'id'   => $data['category_id'],
        'name' => $data['category']
    );
}

Then, since you expressed that you wanted to re-sort using the category name (alphabetically), you can add the following functions to do the sorting:

// case insensitive string compare for alpha sort
function compareNames($a, $b)
{
    return strcasecmp($a['name'], $b['name']);
}

// sort array alphabetically by 'name' key
function sortByNameKeys(&$hier) {
    foreach ($hier as $key => $sub) {
        if (isset($sub['cats']) && !empty($sub['cats'])){
            sortByNameKeys($hier[$key]['cats']);
            uasort($hier[$key]['cats'], 'compareNames');
        }
    }
}

Now all you have to do to get your category hierarchy sorted out is loop through your records (categories) and call the findPlace() function, here is an example:

$hier = array(); // category hierarchy will be saved here

foreach ($records as $record) {
    findPlace($hier, $record) || createPlace($hier, $record);
}

sortByNameKeys($hier); // re-sort by name, keeping hierarchy

Hope that helps!

Copy/paste this code into a php file, run it and then var_dump the $hier array to get an idea of the structure.

Petar Zivkovic
  • 970
  • 10
  • 20
  • Do you also got a code so after so sorting I can bring the array in alphabetic order? Of course for each dimension, I should to this. – craphunter Apr 11 '14 at 15:23
  • 1
    @craphunter, I've updated the answer to include alphabetical sorting by 'name' key. The hierarchal order should still be preserved... be sure to test before you deploy. :) – Petar Zivkovic Apr 11 '14 at 20:14
  • It is perfect! Just can't call the function `compareNames` in `sortByNameKeys` in PHP 5.3. But I got an answer here: http://stackoverflow.com/questions/2699086/sort-multi-dimensional-array-by-value. THANKS AGAIN! Works perfect!!! – craphunter Apr 12 '14 at 11:05
  • @craphunter, are you sure? it should be called by the uasort() function from within sortByNameKeys()... no need for you to call it manually. In either case, glad I could help. – Petar Zivkovic Apr 12 '14 at 12:26
  • Yes, I use PHP 5.4.24 with symfony2. I don't know why either. It should work actually. I tested it on another server with a different PHP-Version and it worked fine. Strange. – craphunter Apr 12 '14 at 18:28
  • Okay, it works perfect, but is there still a way that you can add so many subcategories like I get it from the table? The alogrithm stops by 5 | 8. But I added later a subcategory in 8. See update. Is it possible with a little difference in the code? – craphunter Apr 15 '14 at 16:30
  • @craphunter, this code recurses, so it will automatically handle the sub levels… so long as you provide the "head" number correctly. No need to modify the code. – Petar Zivkovic Apr 17 '14 at 10:22