教义@OneToMany关系不会返回集合


Doctrine @OneToMany relation doesn't return Collection

我正在使用Symfony 2.7和Doctrine 2。使用一对多关系时,该属性将保持为空。

上下文

我正在尝试创建一个过滤器,以便只有当前受雇于某个组织的员工才能看到与该组织相关的实体。(我已经创建了一个带有硬编码的组织过滤器,可以工作)。

我创建了 en 员工实体 与用户有 ManyToOne 关系,与组织有 ManyToOne 关系,加入日期和休假日期。用户与员工有(反向)一对多关系。当我调用$user->getEmployees()时,我没有得到任何结果。

预期成果

调用 $user->getEmployees() 时,我希望通过我的user_id获取当前存储在数据库中的三个 Employee 实体的集合。

实际结果

返回一个空集合,这是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]

其他信息

搜索教义@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"
},

配置.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;
    }
}

用户.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;
    }
}

员工.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