web-dev-qa-db-fra.com

Symfony ArrayCollection vs PersistentCollection

Comme je l'ai compris, lorsque vous interrogez une base de données par référentiel, vous obtenez PersistentCollection et lorsque vous travaillez avec vos entités, vous obtenez ArrayCollection.

considérez donc que j'ai une à plusieurs relations d'auto-référencement pour mon entité utilisateur.

et dans mon entité utilisateur, j'ai une méthode setChildren qui obtient ArrayCollection d'utilisateurs comme 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;
    }

}

et c'est ce que je veux faire

$new_owner = $this->userRepository->findOneById($user_id, false);

$children = $old_owner->getChildren();

$old_owner->removeChildren();
$new_owner->setChildren($children);

et j'obtiens une erreur qui dit:

L'argument 1 transmis à Proxies__CG __\UserBundle\Entity\User :: setChildren () doit être une instance de Doctrine\Common\Collections\ArrayCollection, instance de Doctrine\ORM\PersistentCollection donnée

dois-je changer mon indice de type dans la méthode setChildren en PersistentCollection ?? ou je dois changer totalement mon approche?

16
mhndev

Réponse courte:

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

    return $this;
}

Explication:

Si vous regardez en profondeur dans Doctrine Classes, vous verrez la structure suivante:

La collection de tableaux est une classe qui implémente la collection d'interfaces:

class ArrayCollection implements Collection, Selectable

PersistentCollection est une classe qui étendds AbstractLazyCollection:

final class PersistentCollection extends AbstractLazyCollection implements Selectable

mais AbstractLazyCollection implémente Collection:

abstract class AbstractLazyCollection implements Collection

Alors:

La collection est une interface que vous devez utiliser dans la méthode setChildren().

C'est à cause de doctrine utiliser le chargement paresseux - mécanisme qui permet de charger non pas toutes les propriétés, mais seulement celles-ci, qui sont nécessaires.

Question similaire:

Doctrine manyToMany retourne PersistentCollection au lieu de ArrayCollection

25
Daniel