Symfony ArrayCollection vs PersistentCollection

26,979

Solution 1

Short answer:

/**
 * @param Doctrine\Common\Collections\Collection $users
 * @return $this
 */
public function setChildren(Doctrine\Common\Collections\Collection $users)
{
    $this->children = $users;

    return $this;
}

Explanation:

If you look deep into Doctrine Classes you will see the following structure:

Array collection is class that implements interface Collection:

class ArrayCollection implements Collection, Selectable

PersistentCollection is class that extentds AbstractLazyCollection:

final class PersistentCollection extends AbstractLazyCollection implements Selectable

but AbstractLazyCollection implements Collection:

abstract class AbstractLazyCollection implements Collection

So:

Collection is interface, that you should use in method setChildren().

This is because of doctrine use lazy loading - mechanism that allow to load not all properties, but only these, that are needed.

Similar question:

Doctrine manyToMany return PersistentCollection instead of ArrayCollection

Solution 2

In your typing add Collection $children

use Doctrine\Common\Collections\Collection; ...

private ?Collection $children;

symfony: 5.3

Share:
26,979

Related videos on Youtube

Majid Abdolhosseini
Author by

Majid Abdolhosseini

I am a software developer ! my first interest is Software architecture. I worked on so many old systems and I had to scale them and make them decoupled systems (components or services) which can work nice together . I've worked so much on software architecture and design patterns but I know still there is much to learn. One of my hubbies is reading about software world and new technologies and devices. like to learn new technologies. like to dig in technologies not just to use them. I hate using a technology without fully understanding it. I like football , body building , action movies , horror movies , ...

Updated on November 07, 2021

