Doctrine @OneToMany 关系不 return 集合
Doctrine @OneToMany relation doesn't return Collection
我正在使用带有 Doctrine 2 的 Symfony 2.7。当使用 OneToMany 关系时,属性 保持为空。
上下文
我正在尝试创建一个过滤器,以便只有当前受雇于某个组织的员工才能看到与该组织相关的实体。 (我已经创建了一个过滤器,其中包含一个硬编码的组织,有效)。
我创建了 en Employee 实体,该实体具有与用户的 ManyToOne 关系、与组织的 ManyToOne 关系、joindate 和 leavedate。用户与 Employee 具有(反向)OneToMany 关系。当我调用 $user->getEmployees() 时,我没有得到任何结果。
预期结果
当调用 $user->getEmployees() 时,我希望获得当前存储在数据库中的三个 Employee 实体的集合以及我的 user_id.
实际结果
返回一个空集合,var_dump
的一部分
object(Doctrine\ORM\PersistentCollection)[83]
private 'snapshot' =>
array (size=0)
empty
private 'owner' =>
object(AppBundle\Entity\User)[342]
protected 'id' => int 1
protected 'groups' =>
object(Doctrine\ORM\PersistentCollection)[52]
private 'snapshot' =>
array (size=0)
...
private 'owner' =>
&object(AppBundle\Entity\User)[342]
private 'association' =>
array (size=19)
...
private 'em' =>
object(Doctrine\ORM\EntityManager)[282]
...
private 'backRefFieldName' => null
private 'typeClass' =>
object(Doctrine\ORM\Mapping\ClassMetadata)[42]
...
private 'isDirty' => boolean false
private 'initialized' => boolean false
private 'coll' =>
object(Doctrine\Common\Collections\ArrayCollection)[41]
...
protected 'employees' =>
&object(Doctrine\ORM\PersistentCollection)[83]
其他信息
在 Doctrine @OneToMany 上搜索给我的人忘记了一些参数、参数等或打错了字。我和我的大学在我的代码中找不到其中之一。所以我有点卡住了。请帮助。
composer.json(部分):
"require" : {
"php" : ">=5.3.9",
"symfony/symfony" : "2.7.*",
"doctrine/orm" : "~2.2,>=2.2.3,<2.5",
"doctrine/dbal" : "<2.5",
"doctrine/doctrine-bundle" : "~1.4",
"symfony/assetic-bundle" : "~2.3",
"symfony/swiftmailer-bundle" : "~2.3",
"symfony/monolog-bundle" : "~2.4",
"sensio/distribution-bundle" : "~4.0",
"sensio/framework-extra-bundle" : "~3.0,>=3.0.2",
"incenteev/composer-parameter-handler" : "~2.0",
"friendsofsymfony/user-bundle" : "~2.0@dev",
"stof/doctrine-extensions-bundle" : "^1.2",
"sonata-project/admin-bundle" : "^2.3",
"sonata-project/doctrine-orm-admin-bundle" : "^2.3",
"sonata-project/translation-bundle" : "1.0.0",
"doctrine/doctrine-fixtures-bundle" : "^2.3"
},
Configuration.php(这是过滤器的配置)
<?php
namespace AppBundle\Filter;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\Annotations\Reader;
use Doctrine\Common\Collections\Criteria;
use AppBundle\Entity\Employee;
class Configurator
{
protected $em;
protected $tokenStorage;
protected $reader;
public function __construct(ObjectManager $em, TokenStorageInterface $tokenStorage, Reader $reader)
{
$this->em = $em;
$this->tokenStorage = $tokenStorage;
$this->reader = $reader;
}
public function onKernelRequest()
{
if ($user = $this->getUser()) {
$filter = $this->em->getFilters()->enable('organisation');
$user_id = $user->getId();
print "User id: $user_id<br />\n"; // Just to check I can get the user_id, that works
$employeeCollection = $user->getEmployees(); // Get the Employees
var_dump($employeeCollection); // Oeps, no result
die(); // Let's just quit (for now)
// To Do find out all the organisation id's
// $filter->setParameter('organisation_ids', $organisation_ids);
}
}
private function getUser()
{
$token = $this->tokenStorage->getToken();
if (!$token) {
return null;
}
$user = $token->getUser();
if (!($user instanceof UserInterface)) {
return null;
}
return $user;
}
}
User.php
<?php
// src/AppBundle/Entity/User.php
namespace AppBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Group")
* @ORM\JoinTable(name="fos_user_group",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
protected $groups;
/**
* @var Collection
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Employee", mappedBy="user", cascade="persist")
*/
protected $employees;
public function __construct()
{
$this->employees = new \Doctrine\Common\Collections\ArrayCollection();
parent::__construct();
}
public function prePersist($user)
{
parent::prePersist($user);
$user->setEmplolyees($user->getEmployees());
}
public function preUpdate($user)
{
parent::preUpdate($user);
$user->setEmplolyees($user->getEmployees());
}
/**
* Add employees
*
* @param \AppBundle\Entity\User $employee
* @return Organisation
*/
public function addEmployee(\AppBundle\Entity\User $employee)
{
$employee->setOrganisation($this);
$this->employees[] = $employee;
return $this;
}
function setEmployees($employees)
{
foreach ($employees as $employee)
{
$this->addEmployee($employee);
}
}
/**
* Remove employee
*
* @param \AppBundle\Entity\User $employee
*/
public function removeEmployee(\AppBundle\Entity\User $employee)
{
$this->employees->removeElement($employee);
}
/**
* Get employees
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getEmployees()
{
return $this->employees;
}
}
Employee.php
<?php
// src/AppBundle/Entity/User.php
namespace AppBundle\Entity;
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
// use Doctrine\ORM\EntityManager;
use Gedmo\Mapping\Annotation as Gedmo;
use AppBundle\Annotation as CRUD;
/**
* @ORM\Entity
* @ORM\HasLifecycleCallbacks
* @Gedmo\SoftDeleteable(fieldName="deleted")
* @Gedmo\Loggable
*/
class Employee {
/**
* @ORM\Id
* @ORM\Column(type="guid")
* @ORM\GeneratedValue(strategy="UUID")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="employees")
*/
private $user;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Organisation", inversedBy="employees")
*/
private $organisation;
/**
* @ORM\Column(type="date")
*/
private $joindate;
/**
* @ORM\Column(type="date", nullable=true)
*/
private $leavedate;
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="create")
*
*/
private $created;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $deleted;
public function __toString()
{
return $this->user . ' - ' . $this->organisation . ' (' . print_r($this->getJoindate(),1);
}
/**
* Set created
*
* @param \DateTime $created
* @return Employee
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* @return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set deleted
*
* @param \DateTime $deleted
* @return Employee
*/
public function setDeleted($deleted)
{
$this->deleted = $deleted;
return $this;
}
/**
* Get deleted
*
* @return \DateTime
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Get id
*
* @return guid
*/
public function getId()
{
return $this->id;
}
/**
* Set user
*
* @param \AppBundle\Entity\User $user
* @return Employee
*/
public function setUser(\AppBundle\Entity\User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* @return \AppBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
/**
* Set organisation
*
* @param \AppBundle\Entity\Organisation $organisation
* @return Employee
*/
public function setOrganisation(\AppBundle\Entity\Organisation $organisation = null)
{
$this->organisation = $organisation;
return $this;
}
/**
* Get organisation
*
* @return \AppBundle\Entity\Organisation
*/
public function getOrganisation()
{
return $this->organisation;
}
/**
* Set joindate
*
* @param \DateTime $joindate
* @return Employee
*/
public function setJoindate($joindate)
{
$this->joindate = $joindate;
return $this;
}
/**
* Get joindate
*
* @return \DateTime
*/
public function getJoindate()
{
return $this->joindate;
}
/**
* Set leavedate
*
* @param \DateTime $leavedate
* @return Employee
*/
public function setleavedate($leavedate)
{
$this->leavedate = $leavedate;
return $this;
}
/**
* Get leavedate
*
* @return \DateTime
*/
public function getleavedate()
{
return $this->leavedate;
}
}
我不确定是否是它导致了问题。但这肯定无济于事。在 User
你做:
public function addEmployee(\AppBundle\Entity\User $employee)
{
$employee->setOrganisation($this);
$this->employees[] = $employee;
return $this;
}
应该是$employee->setUser($this);
还有一件事。你这样做:
function setEmployees($employees)
{
foreach ($employees as $employee)
{
$this->addEmployee($employee);
}
}
集合是使用 add
方法设置的,而不是 set
方法。所以你应该这样做:
function addEmployees($employees)
{
foreach ($employees as $employee)
{
$this->addEmployee($employee);
}
return $this;
}
当我在做的时候
var_dump(sizeof($employeeCollection));
我得到了预期的结果 3。
经验教训:集合的迭代器是惰性的。用它做点什么去填满它。
例如:
var_dump(sizeof($employeeCollection));
var_dump($employeeCollection);
给出预期结果:
int 3
object(Doctrine\ORM\PersistentCollection)[85]
private 'snapshot' =>
array (size=3)
0 =>
object(AppBundle\Entity\Employee)[94]
private 'id' => string '0426c0cc-b517-11e5-8f2e-080027434d34' (length=36)
private 'user' =>
object(AppBundle\Entity\User)[339]
...
private 'organisation' =>
object(Proxies\__CG__\AppBundle\Entity\Organisation)[129]
...
private 'joindate' =>
object(DateTime)[104]
...
private 'leavedate' => null
private 'created' =>
object(DateTime)[96]
...
private 'deleted' => null
1 =>
object(AppBundle\Entity\Employee)[127]
private 'id' => string '74ca2b62-bac6-11e5-b9ab-080027434d34' (length=36)
private 'user' =>
object(AppBundle\Entity\User)[339]
...
private 'organisation' =>
object(Proxies\__CG__\AppBundle\Entity\Organisation)[122]
...
private 'joindate' =>
object(DateTime)[125]
...
private 'leavedate' => null
private 'created' =>
object(DateTime)[126]
...
private 'deleted' => null
2 =>
object(AppBundle\Entity\Employee)[119]
private 'id' => string 'c1e45d7f-b53e-11e5-8f2e-080027434d34' (length=36)
private 'user' =>
object(AppBundle\Entity\User)[339]
...
private 'organisation' =>
object(Proxies\__CG__\AppBundle\Entity\Organisation)[118]
...
private 'joindate' =>
object(DateTime)[130]
...
private 'leavedate' => null
private 'created' =>
object(DateTime)[124]
...
private 'deleted' => null
private 'owner' =>
object(AppBundle\Entity\User)[339]
protected 'id' => int 1
我正在使用带有 Doctrine 2 的 Symfony 2.7。当使用 OneToMany 关系时,属性 保持为空。
上下文
我正在尝试创建一个过滤器,以便只有当前受雇于某个组织的员工才能看到与该组织相关的实体。 (我已经创建了一个过滤器,其中包含一个硬编码的组织,有效)。
我创建了 en Employee 实体,该实体具有与用户的 ManyToOne 关系、与组织的 ManyToOne 关系、joindate 和 leavedate。用户与 Employee 具有(反向)OneToMany 关系。当我调用 $user->getEmployees() 时,我没有得到任何结果。
预期结果
当调用 $user->getEmployees() 时,我希望获得当前存储在数据库中的三个 Employee 实体的集合以及我的 user_id.
实际结果
返回一个空集合,var_dump
的一部分object(Doctrine\ORM\PersistentCollection)[83]
private 'snapshot' =>
array (size=0)
empty
private 'owner' =>
object(AppBundle\Entity\User)[342]
protected 'id' => int 1
protected 'groups' =>
object(Doctrine\ORM\PersistentCollection)[52]
private 'snapshot' =>
array (size=0)
...
private 'owner' =>
&object(AppBundle\Entity\User)[342]
private 'association' =>
array (size=19)
...
private 'em' =>
object(Doctrine\ORM\EntityManager)[282]
...
private 'backRefFieldName' => null
private 'typeClass' =>
object(Doctrine\ORM\Mapping\ClassMetadata)[42]
...
private 'isDirty' => boolean false
private 'initialized' => boolean false
private 'coll' =>
object(Doctrine\Common\Collections\ArrayCollection)[41]
...
protected 'employees' =>
&object(Doctrine\ORM\PersistentCollection)[83]
其他信息
在 Doctrine @OneToMany 上搜索给我的人忘记了一些参数、参数等或打错了字。我和我的大学在我的代码中找不到其中之一。所以我有点卡住了。请帮助。
composer.json(部分):
"require" : {
"php" : ">=5.3.9",
"symfony/symfony" : "2.7.*",
"doctrine/orm" : "~2.2,>=2.2.3,<2.5",
"doctrine/dbal" : "<2.5",
"doctrine/doctrine-bundle" : "~1.4",
"symfony/assetic-bundle" : "~2.3",
"symfony/swiftmailer-bundle" : "~2.3",
"symfony/monolog-bundle" : "~2.4",
"sensio/distribution-bundle" : "~4.0",
"sensio/framework-extra-bundle" : "~3.0,>=3.0.2",
"incenteev/composer-parameter-handler" : "~2.0",
"friendsofsymfony/user-bundle" : "~2.0@dev",
"stof/doctrine-extensions-bundle" : "^1.2",
"sonata-project/admin-bundle" : "^2.3",
"sonata-project/doctrine-orm-admin-bundle" : "^2.3",
"sonata-project/translation-bundle" : "1.0.0",
"doctrine/doctrine-fixtures-bundle" : "^2.3"
},
Configuration.php(这是过滤器的配置)
<?php
namespace AppBundle\Filter;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\Annotations\Reader;
use Doctrine\Common\Collections\Criteria;
use AppBundle\Entity\Employee;
class Configurator
{
protected $em;
protected $tokenStorage;
protected $reader;
public function __construct(ObjectManager $em, TokenStorageInterface $tokenStorage, Reader $reader)
{
$this->em = $em;
$this->tokenStorage = $tokenStorage;
$this->reader = $reader;
}
public function onKernelRequest()
{
if ($user = $this->getUser()) {
$filter = $this->em->getFilters()->enable('organisation');
$user_id = $user->getId();
print "User id: $user_id<br />\n"; // Just to check I can get the user_id, that works
$employeeCollection = $user->getEmployees(); // Get the Employees
var_dump($employeeCollection); // Oeps, no result
die(); // Let's just quit (for now)
// To Do find out all the organisation id's
// $filter->setParameter('organisation_ids', $organisation_ids);
}
}
private function getUser()
{
$token = $this->tokenStorage->getToken();
if (!$token) {
return null;
}
$user = $token->getUser();
if (!($user instanceof UserInterface)) {
return null;
}
return $user;
}
}
User.php
<?php
// src/AppBundle/Entity/User.php
namespace AppBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Group")
* @ORM\JoinTable(name="fos_user_group",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
protected $groups;
/**
* @var Collection
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Employee", mappedBy="user", cascade="persist")
*/
protected $employees;
public function __construct()
{
$this->employees = new \Doctrine\Common\Collections\ArrayCollection();
parent::__construct();
}
public function prePersist($user)
{
parent::prePersist($user);
$user->setEmplolyees($user->getEmployees());
}
public function preUpdate($user)
{
parent::preUpdate($user);
$user->setEmplolyees($user->getEmployees());
}
/**
* Add employees
*
* @param \AppBundle\Entity\User $employee
* @return Organisation
*/
public function addEmployee(\AppBundle\Entity\User $employee)
{
$employee->setOrganisation($this);
$this->employees[] = $employee;
return $this;
}
function setEmployees($employees)
{
foreach ($employees as $employee)
{
$this->addEmployee($employee);
}
}
/**
* Remove employee
*
* @param \AppBundle\Entity\User $employee
*/
public function removeEmployee(\AppBundle\Entity\User $employee)
{
$this->employees->removeElement($employee);
}
/**
* Get employees
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getEmployees()
{
return $this->employees;
}
}
Employee.php
<?php
// src/AppBundle/Entity/User.php
namespace AppBundle\Entity;
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
// use Doctrine\ORM\EntityManager;
use Gedmo\Mapping\Annotation as Gedmo;
use AppBundle\Annotation as CRUD;
/**
* @ORM\Entity
* @ORM\HasLifecycleCallbacks
* @Gedmo\SoftDeleteable(fieldName="deleted")
* @Gedmo\Loggable
*/
class Employee {
/**
* @ORM\Id
* @ORM\Column(type="guid")
* @ORM\GeneratedValue(strategy="UUID")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="employees")
*/
private $user;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Organisation", inversedBy="employees")
*/
private $organisation;
/**
* @ORM\Column(type="date")
*/
private $joindate;
/**
* @ORM\Column(type="date", nullable=true)
*/
private $leavedate;
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="create")
*
*/
private $created;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $deleted;
public function __toString()
{
return $this->user . ' - ' . $this->organisation . ' (' . print_r($this->getJoindate(),1);
}
/**
* Set created
*
* @param \DateTime $created
* @return Employee
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* @return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set deleted
*
* @param \DateTime $deleted
* @return Employee
*/
public function setDeleted($deleted)
{
$this->deleted = $deleted;
return $this;
}
/**
* Get deleted
*
* @return \DateTime
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* Get id
*
* @return guid
*/
public function getId()
{
return $this->id;
}
/**
* Set user
*
* @param \AppBundle\Entity\User $user
* @return Employee
*/
public function setUser(\AppBundle\Entity\User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* @return \AppBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
/**
* Set organisation
*
* @param \AppBundle\Entity\Organisation $organisation
* @return Employee
*/
public function setOrganisation(\AppBundle\Entity\Organisation $organisation = null)
{
$this->organisation = $organisation;
return $this;
}
/**
* Get organisation
*
* @return \AppBundle\Entity\Organisation
*/
public function getOrganisation()
{
return $this->organisation;
}
/**
* Set joindate
*
* @param \DateTime $joindate
* @return Employee
*/
public function setJoindate($joindate)
{
$this->joindate = $joindate;
return $this;
}
/**
* Get joindate
*
* @return \DateTime
*/
public function getJoindate()
{
return $this->joindate;
}
/**
* Set leavedate
*
* @param \DateTime $leavedate
* @return Employee
*/
public function setleavedate($leavedate)
{
$this->leavedate = $leavedate;
return $this;
}
/**
* Get leavedate
*
* @return \DateTime
*/
public function getleavedate()
{
return $this->leavedate;
}
}
我不确定是否是它导致了问题。但这肯定无济于事。在 User
你做:
public function addEmployee(\AppBundle\Entity\User $employee)
{
$employee->setOrganisation($this);
$this->employees[] = $employee;
return $this;
}
应该是$employee->setUser($this);
还有一件事。你这样做:
function setEmployees($employees)
{
foreach ($employees as $employee)
{
$this->addEmployee($employee);
}
}
集合是使用 add
方法设置的,而不是 set
方法。所以你应该这样做:
function addEmployees($employees)
{
foreach ($employees as $employee)
{
$this->addEmployee($employee);
}
return $this;
}
当我在做的时候
var_dump(sizeof($employeeCollection));
我得到了预期的结果 3。
经验教训:集合的迭代器是惰性的。用它做点什么去填满它。
例如:
var_dump(sizeof($employeeCollection));
var_dump($employeeCollection);
给出预期结果:
int 3
object(Doctrine\ORM\PersistentCollection)[85]
private 'snapshot' =>
array (size=3)
0 =>
object(AppBundle\Entity\Employee)[94]
private 'id' => string '0426c0cc-b517-11e5-8f2e-080027434d34' (length=36)
private 'user' =>
object(AppBundle\Entity\User)[339]
...
private 'organisation' =>
object(Proxies\__CG__\AppBundle\Entity\Organisation)[129]
...
private 'joindate' =>
object(DateTime)[104]
...
private 'leavedate' => null
private 'created' =>
object(DateTime)[96]
...
private 'deleted' => null
1 =>
object(AppBundle\Entity\Employee)[127]
private 'id' => string '74ca2b62-bac6-11e5-b9ab-080027434d34' (length=36)
private 'user' =>
object(AppBundle\Entity\User)[339]
...
private 'organisation' =>
object(Proxies\__CG__\AppBundle\Entity\Organisation)[122]
...
private 'joindate' =>
object(DateTime)[125]
...
private 'leavedate' => null
private 'created' =>
object(DateTime)[126]
...
private 'deleted' => null
2 =>
object(AppBundle\Entity\Employee)[119]
private 'id' => string 'c1e45d7f-b53e-11e5-8f2e-080027434d34' (length=36)
private 'user' =>
object(AppBundle\Entity\User)[339]
...
private 'organisation' =>
object(Proxies\__CG__\AppBundle\Entity\Organisation)[118]
...
private 'joindate' =>
object(DateTime)[130]
...
private 'leavedate' => null
private 'created' =>
object(DateTime)[124]
...
private 'deleted' => null
private 'owner' =>
object(AppBundle\Entity\User)[339]
protected 'id' => int 1