0

please I have function for 2 level menu... but I dont know how use it for 3 level. Can you help me please ? Example array

  [/c300112000-zvire] => Array
    (
        [/c300112001-pes] => Array
            (
                [0] => /c300112005-antiparazitni-pripravky
                [1] => /c300112002-granulovana-krmiva
                [2] => /c300112009-hracky-misky-a-ostatni
                [3] => /c300112003-konzervy-a-kapsicky
                [4] => /c300112004-pamlsky-a-doplnky-stravy
                [5] => /c300112008-psi-hygiena-a-zdravi
            )

        [/c300112010-kocka] => Array
            (
                [0] => /c300112015-antiparazitni-pripravky
                [1] => /c300112011-granulovana-krmiva
                [2] => /c300112017-hracky-a-misky
                [3] => /c300112016-kocici-hygiena-a-zdravi
                [4] => /c300112012-konzervy-a-kapsicky
                [5] => /c300112013-pamlsky-a-doplnky-stravy
                [6] => /c300112014-podestylky
            )

        [/c300112018-mala-zvirata] => Array
            (
                [0] => /c300112019-krmiva
                [1] => /c300112020-steliva
            )

        [/c300112021-ptactvo] => Array
            (
                [0] => /c300112022-krmiva
                [1] => /c300112023-steliva
            )

        [/c300112024-akvaristika-a-teraristika] => Array
            (
                [0] => /c300112025-krmiva
            )

    )

And my function working only 2 level not 3

  public function saveCategoryTree($categoryTree, Eshop $eshop)
{

    $em = $this->getEntityManager();


    for ($i = 0; $i < sizeof($categoryTree); $i++) {
        $categoryParent = new Category();
        $parent = array_keys($categoryTree)[$i];
        $parentName = explode("/", $parent);
        $parentName = end($parentName);
        $categoryParent->setCreatedAt(new \DateTime());
        $categoryParent->setLastCheckAt(new \DateTime());
        $categoryParent->setLastHttpStatusCode(\Symfony\Component\HttpFoundation\Response::HTTP_OK);
        $categoryParent->setActive(true);
        $categoryParent->setLeaf(false);
        $categoryParent->setEshop($eshop);
        $categoryParent->setName($parentName);
        $categoryParent->setLink($parent);
        $em->persist($categoryParent);
        $em->flush();


        foreach ($categoryTree[array_keys($categoryTree)[$i]] as $childItem) {
            if (is_array($childItem)) {
             echo "Is array ! Recursive call";
            } else {
                $child = new Category();
                $child->setParentCategory($categoryParent);
                $child->setCreatedAt(new \DateTime());
                $child->setLastCheckAt(new \DateTime());
                $child->setLastHttpStatusCode(\Symfony\Component\HttpFoundation\Response::HTTP_OK);
                $child->setActive(true);
                $child->setLeaf(true);
                $child->setEshop($eshop);
                $child->setName($childItem);
                $child->setLink($childItem);
                $em->persist($child);
                $em->flush();
            }

        }

    }
    exit;
}

Thanks for any help. Sorry for my english.

1 Answer 1

1

Move your child iteration logic to a new function and call it recursively;

This way it will work for 2, 3, 4, ... layers of tree functionality.

Edit: In my haste, I've built this code in PHP 7. Be aware this won't work on PHP < 7. Feel free to remove the type hints and return type declarations.

I'd try something along these lines:

    /**
     * @var EntityManager $_em
     */
    private $_em;
    /**
     * @var Eshop $_eshop
     */
    private $_eshop;

    /**
     * @param array $categoryTree
     * @param Eshop $eshop
     */
    public function saveCategoryTree(array $categoryTree, Eshop $eshop)
    {
        $this->_em    = $this->getEntityManager();
        $this->_eshop = $eshop;
        foreach ($categoryTree as $categoryKey => $categoryChildren)
        {
            if (is_array($categoryChildren))
            {
                $parentCategory = $this->_processCategory($categoryKey, $categoryChildren);
                $this->_processRecursiveChildren($parentCategory, $categoryChildren);
            } else
            {
                $this->_processCategory($categoryKey);
            }
        }
        exit;
    }

    /**
     * @param string        $categoryKey
     * @param Category|null $parentCategory
     *
     * @return Category
     */
    private function _processCategory(string $categoryKey, Category $parentCategory=null): Category
    {
        $category   = new Category();
        $parentName = explode("/", $categoryKey);
        $parentName = end($parentName);
        if ($parentCategory !== null)
        {
            $category->setParentCategory($parentCategory);
        }
        $category
            ->setCreatedAt(new \DateTime())
            ->setLastCheckAt(new \DateTime())
            ->setLastHttpStatusCode(\Symfony\Component\HttpFoundation\Response::HTTP_OK)
            ->setActive(true)
            ->setLeaf(false)
            ->setEshop($this->_eshop)
            ->setName($parentName)
            ->setLink($categoryKey)
        ;
        $this->_em->persist($category);
        $this->_em->flush();

        return $category;
    }

    /**
     * @param Category $parentCategory
     * @param array    $children
     */
    private function _processRecursiveChildren(Category $parentCategory, array $children)
    {
        foreach ($children as $childKey => $childItems)
        {
            if (is_array($childItems))
            {
                $nextParentCategory = $this->_processCategory($childKey, $parentCategory);
                $this->_processRecursiveChildren($nextParentCategory, $childItems);
            } else
            {
                $this->_processCategory($childItems, $parentCategory);
            }
        }
    }
Sign up to request clarification or add additional context in comments.

3 Comments

Get error Catchable Fatal Error: Argument 2 passed to AppBundle\Services\CategoryService::_processCategory() must be an instance of AppBundle\Entity\Category, array given, called in D:\Symfony\src\AppBundle\Services\CategoryService.php on line 42
It wasn't meant to be copied 1-on-1, I was trying to give you an impression of how I would solve this particular problem. I've removed the passing of children to the _processCategory call on line 26 of my example code.
You're welcome. Could you accept this answer please?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.