1

I have the following tables, where I have no problem in inserting, updating etc. But, how can I fetch the result rows for this kind of mapping?

Organizations
-->id
-->name

users
-->id
-->first_name

doctors
-->id
-->user_id


org_doctors
-->id
-->org_id
-->doctor_id

This is my OrgDoctor Entity:

<?php
namespace Doctor\Entity;
use Doctrine\ORM\Mapping as ORM;
use Library\Entity\BaseEntity;
use User\Entity\User;
use Doctor\Entity\Doctor;
use Organization\Entity\Organization;

/**
 * @ORM\Entity
 * @ORM\Table(name="org_doctors")
 */
class OrgDoctor extends BaseEntity{

    /**
     * @ORM\ManyToOne(targetEntity="Doctor\Entity\Doctor", inversedBy="orgDoctor")
     * @ORM\JoinColumn(name="doctor_id",referencedColumnName="id",nullable=false)
     */
    protected $doctor;

    /**
     * @ORM\ManyToOne(targetEntity="Organization\Entity\Organization", inversedBy="orgDoctor")
     * @ORM\JoinColumn(name="org_id", referencedColumnName="id", nullable=false)
     */
    protected $organization;

    public function setDoctor(Doctor $doctor = null)
    {
        $this->doctor = $doctor;

        return $this;
    }

    public function getDoctor()
    {
        return $this->doctor;
    } 

    public function setOrganization(Organization $organization = null)
    {
        $this->organization = $organization;

        return $this;
    }

    public function getOrganization()
    {
        return $this->organization;
    }    
}

And this is my Doctor Entity:

<?php
namespace Doctor\Entity;

use Library\Entity\BaseEntity;
use Users\Entity\User;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="doctors")
 */
class Doctor extends BaseEntity {

    /**
     * @ORM\OneToOne(targetEntity="Users\Entity\User")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)
     * @var Users\Entity\User
     */
    private $user;

    /**
     * @ORM\Column(name="summary", type="string")
     * @var string
     */
    private $summary;

    function getUser() {
        return $this->user;
    }

    function setUser(User $user) {
        $this->user = $user;
    }

     function getSummary() {
        return $this->summary;
    }

    function setSummary($summary) {
        $this->summary = $summary;
    }
}

This is how I'm fetching the result for a single doctor:

$doctor = $this->entityManager->find('Doctor\Entity\Doctor', (int) $doctorId);

How can I fetch rows from the OrgDoctor entity?

this is how i tried using queryBuilder:

$qb = $this->entityManager->createQueryBuilder();
        $qb->select('od', 'd', 'o')
            ->from('Doctor\Entity\OrgDoctor', 'od')
            ->join('od.organization', 'o')
            ->join('od.doctor', 'd')
            ->where('od.organization = :organization')
            ->setParameter('organization', $orgId);
        $query = $qb->getQuery();
        $results =  $query->getResult();
        var_dump($results);

 Notice: Undefined index: orgDoctor in C:\xampp\htdocs\corporate-wellness\vendor\doctrine\orm\lib\Doctrine\ORM\Internal\Hydration\ObjectHydrator.php on line 125

In Organization Entity:

     /**
     * @ORM\OneToMany(targetEntity="Doctor\Entity\OrgDoctor", mappedBy="organization")
     */
    protected $orgDoctor;
user3929758
  • 233
  • 2
  • 3
  • 15

1 Answers1

1

Given your entity mapping, Doctrine should provide you with an out of the box repository for your OrgDoctor entity. That repository implements a few methods for you to retrieve entities of that type. One of them is findBy, which return arrays of OrgDoctor entities:

$this->getEntityManager()->getRepository(OrgDoctor::class)->findBy(['doctor' => $doctorId]));

$this->getEntityManager()->getRepository(OrgDoctor::class)->findBy(['organization' => $organizationId]));

$this->getEntityManager()->getRepository(OrgDoctor::class)->findBy(['doctor' => $doctorId, 'organization' => $organizationId]));

The last example, would be quite similar to findOneBy, which would return an OrgDoctor entity instead of an array:

$this->getEntityManager()->getRepository(OrgDoctor::class)->findOneBy(['doctor' => $doctorId, 'organization' => $organizationId]));