Comments

  • Majid Abdolhosseini
    Majid Abdolhosseini over 2 years

    As I understood when you query database by repository you get PersistentCollection and when your working with your entities you get ArrayCollection.

    so consider I have one to many self referencing relation for my user entity.

    and in my user entity I have a setChildren method which get ArrayCollection of users as argument .

    <?php
    
    namespace UserBundle\Entity;
    
    use Abstracts\Entity\BaseModel;
    use CertificateBundle\Entity\Certificate;
    use Doctrine\Common\Collections\ArrayCollection;
    use Doctrine\ORM\Mapping as ORM;
    use EducationBundle\Entity\Education;
    use LanguageBundle\Entity\Language;
    use PostBundle\Entity\Post;
    use ProfileBundle\Entity\Company;
    use RoleBundle\Entity\Role;
    use SkillBundle\Entity\Skill;
    use Symfony\Component\Security\Core\User\UserInterface;
    use Symfony\Component\Validator\Constraints as Assert;
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
    
    /**
     * User
     *
     * @ORM\Table(name="users")
     * @ORM\Entity(repositoryClass="UserBundle\Repository\Entity\UserRepository")
     * @UniqueEntity("email")
     * @UniqueEntity("username")
     */
    class User implements UserInterface
    {
    
    
        use BaseModel;
        /**
         * @var int
         *
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;
    
    
        /**
         * @var string
         *
         * @ORM\Column(name="type", type="string", columnDefinition="ENUM('merchant', 'company', 'customer') ")
         */
        private $type;
    
    
        /**
         * @ORM\Column(type="string", unique=true)
         * @Assert\NotBlank()
         */
        private $username;
    
        /**
         * @var string
         *
         * @ORM\Column(type="string", length=255)
         * @Assert\NotBlank()
         */
        private $email;
    
    
        /**
         * @var string
         * @ORM\Column(type="string", nullable=true)
         */
        private $avatar = null;
        /**
         * @var string
         * @ORM\Column(type="string", nullable=true)
         */
        private $cover = null;
    
    
        /**
         * @ORM\OneToMany(targetEntity="PostBundle\Entity\Post", mappedBy="user", orphanRemoval=true, cascade={"persist", "remove"})
         */
        private $posts;
    
        /**
         * @ORM\OneToMany(targetEntity="EducationBundle\Entity\Education" , mappedBy="user" , orphanRemoval=true, cascade={"persist", "remove"})
         */
        protected $educations;
    
    
        /**
         * @ORM\OneToMany(targetEntity="SkillBundle\Entity\SkillUser" , mappedBy="user" , orphanRemoval=true, cascade={"persist", "remove"})
         */
        protected $skills;
    
        /**
         * @ORM\OneToMany(targetEntity="LanguageBundle\Entity\LanguageUser" , mappedBy="user" , orphanRemoval=true, cascade={"persist", "remove"})
         */
        protected $languages;
    
    
        /**
         * @ORM\OneToMany(targetEntity="ResumeBundle\Entity\Resume" , mappedBy="user" , cascade={"all"})
         */
        protected $resumes;
    
    
        /**
         * @ORM\OneToMany(targetEntity="CertificateBundle\Entity\CertificateUser" , mappedBy="user" , orphanRemoval=true, cascade={"persist", "remove"})
         */
        protected $certificates;
    
    
        /**
         * @ORM\OneToOne(targetEntity="ProfileBundle\Entity\Company", mappedBy="user")
         */
        protected $company;
    
        /**
         * @ORM\OneToOne(targetEntity="ProfileBundle\Entity\Customer", mappedBy="user")
         */
        protected $customer;
    
        /**
         * @ORM\OneToOne(targetEntity="ProfileBundle\Entity\Merchant", mappedBy="user")
         */
        protected $merchant;
    
    
    
    
        /**
         * @var string
         * @Assert\NotBlank()
         * @Assert\Length(min=4)
         * @ORM\Column(name="password", type="string", length=255)
         *
         */
        private $password;
    
        /**
         * @ORM\ManyToMany(targetEntity="RoleBundle\Entity\Role", inversedBy="users", cascade={"persist"})
         * @ORM\JoinTable(name="user_role", joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}, inverseJoinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id")})
         */
        private $roles;
    
    
    
        /**
         * @ORM\ManyToOne(targetEntity="UserBundle\Entity\User", inversedBy="children")
         * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="SET NULL")
         */
        protected $parent;
    
    
        /**
         * @ORM\OneToMany(targetEntity="UserBundle\Entity\User", mappedBy="parent", orphanRemoval=true, cascade={"persist", "remove"})
         *
         */
        protected $children;
    
    
        /**
         * @var array
         */
        public static $fields = [ 'email', 'username', 'id', 'avatar', 'cover', 'type'];
    
        /**
         * User Entity constructor.
         */
        public function __construct(/*EncoderFactoryInterface $encoderFactory*/)
        {
            //$this->encoderFactory = $encoderFactory;
            $this->posts        = new ArrayCollection();
            $this->skills       = new ArrayCollection();
            $this->languages    = new ArrayCollection();
            $this->certificates = new ArrayCollection();
            $this->educations   = new ArrayCollection();
            $this->children     = new ArrayCollection();
    
            dump($this->children);
            die();
    
        }
    
    
    
    
        /**
         * @param User $user
         * @return $this
         */
        public function setParent(User $user)
        {
            $this->parent = $user;
    
            return $this;
        }
    
    
        /**
         * @return $this
         */
        public function removeParent()
        {
            $this->parent = null;
    
            return $this;
        }
    
    
    
        /**
         * @param User $user
         * @return $this
         */
        public function addChild(User $user)
        {
            if(!$this->children->contains($user)){
                $this->children->add($user);
            }
    
            return $this;
        }
    
    
        /**
         * @param User $user
         * @return bool
         */
        public function hasChild(User $user)
        {
            return $this->children->contains($user);
        }
    
    
    
        /**
         * @param User $user
         * @return bool
         */
        public function isChildOf(User $user)
        {
            return $user->getChildren()->contains($this);
        }
    
        /**
         * @return ArrayCollection
         */
        public function getChildren()
        {
            return $this->children;
        }
    
        /**
         * @param User $user
         * @return $this
         */
        public function removeChild(User $user)
        {
            if($this->children->contains($user)){
                $this->children->removeElement($user);
            }
    
            return $this;
        }
    
        /**
         * @param ArrayCollection $users
         * @return $this
         */
        public function setChildren(ArrayCollection $users)
        {
            $this->children = $users;
    
            return $this;
        }
    
    
        /**
         * @return $this
         */
        public function removeChildren()
        {
            $this->children->clear();
    
            return $this;
        }
    
    
        /**
         * @param ArrayCollection $certificates
         * @return $this
         */
        public function setCertificates(ArrayCollection $certificates)
        {
            $this->certificates = $certificates;
    
            return $this;
        }
    
    
        /**
         * @param Certificate $certificate
         * @return $this
         */
        public function addCertificate(Certificate $certificate)
        {
            if(!$this->certificates->contains($certificate))
                $this->certificates->add($certificate);
    
            return $this;
        }
    
        /**
         * @param Certificate $certificate
         * @return $this
         */
        public function removeCertificate(Certificate $certificate)
        {
            if($this->certificates->contains($certificate))
                $this->certificates->removeElement($certificate);
    
            return $this;
        }
    
        /**
         * @return $this
         */
        public function removeCertificates()
        {
            $this->certificates->clear();
    
            return $this;
        }
    
    
        /**
         * @param ArrayCollection $skills
         * @return $this
         */
        public function setSkills(ArrayCollection $skills)
        {
            $this->skills = $skills;
    
            return $this;
        }
    
    
        /**
         * @param Skill $skill
         * @return $this
         */
        public function addSkill(Skill $skill)
        {
            if(!$this->skills->contains($skill))
                $this->skills->add($skill);
    
            return $this;
        }
    
        /**
         * @param Skill $skill
         * @return $this
         */
        public function removeSkill(Skill $skill)
        {
            if($this->skills->contains($skill))
                $this->skills->removeElement($skill);
    
            return $this;
        }
    
        /**
         * @return $this
         */
        public function removeSkills()
        {
            $this->skills->clear();
    
            return $this;
        }
    
    
    
    
        /**
         * @param ArrayCollection $languages
         * @return $this
         */
        public function setLanguages(ArrayCollection $languages)
        {
            $this->languages = $languages;
    
            return $this;
        }
    
    
        /**
         * @param Language $language
         * @return $this
         */
        public function addLanguage(Language $language)
        {
            if(!$this->languages->contains($language))
                $this->languages->add($language);
    
            return $this;
        }
    
        /**
         * @param Language $language
         * @return $this
         */
        public function removeLanguage(Language $language)
        {
            if($this->languages->contains($language))
                $this->languages->removeElement($language);
    
            return $this;
        }
    
        /**
         * @return $this
         */
        public function removeLanguages()
        {
            $this->languages->clear();
    
            return $this;
        }
    
    
        /**
         * @param ArrayCollection $posts
         * @return $this
         */
        public function setPosts(ArrayCollection $posts)
        {
            $this->posts = $posts;
    
            return $this;
        }
    
        /**
         * @param Post $post
         * @return $this
         */
        public function addPost(Post $post)
        {
            $this->posts->add($post);
    
            return $this;
        }
    
        /**
         * @param Post $post
         * @return $this
         */
        public function removePost(Post $post)
        {
            $this->posts->removeElement($post);
    
            return $this;
        }
    
        /**
         * @return $this
         */
        public function removePosts()
        {
            $this->posts->clear();
    
            return $this;
        }
    
    
        /**
         * @param ArrayCollection $educations
         * @return $this
         */
        public function setEducations(ArrayCollection $educations)
        {
            $this->educations = $educations;
    
            return $this;
        }
    
        /**
         * @param Education $education
         * @return $this
         */
        public function addEducation(Education $education)
        {
            $this->educations->add($education);
    
            return $this;
        }
    
        /**
         * @param Education $education
         * @return $this
         */
        public function removeEducation(Education $education)
        {
            $this->educations->removeElement($education);
    
            return $this;
        }
    
        /**
         * @return $this
         */
        public function removeEducations()
        {
            $this->educations->clear();
    
            return $this;
        }
    
    
        /**
         * Get id
         *
         * @return integer
         */
        public function getId()
        {
            return $this->id;
        }
    
        /**
         * @param integer $id
         * @return $this
         */
        public function setId($id)
        {
            $this->id = $id;
    
            return $this;
        }
    
        /**
         * @return mixed
         */
        public function getType()
        {
            return $this->type;
        }
    
        /**
         * @param mixed $type
         * @return $this
         */
        public function setType($type)
        {
            $this->type = $type;
    
            return $this;
        }
    
    
        /**
         * Set email
         *
         * @param string $email
         * @return User
         */
        public function setEmail($email)
        {
            $this->email = $email;
    
            return $this;
        }
    
    
        /**
         * @return string
         */
        public function getEmail()
        {
            return $this->email;
        }
    
    
        /**
         * @param $username
         * @return $this
         */
        public function setUsername($username)
        {
            $this->username = $username;
            return $this;
        }
    
        /**
         * @return mixed
         */
        public function getUsername()
        {
            return $this->username;
        }
    
        /**
         * @return array
         */
        public function getRoles()
        {
            return ['ROLE_USER', 'IS_AUTHENTICATED_ANONYMOUSLY'];
        }
    
        /**
         * @param $password
         * @return $this
         */
        public function setPassword($password)
        {
            //$password =$this->encoderFactory->getEncoder($this)->encodePassword($password, $this->getSalt());
    
            $this->password = $password;
            return $this;
    
        }
    
        /**
         * @return string
         */
        public function getPassword()
        {
            return $this->password;
        }
    
        /**
         *
         */
        public function getSalt()
        {
            return md5(sha1('somesalt'));
        }
    
        /**
         *
         */
        public function eraseCredentials()
        {
        }
    
        /**
         * @param $cover
         * @return $this
         */
        public function setCover($cover)
        {
            $this->cover = $cover;
            return $this;
    
        }
    
        /**
         * @return string
         */
        public function getCover()
        {
            return $this->cover;
        }
    
        /**
         * @param $avatar
         * @return $this
         */
        public function setAvatar($avatar)
        {
            $this->avatar = $avatar;
            return $this;
    
        }
    
        /**
         * @return string
         */
        public function getAvatar()
        {
            return $this->avatar;
    
        }
    
    
        /**
         * @param Role $roles
         */
        public function addRoles(Role $roles)
        {
            $this->roles[] = $roles;
        }
    
        /**
         * @return mixed
         */
        public function getRoles2()
        {
            return $this->roles;
        }
    
        /**
         * @return array
         */
        public function getRolesAsArray()
        {
            $rolesArray = [];
            foreach ($this->getRoles2() as $role) {
                $rolesArray[] = $role->getName();
    
            }
            return $rolesArray;
    
        }
    
    
        /**
         * @return Company
         */
        public function getCompany()
        {
            return $this->company;
        }
    
        /**
         * @param Company $company
         * @return $this
         */
        public function setCompany(Company $company)
        {
            $this->company = $company;
    
            return $this;
        }
    
    }
    

    and this is what I want to do

    $new_owner = $this->userRepository->findOneById($user_id, false);
    
    $children = $old_owner->getChildren();
    
    $old_owner->removeChildren();
    $new_owner->setChildren($children);
    

    and I get error which says :

    Argument 1 passed to Proxies__CG__\UserBundle\Entity\User::setChildren() must be an instance of Doctrine\Common\Collections\ArrayCollection, instance of Doctrine\ORM\PersistentCollection given

    should I change my type hint in setChildren method to PersistentCollection ?? or I need to totally change my approach?

    • B.Kevin
      B.Kevin almost 8 years
      how look your $this->children; in your model ? can i have the two models?
    • Majid Abdolhosseini
      Majid Abdolhosseini almost 8 years
      I updated code above so you can see properties and their annotations. both models are from User Entity. it's a self referencing relation.
    • B.Kevin
      B.Kevin almost 8 years
      try to add public function __construct() { $this->children = new ArrayCollection(); }
    • Majid Abdolhosseini
      Majid Abdolhosseini almost 8 years
      I already did that ! :) it's just not present at my code
    • B.Kevin
      B.Kevin almost 8 years
      okey i cant gess :) how looks the full method in your controller and the full model ?
    • Majid Abdolhosseini
      Majid Abdolhosseini almost 8 years
      I updated code again .
    • B.Kevin
      B.Kevin almost 8 years