Symfony ArrayCollection vs PersistentCollection

2022-08-30 17:09:04

正如我所理解的,当你按存储库查询数据库时,你会得到PersistentCollection,当你使用你的实体时,你会得到ArrayCollection。

因此,请考虑我为我的用户实体提供一对多的自我引用关系。

在我的用户实体中,我有一个 setChildren 方法,该方法获取用户的 ArrayCollection 作为参数。

<?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;
    }

}

这就是我想做的

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

$children = $old_owner->getChildren();

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

我得到错误,说:

传递给Proxies__CG__\UserBundle\Entity\User::setChildren() 的参数 1 必须是 Doctrine\Common\Collections\ArrayCollection 的实例,给出 Doctrine\ORM\PersistentCollection 的实例

我应该将 setChildren 方法中的类型提示更改为 PersistentCollection 吗?或者我需要完全改变我的方法?


答案 1

简短的回答:

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

    return $this;
}

解释:

如果你深入研究教义类,你会看到以下结构:

数组集合是实现接口集合的类:

class ArrayCollection implements Collection, Selectable

PersistentCollection是扩展 AbstractLazyCollection 的类:

final class PersistentCollection extends AbstractLazyCollection implements Selectable

但是 AbstractLazyCollection 实现了 Collection:

abstract class AbstractLazyCollection implements Collection

所以:

集合是接口,应在方法中使用。setChildren()

这是因为原则上使用延迟加载 - 允许加载不是所有属性,而只允许加载所需的这些属性。

类似的问题:

Doctrine manyToMany 返回 PersistentCollection 而不是 ArrayCollection


答案 2

在键入中添加集合$children

使用教义\共同\收藏\收藏;...

私人?收集$children;

符号: 5.3


推荐