简体   繁体   中英

Doctrine @OneToMany relation doesn't return Collection

I'm using Symfony 2.7 with Doctrine 2. When using a OneToMany relation, the property remains empty.

Context

I'm trying to create a filter so that only that only employees that are currently employed at an organisation are able to see the entities related to that organisation. (I've already created a filter with an organisation hard coded, that works).

I've created en Employee entity with a ManyToOne relation to User, a ManyToOne relation to Organisation, a joindate and a leavedate. The user has a (inverse) OneToMany relation to Employee. When I call $user->getEmployees() I get no results.

Expected result

When calling $user->getEmployees() I expect to get a collection of the three Employee entities that are currently stored in the database with my user_id.

Actual result

An empty collection is returned, part of the 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]

Other info

Searching on Doctrine @OneToMany gives me people that have forgotten some parameters, arguments etc. or made a typo. My college and me cannot find one of those in my code. So I'm kind of stuck. Please Help.

composer.json (part of):

"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 (this is the configuration of the filter)

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

I am not sure if it is causing the issue. But it is for sure not helping. In User you do:

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

    return $this;
}

It should be $employee->setUser($this);

And another thing. You do:

function setEmployees($employees)
{
    foreach ($employees as $employee)
    {
        $this->addEmployee($employee);
    }
}

Collections are set using add methods, not set methods. So you should do:

function addEmployees($employees)
{
    foreach ($employees as $employee)
    {
        $this->addEmployee($employee);
    }
    return $this;
}

When I'm doing

var_dump(sizeof($employeeCollection));

I'm getting the expected result 3.

Lesson learned: The iterator of an colletion is lazy. Do something with it go fill it.

For example:

    var_dump(sizeof($employeeCollection));
    var_dump($employeeCollection);

Gives the expected result:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM