Как экспортировать путь к полным категориям продукта из иерархического дерева?

#php #recursion #hierarchical-data #virtuemart

#php #рекурсия #иерархические данные #virtuemart

Вопрос:

Моей отправной точкой является один массив с идентификаторами категорий и их родительских идентификаторов из таблицы категорий Virtuemart, вот так:

Массив
(
 [0] => Массив
 (
 [id] => 1
 [parent_id] => 0
 [name] => Категория A 
 )

 [1] => Массив
 (
 [id] => 2
 [parent_id] => 1
 [name] => Подкатегория A1
 )

 [2] => Массив
 (
 [id] => 3
 [parent_id] => 2
 [name] => Подкатегория A1
 )

 [3] => Массив
 (
 [id] => 4
 [parent_id] => 1
 [name] => Подкатегория A2
 )

 [4] => Массив
 (
 [id] => 5
 [parent_id] => 0
 [name] => Категория B
 )

 [5] => Массив
 (
 [id] => 6
 [parent_id] => 5
 [name] => Подкатегория B 
 )

)

Мне нужно иметь строку с полным путем к каждой последней дочерней категории, разделенным символом / (косая черта) между дочерними элементами и символом (запятая) между родителями первого уровня

Мой вывод должен быть:

Категория A / Подкатегория A1 / Подкатегория A1, Категория A / Подкатегория A2, Категория B/Подкатегория B

[РЕДАКТИРОВАТЬ] Я мог бы преобразовать начальный массив в этот

Массив
(
 [0] => Массив
 (
 [id] => 1
 [parent_id] => 0
 [name] => Категория A 
 [дочерние элементы] => Массив
 (
 [0] => Массив
 (
 [id] => 2
 [parent_id] => 1
 [name] => Подкатегория A1 
 [дочерние элементы] => Массив
 (
 [0] => Массив
 (
 [id] => 3
 [parent_id] => 2
 [name] => Подкатегория A1
 )

 )

 )

 [1] => Массив
 (
 [id] => 4
 [parent_id] => 1
 [name] => Подкатегория A2

 )

 )

 )

 [1] => Массив
 (
 [id] => 5
 [parent_id] => 0
 [name] => Категория B
 [дочерние элементы] => Массив
 (
 [0] => Массив
 (
 [id] => 6
 [parent_id] => 5
 [name] => Подкатегория B1

 )

 )

 )

)

Ответ №1:

Учитывая следующий массив :

 $array = Array(
    "0" => Array
        (
        "id" => 1,
        "parent_id" => 0,
        "name" => "Category A"
    ),
    "1" => Array
        (
        "id" => 2,
        "parent_id" => 1,
        "name" => "Subcategory A1"
    ),
    "2" => Array
        (
        "id" => 3,
        "parent_id" => 2,
        "name" => "Sub-Subcategory A1"
    ),
    "3" => Array
        (
        "id" => 4,
        "parent_id" => 1,
        "name" => "Subcategory A2"
    ),
    "4" => Array
        (
        "id" => 5,
        "parent_id" => 0,
        "name" => "Category B"
    ),
    "5" => Array
        (
        "id" => 6,
        "parent_id" => 5,
        "name" => "Subcategory B"
    )
);
  

Что-то вроде этого :

 $tabOfElements = array();
foreach($array as $element){
    $tabOfElements[$element['id']] = (isset($tabOfElements[$element['parent_id']])?$tabOfElements[$element['parent_id']].'/':'').$element['name'];
}
$stringOfCategories = implode(',',$tabOfElements);
  

должно делать то, что вам нужно. Примечание: это работает, только если родительские категории всегда находятся ПЕРЕД дочерними в массиве.

Редактировать :

Чтобы получить только весь путь к последней дочерней категории, вы можете сделать :

 $tabOfElements = array();
$elementsToDelete = array();
foreach($array as $element){
    $tabOfElements[$element['id']] = (isset($tabOfElements[$element['parent_id']])?$tabOfElements[$element['parent_id']].'/':'').$element['name'];       
    if(isset($tabOfElements[$element['parent_id']]) amp;amp; !isset($elementsToDelete[$element['parent_id']])){
        $elementsToDelete[$element['parent_id']] = $element['parent_id'];
    }
}
$finalArray = array_diff_key($tabOfElements, $elementsToDelete);
$stringOfCategories = implode(',',$finalArray);
  

Это дало бы вам :

 Category A/Subcategory A1/Sub-Subcategory A1,Category A/Subcategory A2,Category B/Subcategory B
  

ПРАВКА 2 :
Со вторым приведенным вами массивом вы можете использовать рекурсивную функцию типа :

 function recursiveFunction($elementArray, $parentString = ''){
    if(isset($elementArray['children']) amp;amp; !empty($elementArray['children'])){
        foreach($elementArray['children'] as $keyChild=>$child){
            $resultString .= recursiveFunction($child, $parentString.$elementArray['name'].'/').(($keyChild<count($elementArray['children'])-1)?',':'');
        }
        return $resultString;
    }else{
        return $parentString.$elementArray['name'];
    }
}

$tabOfPaths = array();
foreach($array as $elementArray){
    $tabOfPaths[] = recursiveFunction($elementArray);
}
$stringOfPaths = implode(',',$tabOfPaths);
echo $stringOfPaths;
  

Надеюсь, это поможет.

Комментарии:

1. На самом деле, это не совсем то, что вам нужно, поскольку он также предоставляет вам путь к каждой категории вместо всего последнего дочернего пути к категории.

2. РЕДАКТИРОВАТЬ: чтобы получить только путь к последней дочерней категории.

3. @Meeuuuhhhhh У меня не всегда родители предшествуют дочерним элементам, но я холодно преобразовываю начальный массив в иерархический, публикую отредактированный

4. @Andrea Parmeggiani Ну, хорошо, рекурсивная функция теперь является хорошим решением, я думаю, ответ отредактирован.