简体   繁体   English

如何在Doctrine2 QueryBuilder上合并多个实体

[英]How can I hydrate multiple entities on Doctrine2 QueryBuilder

I have a symfony2 application using Doctrine2, and some entities for City, State, Country, Address. 我有一个使用Doctrine2的symfony2应用程序,以及一些用于城市,州,国家/地区,地址的实体。

The problem is that if I do this: 问题是,如果我这样做:

    $queryBuilder = $this->em->createQueryBuilder();
    $queryBuilder
        ->select(array('country', 'state', 'city', 'address'))
        ->from('CouponiacsMainBundle:Country', 'country')
        ->leftJoin('country.states', 'state', 'WITH', 'state.name=:stateName OR state.shortName=:stateShortName')
        ->leftJoin('state.cities', 'city', 'WITH', 'city.name=:cityName')
        ->leftJoin('city.addresses', 'address', 'WITH', 'address.address=:address AND address.zip=:zip AND address.latitude=:latitude AND address.longitude=:longitude')
        ->where('country.name=:countryName OR country.shortName=:countryShortName')
        ->orderBy('city.name', 'DESC')
        ->setParameters(array(
            'countryName' => $country,
            'countryShortName' => $countryShort,
            'stateName' => $state,
            'stateShortName' => $stateShort,
            'cityName' => $city,
            'address' => $address['address'],
            'zip' => $address['zip'],
            'latitude' => $address['latitude'],
            'longitude' => $address['longitude'],
        ))
        ->setMaxResults(1);

the resultset contains only the Country entity, but no State entity. 结果集仅包含“国家”实体,而没有“州”实体。 I have also tried the same query using DQL with no success: 我也尝试使用DQL进行相同的查询,但没有成功:

$query = $this->em->createQuery('SELECT country, state, city, address
        FROM CouponiacsMainBundle:Country country
        LEFT JOIN country.states state WITH state.name=:stateName OR state.shortName=:stateShortName
        LEFT JOIN state.cities city WITH city.name=:cityName
        LEFT JOIN city.addresses address WITH address.address=:address AND address.zip=:zip AND address.latitude=:latitude AND address.longitude=:longitude
        WHERE country.name=:countryName OR country.shortName=:countryShortName
        ORDER BY city.name DESC
    ')->setParameters(array(
        'countryName' => $country,
        'countryShortName' => $countryShort,
        'stateName' => $state,
        'stateShortName' => $stateShort,
        'cityName' => $city,
        'address' => $address['address'],
        'zip' => $address['zip'],
        'latitude' => $address['latitude'],
        'longitude' => $address['longitude'],
    ));

If I manually run the generated SQL, the result for state is ok, but on the resultset there is no entity for state. 如果我手动运行生成的SQL,则状态的结果可以,但是在结果集上没有状态的实体。 The result is an array with Country entity, and if I do getStates() I get no states. 结果是一个具有Country实体的数组,如果我执行getStates(),则不会获得任何状态。

Any suggestions are appreciated, Thanks! 任何建议表示赞赏,谢谢!

EDIT : Here is the doctrine mapping: 编辑 :这是学说映射:

Address entity: 地址实体:

    <?php

namespace Couponiacs\MainBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Timestampable\Traits\TimestampableEntity;
use Symfony\Component\Validator\Constraints as Assert;
use Couponiacs\MainBundle\Entity\Traits\EnabledEntity;

/**
* Address
*
* @ORM\Table(uniqueConstraints={@ORM\UniqueConstraint(name="idx", columns={"city_id", "address", "zip", "latitude", "longitude"})})
* @ORM\Entity(repositoryClass="Couponiacs\MainBundle\Entity\AddressRepository")
*/
class Address
{
    use TimestampableEntity;
    use EnabledEntity;

    /**
    * @var integer
    *
    * @ORM\Column(type="integer")
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="AUTO")
    */
    private $id;

    /**
    * @var string
    *
    * @ORM\Column(type="string", length=190)
    */
    private $address = '';

    /**
    * @var City $city
    *
    * @ORM\ManyToOne(targetEntity="City", inversedBy="addresses", cascade={"all"})
    */
    private $city;

    /**
    * @var string
    *
    * @ORM\Column(type="string", length=16)
    */
    private $zip = '';

    /**
    * @var string
    *
    * @ORM\Column(type="string", length=32)
    */
    private $latitude = '';

    /**
    * @var string
    *
    * @ORM\Column(type="string", length=32)
    */
    private $longitude = '';

    /**
    * @var ArrayCollection $coupons
    *
    * @ORM\ManyToMany(targetEntity="Coupon", mappedBy="addresses", fetch="EXTRA_LAZY", cascade={"all"})
    */
    private $coupons;



    public function __construct()
    {
    $this->coupons = new ArrayCollection();
    }

