Symfony ArrayCollection 与 PersistentCollection
Posted
技术标签:
【中文标题】Symfony ArrayCollection 与 PersistentCollection【英文标题】:Symfony ArrayCollection vs PersistentCollection 【发布时间】:2016-09-25 18:20:21 【问题描述】:据我了解,当您按存储库查询数据库时,您会得到 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);
我收到错误消息:
参数 1 传递给 Proxies__CG__\UserBundle\Entity\User::setChildren() 必须是 Doctrine\Common\Collections\ArrayCollection 的实例, 给定的 Doctrine\ORM\PersistentCollection
我应该将 setChildren 方法中的类型提示更改为 PersistentCollection 吗? 还是我需要彻底改变我的方法?
【问题讨论】:
你的 $this->children 怎么样;在你的模型中?我可以有这两个模型吗? 我更新了上面的代码,以便您可以看到属性及其注释。两个模型都来自用户实体。这是一个自引用关系。 尝试添加public function __construct() $this->children = new ArrayCollection();
我已经这样做了! :) 它只是没有出现在我的代码中
好吧,我无法理解 :) 你的控制器和完整模型中的完整方法看起来如何?
【参考方案1】:
在您的输入中添加 Collection $children
使用 Doctrine\Common\Collections\Collection; ...
private ?Collection $children;
symfony:5.3
【讨论】:
【参考方案2】:简答:
/**
* @param Doctrine\Common\Collections\Collection $users
* @return $this
*/
public function setChildren(Doctrine\Common\Collections\Collection $users)
$this->children = $users;
return $this;
解释:
如果您深入研究 Doctrine Classes,您会看到以下结构:
数组集合是实现接口Collection的类:
class ArrayCollection implements Collection, Selectable
PersistentCollection 是扩展 AbstractLazyCollection 的类:
final class PersistentCollection extends AbstractLazyCollection implements Selectable
但是 AbstractLazyCollection 实现了 Collection:
abstract class AbstractLazyCollection implements Collection
所以:
集合是接口,你应该在方法setChildren()
中使用。
这是因为原则上使用延迟加载 - 允许加载并非所有属性的机制,而仅允许加载需要的这些属性。
类似的问题:
Doctrine manyToMany return PersistentCollection instead of ArrayCollection
【讨论】:
以上是关于Symfony ArrayCollection 与 PersistentCollection的主要内容,如果未能解决你的问题,请参考以下文章
Symfony 3,ArrayCollection的remove()导致错误“警告:isset中的非法偏移类型或为空”
在 Symfony 中通过 ajax 为 ArrayCollection 数据传递 POST json 对象
Symfony 2,未定义的变量,在构造函数中初始化为 ArrayCollection 的受保护成员通过错误,它是未定义的
Symfony-Catchable致命错误:传递给Doctrine Common Collections ArrayCollection :: __ construct()的参数1必须是类(代码