0

I've set a standard category entity using Dedmo NestedTree, and i wrote a script to import a list of categories with their parent.

The categories are well set, and the parents are well set, but the lft and rgt values are wrong.

Since i can possibly add a lot of categories in a loop, i don't think doing a search for parent and doing the flush in a single loop is the best solution...

What could cause this error in the lft, rgt value ? Is it a bug in my code or is it a bug (a limitation) in GedmoTree ?

/**
@ORM\Entity(repositoryClass="MyVendor\MyBundle\Repository\CategoryRepository")
 * @Gedmo\Tree(type="nested")
 */
class Category
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * name of the category.
     *
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     */
    private $name;

    /**
     * @Gedmo\TreeLeft
     * @ORM\Column(name="lft", type="integer")
     */
    private $lft;

    /**
     * @Gedmo\TreeLevel
     * @ORM\Column(name="lvl", type="integer")
     */
    private $lvl;

    /**
     * @Gedmo\TreeRight
     * @ORM\Column(name="rgt", type="integer")
     */
    private $rgt;

    /**
     * @Gedmo\TreeRoot
     * @ORM\Column(name="root", type="integer", nullable=true)
     */
    private $root;

    /**
     * @Gedmo\TreeParent
     * @ORM\ManyToOne(
     *     targetEntity="MyVendor\MyBundle\Entity\Category",
     *     inversedBy="children"
     * )
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $parent;

    /**
     * @ORM\ManyToOne(targetEntity="MyVendor\MyBundle\Entity\Poll")
     * @ORM\JoinColumn(name="poll_id", referencedColumnName="id", onDelete="CASCADE")
     */
    private $poll;

    /**
     * @ORM\OneToMany(
     *     targetEntity="MyVendor\MyBundle\Entity\Category",
     *     mappedBy="parent",
     * )
     * @ORM\OrderBy({"lft" = "ASC"})
     */
    protected $children;

    public function __construct()
    {
        $this->children = new ArrayCollection();
    }
...
}

Then i set a script to import a list of categories, with a hierarchy :

This is the csv file :

CategoyName;ParentCategory

RootCategory;null
Category1;RootCategory
Category2;RootCategory
Category3;RootCategory
Category3-1;Category3
Category3-1-1;Category3-1

And the script :

public function importCategories(Poll $poll, array $categories)
{
    $cats = [];
    $parents = [];
    $children = [];

    $repoCat = $this->om->getRepository('MyVendorMyBundle:Category');

    foreach ($categories as $category) {
        if (count($category) > 1) {
            $categoryName = $category[0];
            $categoryParent = $category[1];
            //does the category exists already ?
            $cat = $repoCat->findOneBy([
                'name' => $categoryName,
                'poll' => $poll,
            ]);
            //if it doesn't
            if ($cat === null) {
                //create category, with no parent
                $newCategory = new Category();
                $newCategory->setName($categoryName);
                $newCategory->setParent(null);
                $newCategory->setPoll($poll);
                $newCategory->setUser($user);
                $this->om->persist($newCategory);

                //save infos
                $cats[] = $newCategory;
                $children[] = $categoryName;
                $parents[] = $categoryParent;
            }
        }
    }
    $this->om->flush();

    //update parent
    //search for parent
    foreach ($parents as $id => $parent) {
        if ($parent !== 'null') {
            $pc = $repoCat->findOneBy([
                'name' => $parent,
                'poll' => $poll,
            ]);
            //if parent is created
            if ($pc !== null) {
                $cats[$id]->setParent($pc);
                $this->om->persist($cats[$id]);
                $this->om->flush();
            }
        }
    }
    $this->om->flush();
}

When i run this script i have this kind of results :

id | parent | name | left | lvl | rgt
161 | NULL | RootCategory | 1 | 0 | 12
162 | 161 | Category1 | 10 | 1 | 11
163 | 161 | Category2 | 8 | 1 | 9
164 | 161 | Category3 | 2 | 1 | 7
165 | 164 | Category3-1 | 3 | 2 | 6
166 | 165 | Category3-1-1 | 4 | 3 | 5

instead of

id | parent | name | left | lvl | rgt
161 | NULL | RootCategory | 1 | 0 | 12
162 | 161 | Category1 | 2 | 1 | 3
163 | 161 | Category2 | 4 | 1 | 5
164 | 161 | Category3 | 6 | 1 | 11
165 | 164 | Category3-1 | 7 | 2 | 10
166 | 165 | Category3-1-1 | 8 | 3 | 9

I've see this kind of post, and i've tried to add

$repo->verify();
$repo->recover();

before the flush, but it didn't change anything

Community
  • 1
  • 1
Overdose
  • 585
  • 7
  • 30
  • Generated tree is valid. It just have different sort order than you expected it to have. – Jakub Matczak Aug 29 '16 at 15:37
  • yes it is "valid", but how can i have manage to have the "sort" expected ? since the categories are persisted in that order (root, then cat1, then cat2...) it should be the "expected" sort i should have and not that weird one. – Overdose Aug 29 '16 at 17:18
  • 1
    What about this? https://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/tree.md#inserting-node-in-different-positions – Jakub Matczak Aug 29 '16 at 18:01
  • Indeed, `$repoCat->persistAsLastChildOf($cats[$id], $pc);` seems to do the trick. Thanks. Weird though for the standard behaviour. – Overdose Aug 31 '16 at 12:40

0 Answers0