If you're planning to loop through the results and access their properties or other relationships, you might want to change the default repository strategy and define a custom repository for your OrgDoctor entity. What this will allow you to do, is to write your custom queries for retrieving your entities by means of a query builder class and DQL.

In order to avoid N+1 problems, you want to fetch join before a loop to fetch all the necessary associations in one go, so you won't be running N queries within your loop:

$qb->select('od', 'd', 'o')
   ->from(OrgDoctor::class, 'od')
   ->join('od.organization', 'o')
   ->join('od.doctor', 'd')
   ->where('od.doctor = :doctor')
   ->setParameter('doctor', $doctorId)
;
Community
  • 1
  • 1
hasumedic
  • 2,139
  • 12
  • 17
  • Thanks bro, it only return the org_id and doctor_id and remaining objects return as null. that means shall i need to once again findBy(doctorId) in the Doctor Entity and find(orgId) in Org Entity – user3929758 Feb 18 '16 at 18:34
  • What do you mean that they return org_id and doctor_id? They should return either an OrgDoctor array (findBy) or an OrgDoctor object (findOneBy). Once the entity is hydrated, you should be able to do $organizationDoctor->getDoctor() and $organizationDoctor->getOrganization() to obtain the objects. The ORM will do the heavy lifting for you. – hasumedic Feb 18 '16 at 19:49
  • As you said, if i use $organizationDoctor->getDoctor() and $organizationDoctor->getOrganization() to obtain the objects, wont it be heavy for me. – user3929758 Feb 19 '16 at 07:38
  • Wont it be heavy lifting for me, if i do like this, $orgDoctors = $this->entityManager->getRepository('Doctor\Entity\OrgDoctor') ->findBy(['organization' => $orgId]); //returns 200 rows od data $resArr = array(); foreach($orgDoctors as $doc) { $resArr = array ( 'orgName' => $doc->getOrganization()->getName(), 'doctorId' => $doc->getDoctor()->getId(), 'doctorName' => $doc->getDoctor()->getName(), ); } – user3929758 Feb 19 '16 at 07:42
  • @haumedic Do i need to use, any left join, this is my raw sql --> SELECT od.org_id, od.doctor_id, od.is_active as orgDoctorIsActive, d.user_id, u.first_name as firstName, u.last_name as lastName, u.email_id as emailId, u.contact_number as contactNumber FROM org_doctors od LEFT JOIN doctors d ON od.doctor_id = d.id LEFT JOIN users u ON d.user_id = u.id WHERE od.org_id = 1 – user3929758 Feb 19 '16 at 11:06
  • You can do left joins if you want, but I doubt that you'd have OrgDoctor entities without a Doctor or an Organization. – hasumedic Feb 19 '16 at 11:13
  • Thanks for the support, $qb = $this->entityManager->createQueryBuilder(); $qb->select('od', 'd', 'o') ->from('Doctor\Entity\OrgDoctor', 'od') ->join('od.organization', 'o') ->join('od.doctor', 'd') ->where('od.organization = :organization') ->setParameter('organization', $orgId); $query = $qb->getQuery(); $results = $query->getResult(); var_dump($results); exit; – user3929758 Feb 19 '16 at 11:23
  • I am getting the following error for the above comment... Notice: Undefined index: orgDoctor in C:\xampp\htdocs\corporate-wellness\vendor\doctrine\orm\lib\Doctrine\ORM\Internal\Hydration\ObjectHydrator.php on line 125 – user3929758 Feb 19 '16 at 11:24
  • That's because your relationships are not properly defined. There's no "orgDoctor" inversedBy relationship in your Doctor or Organization entities. But that's outside of the scope of what your original question was. – hasumedic Feb 19 '16 at 11:36
  • /** * @ORM\OneToMany(targetEntity="Doctor\Entity\OrgDoctor", mappedBy="organization") */ protected $orgDoctor; //In Organization Entity – user3929758 Feb 19 '16 at 11:41
  • Thanks man, its works like a charm now, I forgot to add a inverse relationship in Doctor Entity. – user3929758 Feb 19 '16 at 11:49
  • Glad it's working. You might consider up-voting and accepting the answer then ;) – hasumedic Feb 19 '16 at 11:51