【问题标题】:Doctrine @OneToMany relation doesn't return Collection教义@OneToMany 关系不返回集合
【发布时间】:2016-01-18 09:59:54
【问题描述】:

我将 Symfony 2.7 与 Doctrine 2 一起使用。当使用 OneToMany 关系时,该属性保持为空。

上下文

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

我已经创建了一个与用户的多对一关系、与组织的多对一关系、一个加入日期和一个离开日期的 Employee 实体。用户与 Employee 具有(反向)OneToMany 关系。当我调用 $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]

其他信息

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

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

【问题讨论】:

  • 只是在黑暗中快速拍摄。您的员工数据库表是否正确命名为“员工”(即大写)?
  • 您是否检查过您的用户是否确实在数据库中连接了员工(正确链接并保存)...有时会发生:P ...您是否使用自动生成器来创建实体和关系?
  • @technetium 您是如何在 User.php 中实现所有这些方法的。我的意思是这是基于 Doctrine 文档的一些广泛使用的实现,还是只是您的工作?我的意思是要获得相关的实体需要做很多工作。我的意思是它一定是开发人员广泛需要的东西,我不敢相信这个实现没有神奇的替代方案。你怎么看?

标签: php symfony doctrine-orm doctrine one-to-many


【解决方案1】:

我不确定是否是导致问题的原因。但这肯定没有帮助。在User 你这样做:

public function addEmployee(\AppBundle\Entity\User $employee)
{
    $employee->setOrganisation($this);
    $this->employees[] = $employee;

    return $this;
}

应该是$employee-&gt;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;
}

【讨论】:

  • 感谢您的反应。我的印象是函数 addEmployee($employee) 是将一名员工添加到集合中,并且使用 setEmployees 可以设置整个集合。我已经实施了您的建议,但仍然得到相同的(空的)响应。
  • 当你做$entityManager-&gt;getRepository('AppBundle\Entity\Employee')-&gt;findAll();时你得到你的员工吗@
  • 是的,var_dump($this->em->getRepository('AppBundle\Entity\Employee')->findAll());显示数据库中的所有员工。
【解决方案2】:

当我在做的时候

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-03
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多