I have 4 entities : Country, Region, Province, Town.
<?php
namespace Entities;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @Entity (repositoryClass="Repositories\Region")
* @Table(name="regions")
* @HasLifecycleCallbacks
*/
class Region {
/**
* @Id @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/** @Column(type="string", length=30,unique=TRUE) */
private $regionname;
/** @Column(type="boolean") */
private $active;
/**
* @ManyToOne(targetEntity="Country", inversedBy="regions")
* @JoinColumn(name="countries_id", referencedColumnName="id",nullable=FALSE)
*/
private $countries_id;
/**
* @OneToMany(targetEntity="Province", mappedBy="provinces")
*/
private $provinces;
public function __construct() {
$this->provinces = new ArrayCollection();
$this->active = true;
}
<?php
namespace Entities;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @Entity (repositoryClass="Repositories\Province")
* @Table(name="provinces")
* @HasLifecycleCallbacks
*/
class Province {
/**
* @Id @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/** @Column(type="string", length=30,unique=TRUE) */
private $provincename;
/** @Column(type="boolean") */
private $active;
/**
* @ManyToOne(targetEntity="Region", inversedBy="provinces")
* @JoinColumn(name="regions_id", referencedColumnName="id",nullable=FALSE)
*/
private $regions_id;
/**
* @OneToMany(targetEntity="Town", mappedBy="towns")
*/
private $towns;
public function __construct() {
$this->towns = new ArrayCollection();
$this->active = true;
}
<?php
namespace Entities;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @Entity (repositoryClass="Repositories\Town")
* @Table(name="towns")
* @HasLifecycleCallbacks
*/
class Town {
/**
* @Id @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/** @Column(type="string", length=30,unique=FALSE) */
private $townname;
/** @Column(type="boolean") */
private $active;
// so that we know when a user has added a town
/** @Column(type="boolean") */
private $verified;
/**
* @OneToMany(targetEntity="User", mappedBy="users")
*/
private $users;
/**
* @ManyToOne(targetEntity="Province", inversedBy="towns")
* @JoinColumn(name="provinces_id", referencedColumnName="id",nullable=FALSE)
*/
private $provinces_id;
public function __construct() {
$this->users = new ArrayCollection();
$this->active = true;
}
I want to create a query using DQL that will give me a list of towns for a given region.
To get a simple list of active towns I am using :
public function findActiveTowns($provinces_id = null)
// we can pass in a specific provinces_id if we want
{
$qb = $this->_em->createQueryBuilder();
$qb->select('a.townname, a.id')
->from('Entities\Town', 'a');
if (!is_null($provinces_id)){
$qb->where('a.provinces_id = :provinces_id AND a.active = TRUE')
->setParameter('provinces_id', $provinces_id);
} else {
$qb->where('a.active = TRUE');
}
$towns=$qb->getQuery()->getResult();
// make pairs array suitable for select lists
$options = array();
foreach ($towns as $key => $value) {
$options[$value['id']] = $value['townname'];
}
return $options;
}
Now, to get to the point. How do I set up the joins and get this working so that we can pass in a region_id and return all of the towns in the region.
In native SQL I'd do something like this :
SELECT towns.id
FROM `towns`
INNER JOIN `provinces`
INNER JOIN `regions`
WHERE regions.id =1
Thanks.
A few things first.
_id
, because they are not identifiers, but relations to other objects. Join column annotation goes with the real DB name, field in object model go without.As for you question, haven't tested it, but something like this should work.
class Town {
/**
* @ManyToOne(targetEntity="Province", inversedBy="towns")
* @JoinColumn(name="provinces_id", referencedColumnName="id",nullable=FALSE)
*/
private $province;
class Province {
/**
* @ManyToOne(targetEntity="Region", inversedBy="provinces")
* @JoinColumn(name="regions_id", referencedColumnName="id",nullable=FALSE)
*/
private $region;
$qb->select('a.townname, a.id')
->from('Entities\Town', 'a')
->leftJoin('a.province', 'p');
if (!is_null($provinces_id) && !is_null($region_id)){
$qb->where('a.province = :province AND a.active = TRUE')
->andWhere('p.region = :region')
->setParameter('province', $provinces_id)
->setParameter('region', $region_id);
} else {
$qb->where('a.active = TRUE');
}