简体   繁体   中英

PHP how to iterate over hierarhical flat array?

I have this data set, which is a flat hierarhical multi-dimensional array:

[
    [
        'title' => 'Skylake',
        'type' => 'category',
        'items' => 
        [
            [
                'title' => 'Core i3',
                'type' => 'category',
                'items' => 
                [
                    [
                        'title' => '6100',
                        'type' => 'product',
                        'price' => 100.0,
                    ],
                    [
                        'title' => '6300',
                        'type' => 'product',
                        'price' => 110.0,
                    ],
                ],
            ],
            [
                'title' => 'Core i7',
                'type' => 'category',
                'items' => [
                    [
                        'title' => '7700',
                        'type' => 'product',
                        'price' => 330.0,
                    ],
                    [
                        'title' => '7700K',
                        'type' => 'product',
                        'price' => 370.0,
                    ],
                ],
            ],
        ],
    ],
    [
        'title' => 'KabyLake',
        'type' => 'category',
    ]
];

As you can see there are two main category: Skylake and Kabylake, and these contains other subcategories and subcategories contain products.

I have tried to iterate over this flat array, but something went wrong, because the 'core i7' category will not know that its parent is 'Skylake'. When I insert the data into the database its parent_id will be null.

   /**
     * Creates catalog.
     * @param mixin $sampleItems sample items
     * @param interger $categoryId id of category (parent id)
     */
    private function createCatalog(&$sampleItems, $categoryId = null)
    {
        foreach ($sampleItems as $sampleItem) {
            if ($sampleItem['type'] == 'category') {
                $categoryId = $this->createCategory($sampleItem, $categoryId);
            } else {
                $this->createProduct($sampleItem, $categoryId);
            }
            $hasItems = isset($sampleItem['items']) && is_array($sampleItem['items']);
            if ($hasItems) {
                $this->createCatalog($sampleItem['items'], $categoryId);
                $categoryId = null;
            }
        }
    }

    /**
     * Create category.
     * @param mixin $sampleData
     * @param integer $parentId ID of parent category
     * @return integer ID of created category
     */
    private function createCategory($sampleData, $parentId)
    {
        $category = new Category();
        if ($parentId !== null) {
            $category->parent_id = $parentId;
        }
        $category->title = $sampleData['title'];
        $category->status = 1;
        $category->save();

        return $category->id;
    }

    /**
     * Create Product.
     * @param mixin $sampleData
     * @param integer $categoryId
     */
    private function createProduct($sampleData, $categoryId)
    {
        $product = new Product();
        if ($categoryId !== null) {
            $product->category_id = $categoryId;
        }
        $product->title = $sampleData['title'];
        $product->price = $sampleData['price'];
        $product->description = $sampleData['description'];
        $product->status = 1;
        $product->save();
    }

Unfortunately this is the current hierarchy in the database:

Skylake
  Core i3
Core i7
KabyLake

The Core i7 should be under the Skylake.

I think the problem is that $parentId will null for Core i7.

But I do not see why.

The problem is that you're using the same variable $categoryId for the parent of the current category and for the parents of the sub-categories that you're creating in the loop. When you do $categoryId = null; after creating a nested catalog, that affects the next call to createCategory() .

Use a different variable, I use $subcat below.

private function createCatalog(&$sampleItems, $categoryId = null)
{
    $subcat = null;
    foreach ($sampleItems as $sampleItem) {
        if ($sampleItem['type'] == 'category') {
            $subcat = $this->createCategory($sampleItem, $categoryId);
        } else {
            $this->createProduct($sampleItem, $categoryId);
        }
        $hasItems = isset($sampleItem['items']) && is_array($sampleItem['items']);
        if ($hasItems) {
            $this->createCatalog($sampleItem['items'], $subcat);
            $subcat = null;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM