commit
08e38858ed
@ -146,6 +146,7 @@ class ArrayHydrator extends AbstractHydrator
|
||||
$baseElement =& $this->_resultPointers[$parent];
|
||||
} else {
|
||||
unset($this->_resultPointers[$dqlAlias]); // Ticket #1228
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -167,6 +168,7 @@ class ArrayHydrator extends AbstractHydrator
|
||||
|
||||
if ( ! $indexExists || ! $indexIsValid) {
|
||||
$element = $data;
|
||||
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$baseElement[$relationAlias][$row[$this->_rsm->indexByMap[$dqlAlias]]] = $element;
|
||||
} else {
|
||||
@ -183,9 +185,15 @@ class ArrayHydrator extends AbstractHydrator
|
||||
} else {
|
||||
$oneToOne = true;
|
||||
|
||||
if ( ! isset($nonemptyComponents[$dqlAlias]) && ! isset($baseElement[$relationAlias])) {
|
||||
if (
|
||||
( ! isset($nonemptyComponents[$dqlAlias])) &&
|
||||
( ! isset($baseElement[$relationAlias]))
|
||||
) {
|
||||
$baseElement[$relationAlias] = null;
|
||||
} else if ( ! isset($baseElement[$relationAlias])) {
|
||||
} else if (
|
||||
( ! isset($baseElement[$relationAlias])) ||
|
||||
( ! isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]))
|
||||
) {
|
||||
$baseElement[$relationAlias] = $data;
|
||||
}
|
||||
}
|
||||
@ -195,7 +203,6 @@ class ArrayHydrator extends AbstractHydrator
|
||||
if ($coll !== null) {
|
||||
$this->updateResultPointer($coll, $index, $dqlAlias, $oneToOne);
|
||||
}
|
||||
|
||||
} else {
|
||||
// It's a root result element
|
||||
|
||||
@ -204,22 +211,21 @@ class ArrayHydrator extends AbstractHydrator
|
||||
|
||||
// if this row has a NULL value for the root result id then make it a null result.
|
||||
if ( ! isset($nonemptyComponents[$dqlAlias]) ) {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array($entityKey => null);
|
||||
} else {
|
||||
$result[] = null;
|
||||
}
|
||||
$result[] = $this->_rsm->isMixed
|
||||
? array($entityKey => null)
|
||||
: null;
|
||||
|
||||
$resultKey = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for an existing element
|
||||
if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
|
||||
$element = $rowData[$dqlAlias];
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array($entityKey => $element);
|
||||
}
|
||||
$element = $this->_rsm->isMixed
|
||||
? array($entityKey => $rowData[$dqlAlias])
|
||||
: $rowData[$dqlAlias];
|
||||
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]];
|
||||
@ -227,6 +233,7 @@ class ArrayHydrator extends AbstractHydrator
|
||||
} else {
|
||||
$resultKey = $this->_resultCounter;
|
||||
$result[] = $element;
|
||||
|
||||
++$this->_resultCounter;
|
||||
}
|
||||
|
||||
@ -234,11 +241,13 @@ class ArrayHydrator extends AbstractHydrator
|
||||
} else {
|
||||
$index = $this->_identifierMap[$dqlAlias][$id[$dqlAlias]];
|
||||
$resultKey = $index;
|
||||
|
||||
/*if ($this->_rsm->isMixed) {
|
||||
$result[] =& $result[$index];
|
||||
++$this->_resultCounter;
|
||||
}*/
|
||||
}
|
||||
|
||||
$this->updateResultPointer($result, $index, $dqlAlias, false);
|
||||
}
|
||||
}
|
||||
@ -247,11 +256,9 @@ class ArrayHydrator extends AbstractHydrator
|
||||
if (isset($scalars)) {
|
||||
if ( ! isset($resultKey) ) {
|
||||
// this only ever happens when no object is fetched (scalar result only)
|
||||
if (isset($this->_rsm->indexByMap['scalars'])) {
|
||||
$resultKey = $row[$this->_rsm->indexByMap['scalars']];
|
||||
} else {
|
||||
$resultKey = $this->_resultCounter - 1;
|
||||
}
|
||||
$resultKey = isset($this->_rsm->indexByMap['scalars'])
|
||||
? $row[$this->_rsm->indexByMap['scalars']]
|
||||
: $this->_resultCounter - 1;
|
||||
}
|
||||
|
||||
foreach ($scalars as $name => $value) {
|
||||
@ -279,6 +286,12 @@ class ArrayHydrator extends AbstractHydrator
|
||||
return;
|
||||
}
|
||||
|
||||
if ($oneToOne) {
|
||||
$this->_resultPointers[$dqlAlias] =& $coll;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($index !== false) {
|
||||
$this->_resultPointers[$dqlAlias] =& $coll[$index];
|
||||
|
||||
@ -289,12 +302,6 @@ class ArrayHydrator extends AbstractHydrator
|
||||
return;
|
||||
}
|
||||
|
||||
if ($oneToOne) {
|
||||
$this->_resultPointers[$dqlAlias] =& $coll;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
end($coll);
|
||||
$this->_resultPointers[$dqlAlias] =& $coll[key($coll)];
|
||||
|
||||
|
42
tests/Doctrine/Tests/Models/Taxi/Car.php
Normal file
42
tests/Doctrine/Tests/Models/Taxi/Car.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\Taxi;
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @Table(name="taxi_car")
|
||||
*/
|
||||
class Car
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="string", length=25)
|
||||
* @GeneratedValue(strategy="NONE")
|
||||
*/
|
||||
private $brand;
|
||||
|
||||
/**
|
||||
* @Column(type="string", length=255);
|
||||
*/
|
||||
private $model;
|
||||
|
||||
/**
|
||||
* @OneToMany(targetEntity="Ride", mappedBy="car")
|
||||
*/
|
||||
private $freeCarRides;
|
||||
|
||||
/**
|
||||
* @OneToMany(targetEntity="PaidRide", mappedBy="car")
|
||||
*/
|
||||
private $carRides;
|
||||
|
||||
public function setBrand($brand)
|
||||
{
|
||||
$this->brand = $brand;
|
||||
}
|
||||
|
||||
public function setModel($model)
|
||||
{
|
||||
$this->model = $model;
|
||||
}
|
||||
}
|
37
tests/Doctrine/Tests/Models/Taxi/Driver.php
Normal file
37
tests/Doctrine/Tests/Models/Taxi/Driver.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\Taxi;
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @Table(name="taxi_driver")
|
||||
*/
|
||||
class Driver
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @Column(type="string", length=255);
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @OneToMany(targetEntity="Ride", mappedBy="driver")
|
||||
*/
|
||||
private $freeDriverRides;
|
||||
|
||||
/**
|
||||
* @OneToMany(targetEntity="PaidRide", mappedBy="driver")
|
||||
*/
|
||||
private $driverRides;
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
}
|
42
tests/Doctrine/Tests/Models/Taxi/PaidRide.php
Normal file
42
tests/Doctrine/Tests/Models/Taxi/PaidRide.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\Taxi;
|
||||
|
||||
/**
|
||||
* Same as Ride but with an extra column that is not part of the composite primary key
|
||||
*
|
||||
* @Entity
|
||||
* @Table(name="taxi_paid_ride")
|
||||
*/
|
||||
class PaidRide
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @ManyToOne(targetEntity="Driver", inversedBy="driverRides")
|
||||
* @JoinColumn(name="driver_id", referencedColumnName="id")
|
||||
*/
|
||||
private $driver;
|
||||
|
||||
/**
|
||||
* @Id
|
||||
* @ManyToOne(targetEntity="Car", inversedBy="carRides")
|
||||
* @JoinColumn(name="car", referencedColumnName="brand")
|
||||
*/
|
||||
private $car;
|
||||
|
||||
/**
|
||||
* @Column(type="decimal", precision=6, scale=2)
|
||||
*/
|
||||
private $fare;
|
||||
|
||||
public function __construct(Driver $driver, Car $car)
|
||||
{
|
||||
$this->driver = $driver;
|
||||
$this->car = $car;
|
||||
}
|
||||
|
||||
public function setFare($fare)
|
||||
{
|
||||
$this->fare = $fare;
|
||||
}
|
||||
}
|
32
tests/Doctrine/Tests/Models/Taxi/Ride.php
Normal file
32
tests/Doctrine/Tests/Models/Taxi/Ride.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Models\Taxi;
|
||||
|
||||
/**
|
||||
* Test model that contains only Id-columns
|
||||
*
|
||||
* @Entity
|
||||
* @Table(name="taxi_ride")
|
||||
*/
|
||||
class Ride
|
||||
{
|
||||
/**
|
||||
* @Id
|
||||
* @ManyToOne(targetEntity="Driver", inversedBy="freeDriverRides")
|
||||
* @JoinColumn(name="driver_id", referencedColumnName="id")
|
||||
*/
|
||||
private $driver;
|
||||
|
||||
/**
|
||||
* @Id
|
||||
* @ManyToOne(targetEntity="Car", inversedBy="freeCarRides")
|
||||
* @JoinColumn(name="car", referencedColumnName="brand")
|
||||
*/
|
||||
private $car;
|
||||
|
||||
public function __construct(Driver $driver, Car $car)
|
||||
{
|
||||
$this->driver = $driver;
|
||||
$this->car = $car;
|
||||
}
|
||||
}
|
158
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1884Test.php
Normal file
158
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1884Test.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Tests\Models\Taxi\Car,
|
||||
Doctrine\Tests\Models\Taxi\Driver,
|
||||
Doctrine\Tests\Models\Taxi\Ride,
|
||||
Doctrine\Tests\Models\Taxi\PaidRide;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group DDC-1884
|
||||
* @author Sander Coolen <sander@jibber.nl>
|
||||
*/
|
||||
class DDC1884Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
$this->useModelSet('taxi');
|
||||
parent::setUp();
|
||||
|
||||
list($bimmer, $crysler, $merc, $volvo) = $this->createCars('Doctrine\Tests\Models\Taxi\Car');
|
||||
list($john, $foo) = $this->createDrivers('Doctrine\Tests\Models\Taxi\Driver');
|
||||
$this->_em->flush();
|
||||
|
||||
$ride1 = new Ride($john, $bimmer);
|
||||
$ride2 = new Ride($john, $merc);
|
||||
$ride3 = new Ride($john, $volvo);
|
||||
$ride4 = new Ride($foo, $merc);
|
||||
|
||||
$this->_em->persist($ride1);
|
||||
$this->_em->persist($ride2);
|
||||
$this->_em->persist($ride3);
|
||||
$this->_em->persist($ride4);
|
||||
|
||||
$ride5 = new PaidRide($john, $bimmer);
|
||||
$ride5->setFare(10.50);
|
||||
|
||||
$ride6 = new PaidRide($john, $merc);
|
||||
$ride6->setFare(16.00);
|
||||
|
||||
$ride7 = new PaidRide($john, $volvo);
|
||||
$ride7->setFare(20.70);
|
||||
|
||||
$ride8 = new PaidRide($foo, $merc);
|
||||
$ride8->setFare(32.15);
|
||||
|
||||
$this->_em->persist($ride5);
|
||||
$this->_em->persist($ride6);
|
||||
$this->_em->persist($ride7);
|
||||
$this->_em->persist($ride8);
|
||||
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
private function createCars($class)
|
||||
{
|
||||
$bimmer = new $class;
|
||||
$bimmer->setBrand('BMW');
|
||||
$bimmer->setModel('7-Series');
|
||||
|
||||
$crysler = new $class;
|
||||
$crysler->setBrand('Crysler');
|
||||
$crysler->setModel('300');
|
||||
|
||||
$merc = new $class;
|
||||
$merc->setBrand('Mercedes');
|
||||
$merc->setModel('C-Class');
|
||||
|
||||
$volvo = new $class;
|
||||
$volvo->setBrand('Volvo');
|
||||
$volvo->setModel('XC90');
|
||||
|
||||
$this->_em->persist($bimmer);
|
||||
$this->_em->persist($crysler);
|
||||
$this->_em->persist($merc);
|
||||
$this->_em->persist($volvo);
|
||||
|
||||
return array($bimmer, $crysler, $merc, $volvo);
|
||||
}
|
||||
|
||||
private function createDrivers($class)
|
||||
{
|
||||
$john = new $class;
|
||||
$john->setName('John Doe');
|
||||
|
||||
$foo = new $class;
|
||||
$foo->setName('Foo Bar');
|
||||
|
||||
$this->_em->persist($foo);
|
||||
$this->_em->persist($john);
|
||||
|
||||
return array($john, $foo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1) Ride contains only columns that are part of its composite primary key
|
||||
* 2) We use fetch joins here
|
||||
*/
|
||||
public function testSelectFromInverseSideWithCompositePkAndSolelyIdentifierColumnsUsingFetchJoins()
|
||||
{
|
||||
$qb = $this->_em->createQueryBuilder();
|
||||
|
||||
$result = $qb->select('d, dr, c')
|
||||
->from('Doctrine\Tests\Models\Taxi\Driver', 'd')
|
||||
->leftJoin('d.freeDriverRides', 'dr')
|
||||
->leftJoin('dr.car', 'c')
|
||||
->where('d.name = ?1')
|
||||
->setParameter(1, 'John Doe')
|
||||
->getQuery()
|
||||
->getArrayResult();
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertArrayHasKey('freeDriverRides', $result[0]);
|
||||
$this->assertCount(3, $result[0]['freeDriverRides']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1) PaidRide contains an extra column that is not part of the composite primary key
|
||||
* 2) Again we will use fetch joins
|
||||
*/
|
||||
public function testSelectFromInverseSideWithCompositePkUsingFetchJoins()
|
||||
{
|
||||
$qb = $this->_em->createQueryBuilder();
|
||||
|
||||
$result = $qb->select('d, dr, c')
|
||||
->from('Doctrine\Tests\Models\Taxi\Driver', 'd')
|
||||
->leftJoin('d.driverRides', 'dr')
|
||||
->leftJoin('dr.car', 'c')
|
||||
->where('d.name = ?1')
|
||||
->setParameter(1, 'John Doe')
|
||||
->getQuery()->getArrayResult();
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertArrayHasKey('driverRides', $result[0]);
|
||||
$this->assertCount(3, $result[0]['driverRides']);
|
||||
}
|
||||
|
||||
/**
|
||||
* The other way around will fail too
|
||||
*/
|
||||
public function testSelectFromOwningSideUsingFetchJoins()
|
||||
{
|
||||
$qb = $this->_em->createQueryBuilder();
|
||||
|
||||
$result = $qb->select('r, d, c')
|
||||
->from('Doctrine\Tests\Models\Taxi\PaidRide', 'r')
|
||||
->leftJoin('r.driver', 'd')
|
||||
->leftJoin('r.car', 'c')
|
||||
->where('d.name = ?1')
|
||||
->setParameter(1, 'John Doe')
|
||||
->getQuery()->getArrayResult();
|
||||
|
||||
$this->assertCount(3, $result);
|
||||
$this->assertArrayHasKey('driver', $result[0]);
|
||||
$this->assertArrayHasKey('car', $result[0]);
|
||||
}
|
||||
}
|
@ -155,7 +155,13 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
'Doctrine\Tests\Models\CompositeKeyInheritance\JoinedChildClass',
|
||||
'Doctrine\Tests\Models\CompositeKeyInheritance\SingleRootClass',
|
||||
'Doctrine\Tests\Models\CompositeKeyInheritance\SingleChildClass',
|
||||
)
|
||||
),
|
||||
'taxi' => array(
|
||||
'Doctrine\Tests\Models\Taxi\PaidRide',
|
||||
'Doctrine\Tests\Models\Taxi\Ride',
|
||||
'Doctrine\Tests\Models\Taxi\Car',
|
||||
'Doctrine\Tests\Models\Taxi\Driver',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
@ -284,6 +290,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
$conn->executeUpdate('DELETE FROM SingleRootClass');
|
||||
}
|
||||
|
||||
if (isset($this->_usedModelSets['taxi'])) {
|
||||
$conn->executeUpdate('DELETE FROM taxi_paid_ride');
|
||||
$conn->executeUpdate('DELETE FROM taxi_ride');
|
||||
$conn->executeUpdate('DELETE FROM taxi_car');
|
||||
$conn->executeUpdate('DELETE FROM taxi_driver');
|
||||
}
|
||||
|
||||
$this->_em->clear();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user