    /**
    * Get id
    *
    * @return integer 
    */
    public function getId()
    {
    return $this->id;
    }

    /**
    * Set address
    *
    * @param string $address
    * @return Address
    */
    public function setAddress($address)
    {
    $this->address = $address;

    return $this;
    }

    /**
    * Get address
    *
    * @return string 
    */
    public function getAddress()
    {
    return $this->address;
    }

    /**
    * Set zip
    *
    * @param string $zip
    * @return Coupon
    */
    public function setZip($zip)
    {
    $this->zip = $zip;

    return $this;
    }

    /**
    * Get zip
    *
    * @return string 
    */
    public function getZip()
    {
    return $this->zip;
    }

    /**
    * Set latitude
    *
    * @param string $latitude
    * @return Coupon
    */
    public function setLatitude($latitude)
    {
    $this->latitude = $latitude;

    return $this;
    }

    /**
    * Get latitude
    *
    * @return string 
    */
    public function getLatitude()
    {
    return $this->latitude;
    }

    /**
    * Set longitude
    *
    * @param string $longitude
    * @return Coupon
    */
    public function setLongitude($longitude)
    {
    $this->longitude = $longitude;

    return $this;
    }

    /**
    * Get longitude
    *
    * @return string 
    */
    public function getLongitude()
    {
    return $this->longitude;
    }

    /**
    * Set city
    *
    * @param \Couponiacs\MainBundle\Entity\City $city
    * @return Address
    */
    public function setCity(City $city = null)
    {
    $this->city = $city;

    return $this;
    }

    /**
    * Get city
    *
    * @return \Couponiacs\MainBundle\Entity\City 
    */
    public function getCity()
    {
    return $this->city;
    }

    /**
    * Add coupon
    *
    * @param \Couponiacs\MainBundle\Entity\Coupon $coupon
    * @return Address
    */
    public function addCoupon(Coupon $coupon)
    {
    $this->coupons[] = $coupon;

    return $this;
    }

    /**
    * Remove coupon
    *
    * @param \Couponiacs\MainBundle\Entity\Coupon $coupon
    */
    public function removeCoupon(Coupon $coupon)
    {
    $this->coupons->removeElement($coupon);
    }

    /**
    * Get coupons
    *
    * @return \Doctrine\Common\Collections\Collection
    */
    public function getCoupon()
    {
    return $this->coupons;
    }
}

City entity: 城市实体:

    <?php

namespace Couponiacs\MainBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Timestampable\Traits\TimestampableEntity;
use Symfony\Component\Validator\Constraints as Assert;
use Couponiacs\MainBundle\Entity\Traits\NameEntity;
use Couponiacs\MainBundle\Entity\Traits\EnabledEntity;

/**
* City
*
* @ORM\Table(
*   indexes={
*     @ORM\Index(name="idx_name", columns={"name"})
*   },
*   uniqueConstraints={
*     @ORM\UniqueConstraint(name="idx_state_name", columns={"state_id", "name"})
*   }
* )
* @ORM\Entity(repositoryClass="Couponiacs\MainBundle\Entity\CityRepository")
*/
class City
{
    use TimestampableEntity;
    use NameEntity;
    use EnabledEntity;

    /**
    * @var integer
    *
    * @ORM\Column(type="integer")
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="AUTO")
    */
    private $id;

    /**
    * @var string
    *
    * @Gedmo\Slug(handlers={
    *   @Gedmo\SlugHandler(class="Gedmo\Sluggable\Handler\RelativeSlugHandler", options={
    *     @Gedmo\SlugHandlerOption(name="relationField", value="state"),
    *     @Gedmo\SlugHandlerOption(name="relationSlugField", value="slug")
    *   })
    * }, fields={"name"})
    * @ORM\Column(type="string", length=190, unique=true)
    * @Assert\NotBlank(message="err.constraint.empty_value")
    */
    private $slug;

    /**
    * @var State
    *
    * @ORM\ManyToOne(targetEntity="State", inversedBy="cities", cascade={"all"})
    */
    private $state;

    /**
    * @var ArrayCollection $addresses
    *
    * @ORM\OneToMany(targetEntity="Address", mappedBy="city", fetch="EXTRA_LAZY", cascade={"all"})
    */
    private $addresses;



    public function __construct()
    {
    $this->addresses = new ArrayCollection();
    }

    /**
    * Get id
    *
    * @return integer 
    */
    public function getId()
    {
    return $this->id;
    }

    /**
    * Set slug
    *
    * @param string $slug
    * @return City
    */
    public function setSlug($slug)
    {
    $this->slug = $slug;

    return $this;
    }

    /**
    * Get slug
    *
    * @return string 
    */
    public function getSlug()
    {
    return $this->slug;
    }

