SingleTableInheritanceTest.php 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. <?php
  2. namespace Doctrine\Tests\ORM\Functional;
  3. use Doctrine\ORM\Mapping\ClassMetadata;
  4. require_once __DIR__ . '/../../TestInit.php';
  5. class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
  6. {
  7. private $salesPerson;
  8. private $engineers = array();
  9. private $fix;
  10. private $flex;
  11. private $ultra;
  12. public function setUp()
  13. {
  14. $this->useModelSet('company');
  15. parent::setUp();
  16. }
  17. public function persistRelatedEmployees()
  18. {
  19. $this->salesPerson = new \Doctrine\Tests\Models\Company\CompanyEmployee();
  20. $this->salesPerson->setName('Poor Sales Guy');
  21. $this->salesPerson->setDepartment('Sales');
  22. $this->salesPerson->setSalary(100);
  23. $engineer1 = new \Doctrine\Tests\Models\Company\CompanyEmployee();
  24. $engineer1->setName('Roman B.');
  25. $engineer1->setDepartment('IT');
  26. $engineer1->setSalary(100);
  27. $this->engineers[] = $engineer1;
  28. $engineer2 = new \Doctrine\Tests\Models\Company\CompanyEmployee();
  29. $engineer2->setName('Jonathan W.');
  30. $engineer2->setDepartment('IT');
  31. $engineer2->setSalary(100);
  32. $this->engineers[] = $engineer2;
  33. $engineer3 = new \Doctrine\Tests\Models\Company\CompanyEmployee();
  34. $engineer3->setName('Benjamin E.');
  35. $engineer3->setDepartment('IT');
  36. $engineer3->setSalary(100);
  37. $this->engineers[] = $engineer3;
  38. $engineer4 = new \Doctrine\Tests\Models\Company\CompanyEmployee();
  39. $engineer4->setName('Guilherme B.');
  40. $engineer4->setDepartment('IT');
  41. $engineer4->setSalary(100);
  42. $this->engineers[] = $engineer4;
  43. $this->_em->persist($this->salesPerson);
  44. $this->_em->persist($engineer1);
  45. $this->_em->persist($engineer2);
  46. $this->_em->persist($engineer3);
  47. $this->_em->persist($engineer4);
  48. }
  49. public function loadFullFixture()
  50. {
  51. $this->persistRelatedEmployees();
  52. $this->fix = new \Doctrine\Tests\Models\Company\CompanyFixContract();
  53. $this->fix->setFixPrice(1000);
  54. $this->fix->setSalesPerson($this->salesPerson);
  55. $this->fix->addEngineer($this->engineers[0]);
  56. $this->fix->addEngineer($this->engineers[1]);
  57. $this->fix->markCompleted();
  58. $this->flex = new \Doctrine\Tests\Models\Company\CompanyFlexContract();
  59. $this->flex->setSalesPerson($this->salesPerson);
  60. $this->flex->setHoursWorked(100);
  61. $this->flex->setPricePerHour(100);
  62. $this->flex->addEngineer($this->engineers[2]);
  63. $this->flex->addEngineer($this->engineers[1]);
  64. $this->flex->addEngineer($this->engineers[3]);
  65. $this->flex->markCompleted();
  66. $this->ultra = new \Doctrine\Tests\Models\Company\CompanyFlexUltraContract();
  67. $this->ultra->setSalesPerson($this->salesPerson);
  68. $this->ultra->setHoursWorked(150);
  69. $this->ultra->setPricePerHour(150);
  70. $this->ultra->setMaxPrice(7000);
  71. $this->ultra->addEngineer($this->engineers[3]);
  72. $this->ultra->addEngineer($this->engineers[0]);
  73. $this->_em->persist($this->fix);
  74. $this->_em->persist($this->flex);
  75. $this->_em->persist($this->ultra);
  76. $this->_em->flush();
  77. $this->_em->clear();
  78. }
  79. public function testPersistChildOfBaseClass()
  80. {
  81. $this->persistRelatedEmployees();
  82. $fixContract = new \Doctrine\Tests\Models\Company\CompanyFixContract();
  83. $fixContract->setFixPrice(1000);
  84. $fixContract->setSalesPerson($this->salesPerson);
  85. $this->_em->persist($fixContract);
  86. $this->_em->flush();
  87. $this->_em->clear();
  88. $contract = $this->_em->find('Doctrine\Tests\Models\Company\CompanyFixContract', $fixContract->getId());
  89. $this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyFixContract', $contract);
  90. $this->assertEquals(1000, $contract->getFixPrice());
  91. $this->assertEquals($this->salesPerson->getId(), $contract->getSalesPerson()->getId());
  92. }
  93. public function testPersistDeepChildOfBaseClass()
  94. {
  95. $this->persistRelatedEmployees();
  96. $ultraContract = new \Doctrine\Tests\Models\Company\CompanyFlexUltraContract();
  97. $ultraContract->setSalesPerson($this->salesPerson);
  98. $ultraContract->setHoursWorked(100);
  99. $ultraContract->setPricePerHour(50);
  100. $ultraContract->setMaxPrice(7000);
  101. $this->_em->persist($ultraContract);
  102. $this->_em->flush();
  103. $this->_em->clear();
  104. $contract = $this->_em->find('Doctrine\Tests\Models\Company\CompanyFlexUltraContract', $ultraContract->getId());
  105. $this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyFlexUltraContract', $contract);
  106. $this->assertEquals(7000, $contract->getMaxPrice());
  107. $this->assertEquals(100, $contract->getHoursWorked());
  108. $this->assertEquals(50, $contract->getPricePerHour());
  109. }
  110. public function testChildClassLifecycleUpdate()
  111. {
  112. $this->loadFullFixture();
  113. $fix = $this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->fix->getId());
  114. $fix->setFixPrice(2500);
  115. $this->_em->flush();
  116. $this->_em->clear();
  117. $newFix = $this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->fix->getId());
  118. $this->assertEquals(2500, $newFix->getFixPrice());
  119. }
  120. public function testChildClassLifecycleRemove()
  121. {
  122. $this->loadFullFixture();
  123. $fix = $this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->fix->getId());
  124. $this->_em->remove($fix);
  125. $this->_em->flush();
  126. $this->assertNull($this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->fix->getId()));
  127. }
  128. public function testFindAllForAbstractBaseClass()
  129. {
  130. $this->loadFullFixture();
  131. $contracts = $this->_em->getRepository('Doctrine\Tests\Models\Company\CompanyContract')->findAll();
  132. $this->assertEquals(3, count($contracts));
  133. $this->assertContainsOnly('Doctrine\Tests\Models\Company\CompanyContract', $contracts);
  134. }
  135. public function testFindAllForChildClass()
  136. {
  137. $this->loadFullFixture();
  138. $this->assertEquals(1, count($this->_em->getRepository('Doctrine\Tests\Models\Company\CompanyFixContract')->findAll()));
  139. $this->assertEquals(2, count($this->_em->getRepository('Doctrine\Tests\Models\Company\CompanyFlexContract')->findAll()));
  140. $this->assertEquals(1, count($this->_em->getRepository('Doctrine\Tests\Models\Company\CompanyFlexUltraContract')->findAll()));
  141. }
  142. public function testFindForAbstractBaseClass()
  143. {
  144. $this->loadFullFixture();
  145. $contract = $this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->fix->getId());
  146. $this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyFixContract', $contract);
  147. $this->assertEquals(1000, $contract->getFixPrice());
  148. }
  149. public function testQueryForAbstractBaseClass()
  150. {
  151. $this->loadFullFixture();
  152. $contracts = $this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c')->getResult();
  153. $this->assertEquals(3, count($contracts));
  154. $this->assertContainsOnly('Doctrine\Tests\Models\Company\CompanyContract', $contracts);
  155. }
  156. public function testQueryForChildClass()
  157. {
  158. $this->loadFullFixture();
  159. $this->assertEquals(1, count($this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\Company\CompanyFixContract c')->getResult()));
  160. $this->assertEquals(2, count($this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\Company\CompanyFlexContract c')->getResult()));
  161. $this->assertEquals(1, count($this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\Company\CompanyFlexUltraContract c')->getResult()));
  162. }
  163. public function testQueryBaseClassWithJoin()
  164. {
  165. $this->loadFullFixture();
  166. $contracts = $this->_em->createQuery('SELECT c, p FROM Doctrine\Tests\Models\Company\CompanyContract c JOIN c.salesPerson p')->getResult();
  167. $this->assertEquals(3, count($contracts));
  168. $this->assertContainsOnly('Doctrine\Tests\Models\Company\CompanyContract', $contracts);
  169. }
  170. public function testQueryScalarWithDiscrimnatorValue()
  171. {
  172. $this->loadFullFixture();
  173. $contracts = $this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c ORDER BY c.id')->getScalarResult();
  174. $discrValues = \array_map(function($a) {
  175. return $a['c_discr'];
  176. }, $contracts);
  177. sort($discrValues);
  178. $this->assertEquals(array('fix', 'flexible', 'flexultra'), $discrValues);
  179. }
  180. public function testQueryChildClassWithCondition()
  181. {
  182. $this->loadFullFixture();
  183. $dql = 'SELECT c FROM Doctrine\Tests\Models\Company\CompanyFixContract c WHERE c.fixPrice = ?1';
  184. $contract = $this->_em->createQuery($dql)->setParameter(1, 1000)->getSingleResult();
  185. $this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyFixContract', $contract);
  186. $this->assertEquals(1000, $contract->getFixPrice());
  187. }
  188. public function testUpdateChildClassWithCondition()
  189. {
  190. $this->loadFullFixture();
  191. $dql = 'UPDATE Doctrine\Tests\Models\Company\CompanyFlexContract c SET c.hoursWorked = c.hoursWorked * 2 WHERE c.hoursWorked = 150';
  192. $affected = $this->_em->createQuery($dql)->execute();
  193. $this->assertEquals(1, $affected);
  194. $flexContract = $this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->flex->getId());
  195. $ultraContract = $this->_em->find('Doctrine\Tests\Models\Company\CompanyContract', $this->ultra->getId());
  196. $this->assertEquals(300, $ultraContract->getHoursWorked());
  197. $this->assertEquals(100, $flexContract->getHoursWorked());
  198. }
  199. public function testUpdateBaseClassWithCondition()
  200. {
  201. $this->loadFullFixture();
  202. $dql = 'UPDATE Doctrine\Tests\Models\Company\CompanyContract c SET c.completed = true WHERE c.completed = false';
  203. $affected = $this->_em->createQuery($dql)->execute();
  204. $this->assertEquals(1, $affected);
  205. $dql = 'UPDATE Doctrine\Tests\Models\Company\CompanyContract c SET c.completed = false';
  206. $affected = $this->_em->createQuery($dql)->execute();
  207. $this->assertEquals(3, $affected);
  208. }
  209. public function testDeleteByChildClassCondition()
  210. {
  211. $this->loadFullFixture();
  212. $dql = 'DELETE Doctrine\Tests\Models\Company\CompanyFlexContract c';
  213. $affected = $this->_em->createQuery($dql)->execute();
  214. $this->assertEquals(2, $affected);
  215. }
  216. public function testDeleteByBaseClassCondition()
  217. {
  218. $this->loadFullFixture();
  219. $dql = "DELETE Doctrine\Tests\Models\Company\CompanyContract c WHERE c.completed = true";
  220. $affected = $this->_em->createQuery($dql)->execute();
  221. $this->assertEquals(2, $affected);
  222. $contracts = $this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c')->getResult();
  223. $this->assertEquals(1, count($contracts));
  224. $this->assertFalse($contracts[0]->isCompleted(), "Only non completed contracts should be left.");
  225. }
  226. /**
  227. * @group DDC-130
  228. */
  229. public function testDeleteJoinTableRecords()
  230. {
  231. $this->loadFullFixture();
  232. // remove managed copy of the fix contract
  233. $this->_em->remove($this->_em->find(get_class($this->fix), $this->fix->getId()));
  234. $this->_em->flush();
  235. $this->assertNull($this->_em->find(get_class($this->fix), $this->fix->getId()), "Contract should not be present in the database anymore.");
  236. }
  237. /**
  238. * @group DDC-817
  239. */
  240. public function testFindByAssociation()
  241. {
  242. $this->loadFullFixture();
  243. $repos = $this->_em->getRepository("Doctrine\Tests\Models\Company\CompanyContract");
  244. $contracts = $repos->findBy(array('salesPerson' => $this->salesPerson->getId()));
  245. $this->assertEquals(3, count($contracts), "There should be 3 entities related to " . $this->salesPerson->getId() . " for 'Doctrine\Tests\Models\Company\CompanyContract'");
  246. $repos = $this->_em->getRepository("Doctrine\Tests\Models\Company\CompanyFixContract");
  247. $contracts = $repos->findBy(array('salesPerson' => $this->salesPerson->getId()));
  248. $this->assertEquals(1, count($contracts), "There should be 1 entities related to " . $this->salesPerson->getId() . " for 'Doctrine\Tests\Models\Company\CompanyFixContract'");
  249. $repos = $this->_em->getRepository("Doctrine\Tests\Models\Company\CompanyFlexContract");
  250. $contracts = $repos->findBy(array('salesPerson' => $this->salesPerson->getId()));
  251. $this->assertEquals(2, count($contracts), "There should be 2 entities related to " . $this->salesPerson->getId() . " for 'Doctrine\Tests\Models\Company\CompanyFlexContract'");
  252. $repos = $this->_em->getRepository("Doctrine\Tests\Models\Company\CompanyFlexUltraContract");
  253. $contracts = $repos->findBy(array('salesPerson' => $this->salesPerson->getId()));
  254. $this->assertEquals(1, count($contracts), "There should be 1 entities related to " . $this->salesPerson->getId() . " for 'Doctrine\Tests\Models\Company\CompanyFlexUltraContract'");
  255. }
  256. /**
  257. * @group DDC-834
  258. */
  259. public function testGetReferenceEntityWithSubclasses()
  260. {
  261. $this->loadFullFixture();
  262. $ref = $this->_em->getReference('Doctrine\Tests\Models\Company\CompanyContract', $this->fix->getId());
  263. $this->assertNotInstanceOf('Doctrine\ORM\Proxy\Proxy', $ref, "Cannot Request a proxy from a class that has subclasses.");
  264. $this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyContract', $ref);
  265. $this->assertInstanceOf('Doctrine\Tests\Models\Company\CompanyFixContract', $ref, "Direct fetch of the reference has to load the child class Emplyoee directly.");
  266. $this->_em->clear();
  267. $ref = $this->_em->getReference('Doctrine\Tests\Models\Company\CompanyFixContract', $this->fix->getId());
  268. $this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $ref, "A proxy can be generated only if no subclasses exists for the requested reference.");
  269. }
  270. /**
  271. * @group DDC-952
  272. */
  273. public function testEagerLoadInheritanceHierachy()
  274. {
  275. $this->loadFullFixture();
  276. $dql = 'SELECT f FROM Doctrine\Tests\Models\Company\CompanyFixContract f WHERE f.id = ?1';
  277. $contract = $this->_em->createQuery($dql)
  278. ->setFetchMode('Doctrine\Tests\Models\Company\CompanyFixContract', 'salesPerson', ClassMetadata::FETCH_EAGER)
  279. ->setParameter(1, $this->fix->getId())
  280. ->getSingleResult();
  281. $this->assertNotInstanceOf('Doctrine\ORM\Proxy\Proxy', $contract->getSalesPerson());
  282. }
  283. /**
  284. * @group DDC-1770
  285. */
  286. public function testTwoSingleTableInheritanceInFromClause()
  287. {
  288. $dql = 'SELECT f1,f2 FROM Doctrine\Tests\Models\Company\CompanyFixContract f1, Doctrine\Tests\Models\Company\CompanyFixContract f2';
  289. $result = $this->_em->createQuery($dql)->getResult();
  290. }
  291. }