PHP обратный массив дерева категорий в список Breadcrumb - PullRequest
0 голосов
/ 29 сентября 2018

У меня есть массив дерева категорий, полученный из MySQL Table.Я хочу вернуть это дерево массива категорий обратно в список Breadcrumb, используя PHP.

Функция построения дерева категорий PHP

function buildTree(array &$elements, $parentId = 0) 
{
    $branch = array();

    foreach ($elements as $element) {
        if ($element['parent_category_id'] == $parentId) {
            $children = buildTree($elements, $element['category_id']);
            if ($children) {
                $element['children'] = $children;
            }
            $branch[$element['category_id']] = $element;
            unset($elements[$element['category_id']]);
        }
    }
    return $branch;
}

Массив результатов

[48] => Array
    (
        [category_id] => 48
        [category_name] => Cat 1 
        [parent_category_id] => 0
        [children] => Array
            (
                [957] => Array
                    (
                        [category_id] => 957
                        [category_name] =>  Cat 2
                        [parent_category_id] => 48
                        [children] => Array
                            (
                                [1528] => Array
                                    (
                                        [category_id] => 1528
                                        [category_name] =>  Cat 3
                                        [parent_category_id] => 957
                                    )

                                [1890] => Array
                                    (
                                        [category_id] => 1890
                                        [category_name] =>  Cat 4
                                        [parent_category_id] => 957
                                    )

                                [1570] => Array
                                    (
                                        [category_id] => 1570
                                        [category_name] =>  Cat 5
                                        [parent_category_id] => 957
                                    )

                                [958] => Array
                                    (
                                        [category_id] => 958
                                        [category_name] =>  Cat 6
                                        [parent_category_id] => 957
                                    )

                            )

                    )

Теперь я хочу преобразовать это дерево массива обратно в список Breadcrumb, используя PHP, например

"Cat 1> Cat 2> Cat 3"

"Кошка 1> Кошка 2> Кошка 4"

"Кошка 1> Кошка 2> Кошка 5"

"Кошка 1> Кошка 2> Кошка 6"

Любая помощь будет высоко ценится.

Снимок экрана

Снимок экрана Справочник

Ответы [ 2 ]

0 голосов
/ 29 сентября 2018

Ключевой концепцией является преобразование вашего дерева в плоский массив, где каждая категория индексируется по ее идентификатору.Из этой плоской структуры вы можете идти вверх по иерархии, пока не дойдете до корня для каждой категории, создавая массив уровней.Я создал вспомогательный класс для инкапсуляции базовой функциональности, которая может потребоваться для хлебных крошек.Рекурсия происходит по методу _unwindTree.Метод _buildBreadcrumbs вызывает эту функцию и использует результирующий плоский массив для построения «линий» хлебных крошек для каждой категории.Это две функции, на которые нужно обратить внимание, чтобы понять, как преобразовать дерево в массив путей категорий.

Существуют некоторые открытые функции, которые по-разному предоставляют доступ к данным хлебной крошки.

<?php

$tree = [
    48 => [
        'category_id' => 48,
        'category_name' => 'Cat 1',
        'parent_category_id' => 0,
        'children' =>
            [
                957 =>
                    [
                        'category_id' => 957,
                        'category_name' => 'Cat 2',
                        'parent_category_id' => 48,
                        'children' =>
                            [
                                1528 =>
                                    [
                                        'category_id' => 1528,
                                        'category_name' => 'Cat 3',
                                        'parent_category_id' => 957
                                    ],
                                1890 =>
                                    [
                                        'category_id' => 1890,
                                        'category_name' => 'Cat 4',
                                        'parent_category_id' => 957
                                    ],
                                1570 =>
                                    [
                                        'category_id' => 1570,
                                        'category_name' => 'Cat 5',
                                        'parent_category_id' => 957
                                    ],
                                958 =>
                                    [
                                        'category_id' => 958,
                                        'category_name' => 'Cat 6',
                                        'parent_category_id' => 957
                                    ]

                            ]

                    ]
            ]
    ]
];

class BreadcrumbHelper
{

    private $_leafOnly = true;
    private $_defaultBaseUrlPath = '/category/';

    private $_tree        = [];
    private $_idMap       = [];
    private $_leafIds     = [];
    private $_breadcrumbs = [];

    /**
     * BreadcrumbHelper constructor.
     * @param array $tree The tree of category data
     */
    public function __construct($tree)
    {
        $this->_tree = $tree;

        //Build the breadcrumb data structure
        $this->_buildBreadcrumbs();
    }

    /**
     * Return breadcrumbs as an array
     * @param mixed $categoryIds optional, only specified categories will be returned
     * @return array
     */
    public function getBreadcrumbArray($categoryIds = [])
    {
        //If a bare ID is passed, wrap it in an array so we can treat all input the same way
        if (!is_array($categoryIds))
        {
            $categoryIds = [$categoryIds];
        }

        //If we have category input, return a filtered array of the breadcrumbs
        if (!empty($categoryIds))
        {
            return array_intersect_key($this->_breadcrumbs, array_flip($categoryIds));
        }

        //If no input, return the fill array
        return $this->_breadcrumbs;
    }

    /**
     * Return breadcrumbs as an array containing HTML markup
     * You may want to modify this to echo HTML directly, or return markup only instead of an array
     * @param mixed $categoryIds optional, only specified categories will be returned
     * @return array
     */
    public function getBreadcrumbHtml($categoryIds = [], $baseUrlPath = null)
    {
        //If a bare ID is passed, wrap it in an array so we can treat all input the same way
        if (!is_array($categoryIds))
        {
            $categoryIds = [$categoryIds];
        }

        //If a base URL path is provided, use it, otherwise use default
        $baseUrlPath = (empty($baseUrlPath)) ? $this->_defaultBaseUrlPath : $baseUrlPath;

        //Filter breadcrumbs if IDs provided
        $breadcrumbs = (empty($categoryIds)) ? $this->_breadcrumbs : array_intersect_key($this->_breadcrumbs, array_flip($categoryIds));

        $output = [];
        foreach ($breadcrumbs as $currCategoryId => $currLine)
        {
            $currLinkBuffer = [];
            foreach ($currLine as $currCategory)
            {
                //Build the markup - customize the URL for your application
                $currLinkBuffer[] = '<a href="' . $baseUrlPath . $currCategory['category_id'] . '">' . $currCategory['category_name'] . '</a>';
            }

            $output[$currCategoryId] = implode(' &gt; ', $currLinkBuffer);
        }

        return $output;
    }

    /**
     * Print the breadcrumbs
     * @param array $categoryIds optional, only specified categories will be printed
     */
    public function printBreadcrumbs($categoryIds = [])
    {
        //If a bare ID is passed, wrap it in an array so we can treat all input the same way
        if (!is_array($categoryIds))
        {
            $categoryIds = [$categoryIds];
        }

        //Filter breadcrumbs if IDs provided
        $breadcrumbs = (empty($categoryIds)) ? $this->_breadcrumbs : array_intersect_key($this->_breadcrumbs, array_flip($categoryIds));

        foreach ($breadcrumbs as $currLine)
        {
            //Build a buffer of the category names
            $currNameBuffer = [];
            foreach ($currLine as $currCategory)
            {
                $currNameBuffer[] = $currCategory['category_name'];
            }

            //Join the name buffer with a separator and echo the result
            echo implode(' > ', $currNameBuffer) . PHP_EOL;
        }
    }

    /**
     * Create the breadcrumb data structure from the provided tree
     */
    private function _buildBreadcrumbs()
    {
        //Unwind the tree into a flat array
        $this->_unwindTree($this->_tree);

        //Traverse the flat array and build the breadcrumb lines
        $categoryIds = ($this->_leafOnly) ? $this->_leafIds:array_keys($this->_idMap);
        foreach ($categoryIds as $currLeafId)
        {
            $currCategoryId = $currLeafId;

            $currLine = [];

            do
            {
                $currLine[]     = $this->_idMap[$currCategoryId];
                $currCategoryId = $this->_idMap[$currCategoryId]['parent_category_id'];
            } while ($currCategoryId != 0);

            $this->_breadcrumbs[$currLeafId] = array_reverse($currLine);
        }
    }

    /**
     * Recursive function that traverses the tree and builds an associative array of all categories
     * indexed by ID. Categories saved in this structure do not include children.
     * @param $branch
     */
    private function _unwindTree($branch)
    {
        foreach ($branch as $currId => $currData)
        {
            //Set the current category in the ID map, remove the children if present
            $this->_idMap[$currId] = array_diff_key($currData, array_flip(['children']));

            if (!empty($currData['children']))
            {
                //Recursion
                $this->_unwindTree($currData['children']);
            }
            else
            {
                $this->_leafIds[] = $currId;
            }
        }
    }
}

//Instantiate our helper with the tree data
$breadcrumbHelper = new BreadcrumbHelper($tree);

echo 'All breadcrumbs: ' . PHP_EOL;
$breadcrumbHelper->printBreadcrumbs();
echo PHP_EOL;

echo 'Single breadcrumb line by category ID: ' . PHP_EOL;
$breadcrumbHelper->printBreadcrumbs(1570);
echo PHP_EOL;

echo 'Multiple categories: ' . PHP_EOL;
$breadcrumbHelper->printBreadcrumbs([957, 1570]);
echo PHP_EOL;

echo 'Breadcrumb HTML: ' . PHP_EOL;
$breadcrumbMarkup = $breadcrumbHelper->getBreadcrumbHtml();
echo $breadcrumbMarkup[1570] . PHP_EOL;
echo PHP_EOL;

echo 'Breadcrumb HTML with custom base URL: ' . PHP_EOL;
$breadcrumbMarkup = $breadcrumbHelper->getBreadcrumbHtml(1570, '/category.php?id=');
echo $breadcrumbMarkup[1570] . PHP_EOL;
echo PHP_EOL;
0 голосов
/ 29 сентября 2018
function treeToArray($data, &$return_data, $index = '', $sub = 'sub')
{
    if (is_array($data)) {
        foreach ($data as $value) {
            if (isset($value[$sub])) {
                $tmp = $value[$sub];
                unset($value[$sub]);
                if ($index) {
                    $return_data[$value[$index]] = $value;
                } else {
                    $return_data[] = $value;
                }
                treeToArray($tmp, $return_data, $index, $sub);
            } else {
                if ($index) {
                    $return_data[$value[$index]] = $value;
                } else {
                    $return_data[] = $value;
                }
            }
        }
    }
    return $return_data;
}

$tree[48] =  Array
    (
    "category_id" => '48',
    "category_name" => 'Cat 1',
    "parent_category_id" => '0',
    "children" => Array
        (
            '957' => Array
                (
                    "category_id" => "957",
                    "category_name" =>  "Cat",
                    "parent_category_id" => "48",
                    "children" => Array
                        (
                            '1528' => Array
                                (
                                    "category_id" => "1528",
                                    "category_name" =>  "Cat3",
                                    "parent_category_id" => "957",
                                )

                        )

                )
            )
    );

$data = [];
treeToArray($tree, $data, 'category_id', 'children');
print_r($data);

надеюсь, что это может быть полезным

...