    /**
    * Set state
    *
    * @param \Couponiacs\MainBundle\Entity\State $state
    * @return City
    */
    public function setState(State $state = null)
    {
    $this->state = $state;

    return $this;
    }

    /**
    * Get state
    *
    * @return \Couponiacs\MainBundle\Entity\State 
    */
    public function getState()
    {
    return $this->state;
    }

    /**
    * Add address
    *
    * @param \Couponiacs\MainBundle\Entity\Address $address
    * @return City
    */
    public function addAddress(Address $address)
    {
    $this->addresses[] = $address;

    return $this;
    }

    /**
    * Remove address
    *
    * @param \Couponiacs\MainBundle\Entity\Address $address
    */
    public function removeAddress(Address $address)
    {
    $this->addresses->removeElement($address);
    }

    /**
    * Get addresses
    *
    * @return \Doctrine\Common\Collections\Collection 
    */
    public function getAddresses()
    {
    return $this->addresses;
    }
}

State entity: 国家实体:

    <?php

namespace Couponiacs\MainBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Timestampable\Traits\TimestampableEntity;
use Symfony\Component\Validator\Constraints as Assert;
use Couponiacs\MainBundle\Entity\Traits\NameEntity;
use Couponiacs\MainBundle\Entity\Traits\EnabledEntity;

/**
* State
*
* @ORM\Table(uniqueConstraints={@ORM\UniqueConstraint(name="idx_name_country", columns={"name", "country_id"})})
* @ORM\Table(uniqueConstraints={@ORM\UniqueConstraint(name="idx_shortName_country", columns={"shortName", "country_id"})})
* @ORM\Entity(repositoryClass="Couponiacs\MainBundle\Entity\StateRepository")
*/
class State
{
    use TimestampableEntity;
    use NameEntity;
    use EnabledEntity;

    /**
    * @var integer
    *
    * @ORM\Column(type="integer")
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="AUTO")
    */
    private $id;

    /**
    * @var string
    *
    * @ORM\Column(type="string", length=16)
    * @Assert\NotBlank(message="err.constraint.empty_value")
    */
    private $shortName = '';

    /**
    * @var string
    *
    * @Gedmo\Slug(handlers={
    *   @Gedmo\SlugHandler(class="Couponiacs\MainBundle\Entity\Handler\RelativeSlugHandler", options={
    *     @Gedmo\SlugHandlerOption(name="relationField", value="country"),
    *     @Gedmo\SlugHandlerOption(name="relationSlugField", value="slug")
    *   })
    * }, fields={"name"})
    * @ORM\Column(type="string", length=190, unique=true, nullable=true)
    */
    private $slug;

    /**
    * @var Country
    *
    * @ORM\ManyToOne(targetEntity="Country", inversedBy="states", cascade={"all"})
    */
    private $country;

    /**
    * @var ArrayCollection $cities
    *
    * @ORM\OneToMany(targetEntity="City", mappedBy="state", fetch="EXTRA_LAZY", cascade={"all"})
    */
    private $cities;



    public function __construct()
    {
    $this->cities = new ArrayCollection();
    }

    /**
    * Get id
    *
    * @return integer 
    */
    public function getId()
    {
    return $this->id;
    }

    /**
    * Set shortName
    *
    * @param string $shortName
    * @return State
    */
    public function setShortName($shortName)
    {
    $this->shortName = $shortName;

    return $this;
    }

    /**
    * Get shortName
    *
    * @return string
    */
    public function getShortName()
    {
    return $this->shortName;
    }

    /**
    * Set slug
    *
    * @param string $slug
    * @return State
    */
    public function setSlug($slug)
    {
    $this->slug = $slug;

    return $this;
    }

    /**
    * Get slug
    *
    * @return string 
    */
    public function getSlug()
    {
    return $this->slug;
    }

    /**
    * Set country
    *
    * @param \Couponiacs\MainBundle\Entity\Country $country
    * @return State
    */
    public function setCountry(Country $country = null)
    {
    $this->country = $country;

    return $this;
    }

    /**
    * Get country
    *
    * @return \Couponiacs\MainBundle\Entity\Country 
    */
    public function getCountry()
    {
    return $this->country;
    }

    /**
    * Add city
    *
    * @param \Couponiacs\MainBundle\Entity\City $city
    * @return State
    */
    public function addCity(City $city)
    {
    $this->cities[] = $city;

    return $this;
    }

    /**
    * Remove city
    *
    * @param \Couponiacs\MainBundle\Entity\City $city
    */
    public function removeCity(City $city)
    {
    $this->cities->removeElement($city);
    }

    /**
    * Get cities
    *
    * @return \Doctrine\Common\Collections\Collection 
    */
    public function getCities()
    {
    return $this->cities;
    }
}

Country entity: 国家实体:

    <?php

