Parent Child Relationship With A Single Entity In Doctrine 2

17,960

This should work:

<?php

use Doctrine\Common\Collections\ArrayCollection;

/** @ORM\Entity */
class Category {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer", name="id")
     * @ORM\GeneratedValue
     */
    protected $id;

    // ...

    /**
     * @ORM\OneToMany(targetEntity="Category", mappedBy="parent")
     */
    protected $children;

    /**
     * @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
     * @ORM\JoinColumn(name="parent", referencedColumnName="id")
     */
    protected $parent;

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

    // Once you have that, accessing the parent and children should be straight forward 
    // (they will be lazy-loaded in this example as soon as you try to access them). IE:

    public function getParent() {
        return $this->parent;
    }

    public function getChildren() {
        return $this->children;
    }

    // ...

    // always use this to setup a new parent/child relationship
    public function addChild(Category $child) {
       $this->children[] = $child;
       $child->setParent($this);
    }

    public function setParent(Category $parent) {
       $this->parent = $parent;
    }

}
Share:
17,960
HenryHayes
Author by

HenryHayes

Updated on June 23, 2022

Comments

  • HenryHayes
    HenryHayes almost 2 years

    I have database table that looks like this:

    +----+--------+--------------------+
    | id | parent | description        |
    +----+--------+--------------------+
    |  1 | null   | P Cat 1            |
    |  2 | 1      | Child 1 of P Cat 1 |
    |  3 | 1      | Child 2 of P Cat 1 |
    |  4 | null   | P Cat 2            |
    |  5 | 4      | Child 1 of P Cat 2 |
    |  6 | 4      | Child 2 of P Cat 2 |
    +----+--------+--------------------+
    

    How can I create a doctrine 2 entity that has these columns, but I need the parent column to reference the "id" column as a parent. Of course, a parent record has a null "parent" column value.

    So fair I have

    <?php
    namespace MyNamespace;
    use Doctrine\ORM\Mapping AS ORM;
    use Doctrine\Common\Collections\ArrayCollection;
    /**
     * @ORM\Entity
     * @ORM\Table(name="category")
     **/
    class Category
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="integer", name="id")
         * @ORM\GeneratedValue
         */
        protected $id;
    
        /**
         * Creates a parent / child relationship on this entity.
         *
         * @ORM\ManyToOne(targetEntity="MyNamespace\Category",inversedBy="id")
         * @ORM\JoinColumn(name="FK_parent_id", referencedColumnName="id", nullable=true)
         */
        protected $parent = null;
    
        /**
         * @ORM\Column(type="string", name="description", length=250)
         *
         * @var string
         */
        protected $description;
    
        /**
         * Gets the Primary key value.
         *
         * @return integer
         */
        public function getId()
        {
            return $this->id;
        }
    
        /**
         * Sets another category ID as the parent of this category.
         */
        public function setParent(Category $category)
        {
            $this->parent = $category;
        }
    
        /**
         * Clears the parent id and makes it null.
         */
        public function clearParent()
        {
            $this->parent = null;
        }
    
        /**
         * Sets the description.
         *
         * @param string $description
         * @return Category
         */
        public function setDescription($description)
        {
            $this->description = $description;
            return $this;
        }
    
        /**
         * Gets the description value.
         *
         * @return string
         */
        public function getDescription()
        {
            return $this->description;
        }
    }
    

    Needless to say, this doesn't appear to work. The questions are:

    1. The setParent() method doesn't appear to work as expected when another entity is added as a parent.
    2. I need a getChildren() method on this entity. How can I achieve that?
  • Marcelo Aymone
    Marcelo Aymone over 7 years
    In this case referencedColumnName="id" dont need to be changed to referencedColumnName="children"? Who are id field?
  • redreinard
    redreinard over 7 years
    @MarceloAymone The id and other fields are posted in the question, I didn't copy&paste them here, but yes, referencedColumnName="id" is correct.
  • Mentos93
    Mentos93 about 6 years
    But what if the child has two (or more) parents? For example a real world scenario; mom and dad? Then it would become ManyToMany on the same properties/same config, wouldn't it?
  • redreinard
    redreinard about 6 years
    You would need a separate table to manage that relationship in that case, which would quite significantly change this example. But yes, you could then represent that as a ManyToMany relationship.
  • commonpike
    commonpike over 4 years
    Since the 'child' is the owning side of the relation, should the symmetry not be handled by setParent() instead of by addChild() ? It probably both works ..
  • redreinard
    redreinard over 4 years
    Conceptually only the parent has (should have) access to the children[] array, so ultimately, adding to the children[] array has to be done by the parent. The children array available in setParent() represents the children of that child, not what you want to modify. There's probably ways to hack it to make it work, but I'd stick with always adding entities from the "one" side of the "one-to-many" relationship.