3 namespace Doctrine\Tests\ORM\Functional;
5 use Doctrine\ORM\Mapping\ClassMetadata;
6 use Doctrine\Common\Collections\Criteria;
8 class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
11 private $engineers = array();
16 public function setUp()
18 $this->useModelSet('company');
22 public function persistRelatedEmployees()
24 $this->salesPerson = new \Doctrine\Tests\Models\Company\CompanyEmployee();
25 $this->salesPerson->setName('Poor Sales Guy');
26 $this->salesPerson->setDepartment('Sales');
27 $this->salesPerson->setSalary(100);
29 $engineer1 = new \Doctrine\Tests\Models\Company\CompanyEmployee();
30 $engineer1->setName('Roman B.');
31 $engineer1->setDepartment('IT');
32 $engineer1->setSalary(100);
33 $this->engineers[] = $engineer1;
35 $engineer2 = new \Doctrine\Tests\Models\Company\CompanyEmployee();
36 $engineer2->setName('Jonathan W.');
37 $engineer2->setDepartment('IT');
38 $engineer2->setSalary(100);
39 $this->engineers[] = $engineer2;
41 $engineer3 = new \Doctrine\Tests\Models\Company\CompanyEmployee();
42 $engineer3->setName('Benjamin E.');
43 $engineer3->setDepartment('IT');
44 $engineer3->setSalary(100);
45 $this->engineers[] = $engineer3;
47 $engineer4 = new \Doctrine\Tests\Models\Company\CompanyEmployee();
48 $engineer4->setName('Guilherme B.');
49 $engineer4->setDepartment('IT');
50 $engineer4->setSalary(100);
51 $this->engineers[] = $engineer4;
53 $this->_em->persist($this->salesPerson);
54 $this->_em->persist($engineer1);
55 $this->_em->persist($engineer2);
56 $this->_em->persist($engineer3);
57 $this->_em->persist($engineer4);
60 public function loadFullFixture()
62 $this->persistRelatedEmployees();
64 $this->fix = new \Doctrine\Tests\Models\Company\CompanyFixContract();
65 $this->fix->setFixPrice(1000);
66 $this->fix->setSalesPerson($this->salesPerson);
67 $this->fix->addEngineer($this->engineers[0]);
68 $this->fix->addEngineer($this->engineers[1]);
69 $this->fix->markCompleted();
71 $this->flex = new \Doctrine\Tests\Models\Company\CompanyFlexContract();
72 $this->flex->setSalesPerson($this->salesPerson);
73 $this->flex->setHoursWorked(100);
74 $this->flex->setPricePerHour(100);
75 $this->flex->addEngineer($this->engineers[2]);
76 $this->flex->addEngineer($this->engineers[1]);
77 $this->flex->addEngineer($this->engineers[3]);
78 $this->flex->markCompleted();
80 $this->ultra = new \Doctrine\Tests\Models\Company\CompanyFlexUltraContract();
81 $this->ultra->setSalesPerson($this->salesPerson);
82 $this->ultra->setHoursWorked(150);
83 $this->ultra->setPricePerHour(150);
84 $this->ultra->setMaxPrice(7000);
85 $this->ultra->addEngineer($this->engineers[3]);
86 $this->ultra->addEngineer($this->engineers[0]);
88 $this->_em->persist($this->fix);
89 $this->_em->persist($this->flex);
90 $this->_em->persist($this->ultra);
95 public function testPersistChildOfBaseClass()
97 $this->persistRelatedEmployees();
99 $fixContract = new \Doctrine\Tests\Models\Company\CompanyFixContract();
100 $fixContract->setFixPrice(1000);
101 $fixContract->setSalesPerson($this->salesPerson);
103 $this->_em->persist($fixContract);
107 $contract = $this->_em->find('Doctrine\Tests\Models\Company\CompanyFixContract', $fixContract->getId());
109 $this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyFixContract', $contract);
110 $this->assertEquals(1000, $contract->getFixPrice());
111 $this->assertEquals($this->salesPerson->getId(), $contract->getSalesPerson()->getId());
114 public function testPersistDeepChildOfBaseClass()
116 $this->persistRelatedEmployees();
118 $ultraContract = new \Doctrine\Tests\Models\Company\CompanyFlexUltraContract();
119 $ultraContract->setSalesPerson($this->salesPerson);
120 $ultraContract->setHoursWorked(100);
121 $ultraContract->setPricePerHour(50);
122 $ultraContract->setMaxPrice(7000);
124 $this->_em->persist($ultraContract);
128 $contract = $this->_em->find('Doctrine\Tests\Models\Company\CompanyFlexUltraContract', $ultraContract->getId());
130 $this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyFlexUltraContract', $contract);
131 $this->assertEquals(7000, $contract->getMaxPrice());
132 $this->assertEquals(100, $contract->getHoursWorked());
133 $this->assertEquals(50, $contract->getPricePerHour());
136 public function testChildClassLifecycleUpdate()
138 $this->loadFullFixture();
140 $fix = $this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->fix->getId());
141 $fix->setFixPrice(2500);
146 $newFix = $this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->fix->getId());
147 $this->assertEquals(2500, $newFix->getFixPrice());
150 public function testChildClassLifecycleRemove()
152 $this->loadFullFixture();
154 $fix = $this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->fix->getId());
155 $this->_em->remove($fix);
158 $this->assertNull($this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->fix->getId()));
161 public function testFindAllForAbstractBaseClass()
163 $this->loadFullFixture();
164 $contracts = $this->_em->getRepository('Doctrine\Tests\Models\Company\CompanyContract')->findAll();
166 $this->assertEquals(3, count($contracts));
167 $this->assertContainsOnly('Doctrine\Tests\Models\Company\CompanyContract', $contracts);
170 public function testFindAllForChildClass()
172 $this->loadFullFixture();
174 $this->assertEquals(1, count($this->_em->getRepository('Doctrine\Tests\Models\Company\CompanyFixContract')->findAll()));
175 $this->assertEquals(2, count($this->_em->getRepository('Doctrine\Tests\Models\Company\CompanyFlexContract')->findAll()));
176 $this->assertEquals(1, count($this->_em->getRepository('Doctrine\Tests\Models\Company\CompanyFlexUltraContract')->findAll()));
179 public function testFindForAbstractBaseClass()
181 $this->loadFullFixture();
183 $contract = $this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->fix->getId());
185 $this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyFixContract', $contract);
186 $this->assertEquals(1000, $contract->getFixPrice());
189 public function testQueryForAbstractBaseClass()
191 $this->loadFullFixture();
193 $contracts = $this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c')->getResult();
195 $this->assertEquals(3, count($contracts));
196 $this->assertContainsOnly('Doctrine\Tests\Models\Company\CompanyContract', $contracts);
199 public function testQueryForChildClass()
201 $this->loadFullFixture();
203 $this->assertEquals(1, count($this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\Company\CompanyFixContract c')->getResult()));
204 $this->assertEquals(2, count($this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\Company\CompanyFlexContract c')->getResult()));
205 $this->assertEquals(1, count($this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\Company\CompanyFlexUltraContract c')->getResult()));
208 public function testQueryBaseClassWithJoin()
210 $this->loadFullFixture();
212 $contracts = $this->_em->createQuery('SELECT c, p FROM Doctrine\Tests\Models\Company\CompanyContract c JOIN c.salesPerson p')->getResult();
213 $this->assertEquals(3, count($contracts));
214 $this->assertContainsOnly('Doctrine\Tests\Models\Company\CompanyContract', $contracts);
217 public function testQueryScalarWithDiscrimnatorValue()
219 $this->loadFullFixture();
221 $contracts = $this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c ORDER BY c.id')->getScalarResult();
223 $discrValues = \array_map(function($a) {
224 return $a['c_discr'];
229 $this->assertEquals(array('fix', 'flexible', 'flexultra'), $discrValues);
232 public function testQueryChildClassWithCondition()
234 $this->loadFullFixture();
236 $dql = 'SELECT c FROM Doctrine\Tests\Models\Company\CompanyFixContract c WHERE c.fixPrice = ?1';
237 $contract = $this->_em->createQuery($dql)->setParameter(1, 1000)->getSingleResult();
239 $this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyFixContract', $contract);
240 $this->assertEquals(1000, $contract->getFixPrice());
243 public function testUpdateChildClassWithCondition()
245 $this->loadFullFixture();
247 $dql = 'UPDATE Doctrine\Tests\Models\Company\CompanyFlexContract c SET c.hoursWorked = c.hoursWorked * 2 WHERE c.hoursWorked = 150';
248 $affected = $this->_em->createQuery($dql)->execute();
250 $this->assertEquals(1, $affected);
252 $flexContract = $this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->flex->getId());
253 $ultraContract = $this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->ultra->getId());
255 $this->assertEquals(300, $ultraContract->getHoursWorked());
256 $this->assertEquals(100, $flexContract->getHoursWorked());
259 public function testUpdateBaseClassWithCondition()
261 $this->loadFullFixture();
263 $dql = 'UPDATE Doctrine\Tests\Models\Company\CompanyContract c SET c.completed = true WHERE c.completed = false';
264 $affected = $this->_em->createQuery($dql)->execute();
266 $this->assertEquals(1, $affected);
268 $dql = 'UPDATE Doctrine\Tests\Models\Company\CompanyContract c SET c.completed = false';
269 $affected = $this->_em->createQuery($dql)->execute();
271 $this->assertEquals(3, $affected);
274 public function testDeleteByChildClassCondition()
276 $this->loadFullFixture();
278 $dql = 'DELETE Doctrine\Tests\Models\Company\CompanyFlexContract c';
279 $affected = $this->_em->createQuery($dql)->execute();
281 $this->assertEquals(2, $affected);
284 public function testDeleteByBaseClassCondition()
286 $this->loadFullFixture();
288 $dql = "DELETE Doctrine\Tests\Models\Company\CompanyContract c WHERE c.completed = true";
289 $affected = $this->_em->createQuery($dql)->execute();
291 $this->assertEquals(2, $affected);
293 $contracts = $this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c')->getResult();
294 $this->assertEquals(1, count($contracts));
296 $this->assertFalse($contracts[0]->isCompleted(), "Only non completed contracts should be left.");
302 public function testDeleteJoinTableRecords()
304 $this->loadFullFixture();
306 // remove managed copy of the fix contract
307 $this->_em->remove($this->_em->find(get_class($this->fix), $this->fix->getId()));
310 $this->assertNull($this->_em->find(get_class($this->fix), $this->fix->getId()), "Contract should not be present in the database anymore.");
316 public function testFindByAssociation()
318 $this->loadFullFixture();
320 $repos = $this->_em->getRepository("Doctrine\Tests\Models\Company\CompanyContract");
321 $contracts = $repos->findBy(array('salesPerson' => $this->salesPerson->getId()));
322 $this->assertEquals(3, count($contracts), "There should be 3 entities related to " . $this->salesPerson->getId() . " for 'Doctrine\Tests\Models\Company\CompanyContract'");
324 $repos = $this->_em->getRepository("Doctrine\Tests\Models\Company\CompanyFixContract");
325 $contracts = $repos->findBy(array('salesPerson' => $this->salesPerson->getId()));
326 $this->assertEquals(1, count($contracts), "There should be 1 entities related to " . $this->salesPerson->getId() . " for 'Doctrine\Tests\Models\Company\CompanyFixContract'");
328 $repos = $this->_em->getRepository("Doctrine\Tests\Models\Company\CompanyFlexContract");
329 $contracts = $repos->findBy(array('salesPerson' => $this->salesPerson->getId()));
330 $this->assertEquals(2, count($contracts), "There should be 2 entities related to " . $this->salesPerson->getId() . " for 'Doctrine\Tests\Models\Company\CompanyFlexContract'");
332 $repos = $this->_em->getRepository("Doctrine\Tests\Models\Company\CompanyFlexUltraContract");
333 $contracts = $repos->findBy(array('salesPerson' => $this->salesPerson->getId()));
334 $this->assertEquals(1, count($contracts), "There should be 1 entities related to " . $this->salesPerson->getId() . " for 'Doctrine\Tests\Models\Company\CompanyFlexUltraContract'");
340 public function testInheritanceMatching()
342 $this->loadFullFixture();
344 $repository = $this->_em->getRepository("Doctrine\Tests\Models\Company\CompanyContract");
345 $contracts = $repository->matching(new Criteria(
346 Criteria::expr()->eq('salesPerson', $this->salesPerson->getId())
348 $this->assertEquals(3, count($contracts));
350 $repository = $this->_em->getRepository("Doctrine\Tests\Models\Company\CompanyFixContract");
351 $contracts = $repository->matching(new Criteria(
352 Criteria::expr()->eq('salesPerson', $this->salesPerson->getId())
354 $this->assertEquals(1, count($contracts));
360 public function testGetReferenceEntityWithSubclasses()
362 $this->loadFullFixture();
364 $ref = $this->_em->getReference('Doctrine\Tests\Models\Company\CompanyContract', $this->fix->getId());
365 $this->assertNotInstanceOf('Doctrine\ORM\Proxy\Proxy', $ref, "Cannot Request a proxy from a class that has subclasses.");
366 $this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyContract', $ref);
367 $this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyFixContract', $ref, "Direct fetch of the reference has to load the child class Emplyoee directly.");
370 $ref = $this->_em->getReference('Doctrine\Tests\Models\Company\CompanyFixContract', $this->fix->getId());
371 $this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $ref, "A proxy can be generated only if no subclasses exists for the requested reference.");
377 public function testEagerLoadInheritanceHierachy()
379 $this->loadFullFixture();
381 $dql = 'SELECT f FROM Doctrine\Tests\Models\Company\CompanyFixContract f WHERE f.id = ?1';
382 $contract = $this->_em->createQuery($dql)
383 ->setFetchMode('Doctrine\Tests\Models\Company\CompanyFixContract', 'salesPerson', ClassMetadata::FETCH_EAGER)
384 ->setParameter(1, $this->fix->getId())
387 $this->assertNotInstanceOf('Doctrine\ORM\Proxy\Proxy', $contract->getSalesPerson());