namespace Couponiacs\MainBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Timestampable\Traits\TimestampableEntity;
use Symfony\Component\Validator\Constraints as Assert;
use Couponiacs\MainBundle\Entity\Traits\UniqueNameEntity;
use Couponiacs\MainBundle\Entity\Traits\EnabledEntity;

/**
* Country
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="Couponiacs\MainBundle\Entity\CountryRepository")
*/
class Country
{
    use TimestampableEntity;
    use UniqueNameEntity;
    use EnabledEntity;

    /**
    * @var integer
    *
    * @ORM\Column(type="integer")
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="AUTO")
    */
    private $id;

    /**
    * @var string
    *
    * @ORM\Column(type="string", length=16, unique=true)
    * @Assert\NotBlank(message="err.constraint.empty_value")
    */
    private $shortName = '';

    /**
    * @var string
    *
    * @ORM\Column(type="string", length=64)
    */
    private $formatShort;

    /**
    * @var string
    *
    * @ORM\Column(type="string", length=64)
    */
    private $formatLong;

    /**
    * @var string
    *
    * @Gedmo\Slug(fields={"name"})
    * @ORM\Column(type="string", length=190, unique=true)
    * @Assert\NotBlank(message="err.constraint.empty_value")
    */
    private $slug;

    /**
    * @var ArrayCollection $states
    *
    * @ORM\OneToMany(targetEntity="State", mappedBy="country", fetch="EXTRA_LAZY", cascade={"all"})
    */
    private $states;

    /**
    * @var ArrayCollection $coupons
    *
    * @ORM\OneToMany(targetEntity="Coupon", mappedBy="country", fetch="EXTRA_LAZY", cascade={"all"})
    */
    private $coupons;



    public function __construct()
    {
    $this->states = new ArrayCollection();
    $this->coupons = new ArrayCollection();
    }

    /**
    * Get id
    *
    * @return integer 
    */
    public function getId()
    {
    return $this->id;
    }

    /**
    * Set shortName
    *
    * @param string $shortName
    * @return Country
    */
    public function setShortName($shortName)
    {
    $this->shortName = $shortName;

    return $this;
    }

    /**
    * Get shortName
    *
    * @return string
    */
    public function getShortName()
    {
    return $this->shortName;
    }

    /**
    * Set formatShort
    *
    * @param string $formatShort
    * @return Country
    */
    public function setFormatShort($formatShort)
    {
    $this->formatShort = $formatShort;

    return $this;
    }

    /**
    * Get formatShort
    *
    * @return string
    */
    public function getFormatShort()
    {
    return $this->formatShort;
    }

    /**
    * Set formatLong
    *
    * @param string $formatLong
    * @return Country
    */
    public function setFormatLong($formatLong)
    {
    $this->formatLong = $formatLong;

    return $this;
    }

    /**
    * Get formatLong
    *
    * @return string
    */
    public function getFormatLong()
    {
    return $this->formatLong;
    }

    /**
    * Set slug
    *
    * @param string $slug
    * @return Country
    */
    public function setSlug($slug)
    {
    $this->slug = $slug;

    return $this;
    }

    /**
    * Get slug
    *
    * @return string 
    */
    public function getSlug()
    {
    return $this->slug;
    }

    /**
    * Add state
    *
    * @param \Couponiacs\MainBundle\Entity\State $state
    * @return Country
    */
    public function addState(State $state)
    {
    $this->states[] = $state;

    return $this;
    }

    /**
    * Remove state
    *
    * @param \Couponiacs\MainBundle\Entity\State $state
    */
    public function removeState(State $state)
    {
    $this->states->removeElement($state);
    }

    /**
    * Get states
    *
    * @return \Doctrine\Common\Collections\Collection 
    */
    public function getStates()
    {
    return $this->states;
    }

    /**
    * Add coupon
    *
    * @param \Couponiacs\MainBundle\Entity\Coupon $coupon
    * @return Country
    */
    public function addCoupon(Coupon $coupon)
    {
    $this->coupons[] = $coupon;

    return $this;
    }

    /**
    * Remove coupon
    *
    * @param \Couponiacs\MainBundle\Entity\Coupon $coupon
    */
    public function removeCoupon(Coupon $coupon)
    {
    $this->coupons->removeElement($coupon);
    }

    /**
    * Get coupons
    *
    * @return \Doctrine\Common\Collections\Collection
    */
    public function getCoupons()
    {
    return $this->coupons;
    }
}

The problem is likely that you are using some of these entities before in other queries. 问题可能是您在其他查询中先使用了其中一些实体。 And Doctrine keeps some of that stuff cached. 而Doctrine则保留了其中的一些东西。 It depending on if the associations are fully loaded or only partially. 这取决于关联是完全加载还是仅部分加载。 Loading a fresh entity manager or another entity manager should do the trick. 加载新的实体经理或其他实体经理应该可以解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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