ManyToManyBasicAssociationTest.php 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. <?php
  2. namespace Doctrine\Tests\ORM\Functional;
  3. use Doctrine\Tests\Models\CMS\CmsUser,
  4. Doctrine\Tests\Models\CMS\CmsGroup,
  5. Doctrine\Common\Collections\ArrayCollection;
  6. require_once __DIR__ . '/../../TestInit.php';
  7. /**
  8. * Basic many-to-many association tests.
  9. * ("Working with associations")
  10. *
  11. * @author robo
  12. */
  13. class ManyToManyBasicAssociationTest extends \Doctrine\Tests\OrmFunctionalTestCase
  14. {
  15. protected function setUp()
  16. {
  17. $this->useModelSet('cms');
  18. parent::setUp();
  19. }
  20. public function testUnsetManyToMany()
  21. {
  22. $user = $this->addCmsUserGblancoWithGroups(1);
  23. unset($user->groups[0]->users[0]); // inverse side
  24. unset($user->groups[0]); // owning side!
  25. $this->_em->flush();
  26. // Check that the link in the association table has been deleted
  27. $this->assertGblancoGroupCountIs(0);
  28. }
  29. public function testBasicManyToManyJoin()
  30. {
  31. $user = $this->addCmsUserGblancoWithGroups(1);
  32. $this->_em->clear();
  33. $this->assertEquals(0, $this->_em->getUnitOfWork()->size());
  34. $query = $this->_em->createQuery("select u, g from Doctrine\Tests\Models\CMS\CmsUser u join u.groups g");
  35. $result = $query->getResult();
  36. $this->assertEquals(2, $this->_em->getUnitOfWork()->size());
  37. $this->assertTrue($result[0] instanceof CmsUser);
  38. $this->assertEquals('Guilherme', $result[0]->name);
  39. $this->assertEquals(1, $result[0]->getGroups()->count());
  40. $groups = $result[0]->getGroups();
  41. $this->assertEquals('Developers_0', $groups[0]->getName());
  42. $this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_MANAGED, $this->_em->getUnitOfWork()->getEntityState($result[0]));
  43. $this->assertEquals(\Doctrine\ORM\UnitOfWork::STATE_MANAGED, $this->_em->getUnitOfWork()->getEntityState($groups[0]));
  44. $this->assertTrue($groups instanceof \Doctrine\ORM\PersistentCollection);
  45. $this->assertTrue($groups[0]->getUsers() instanceof \Doctrine\ORM\PersistentCollection);
  46. $groups[0]->getUsers()->clear();
  47. $groups->clear();
  48. $this->_em->flush();
  49. $this->_em->clear();
  50. $query = $this->_em->createQuery("select u, g from Doctrine\Tests\Models\CMS\CmsUser u join u.groups g");
  51. $this->assertEquals(0, count($query->getResult()));
  52. }
  53. public function testManyToManyAddRemove()
  54. {
  55. $user = $this->addCmsUserGblancoWithGroups(2);
  56. $this->_em->clear();
  57. $uRep = $this->_em->getRepository(get_class($user));
  58. // Get user
  59. $user = $uRep->findOneById($user->getId());
  60. $this->assertNotNull($user, "Has to return exactly one entry.");
  61. $this->assertFalse($user->getGroups()->isInitialized());
  62. // Check groups
  63. $this->assertEquals(2, $user->getGroups()->count());
  64. $this->assertTrue($user->getGroups()->isInitialized());
  65. // Remove first group
  66. unset($user->groups[0]);
  67. //$user->getGroups()->remove(0);
  68. $this->_em->flush();
  69. $this->_em->clear();
  70. // Reload same user
  71. $user2 = $uRep->findOneById($user->getId());
  72. // Check groups
  73. $this->assertEquals(1, $user2->getGroups()->count());
  74. }
  75. public function testManyToManyInverseSideIgnored()
  76. {
  77. $user = $this->addCmsUserGblancoWithGroups(0);
  78. $group = new CmsGroup;
  79. $group->name = 'Humans';
  80. // modify directly, addUser() would also (properly) set the owning side
  81. $group->users[] = $user;
  82. $this->_em->persist($user);
  83. $this->_em->persist($group);
  84. $this->_em->flush();
  85. $this->_em->clear();
  86. // Association should not exist
  87. $user2 = $this->_em->find(get_class($user), $user->getId());
  88. $this->assertNotNull($user2, "Has to return exactly one entry.");
  89. $this->assertEquals(0, $user2->getGroups()->count());
  90. }
  91. public function testManyToManyCollectionClearing()
  92. {
  93. $user = $this->addCmsUserGblancoWithGroups($groupCount = 10);
  94. // Check that there are indeed 10 links in the association table
  95. $this->assertGblancoGroupCountIs($groupCount);
  96. $user->groups->clear();
  97. $this->_em->flush();
  98. // Check that the links in the association table have been deleted
  99. $this->assertGblancoGroupCountIs(0);
  100. }
  101. public function testManyToManyCollectionClearAndAdd()
  102. {
  103. $user = $this->addCmsUserGblancoWithGroups($groupCount = 10);
  104. $groups = $user->groups->toArray();
  105. $user->groups->clear();
  106. foreach ($groups AS $group) {
  107. $user->groups[] = $group;
  108. }
  109. $this->assertInstanceOf('Doctrine\ORM\PersistentCollection', $user->groups);
  110. $this->assertTrue($user->groups->isDirty());
  111. $this->assertEquals($groupCount, count($user->groups), "There should be 10 groups in the collection.");
  112. $this->_em->flush();
  113. $this->assertGblancoGroupCountIs($groupCount);
  114. }
  115. /**
  116. * @param int $expectedGroupCount
  117. */
  118. public function assertGblancoGroupCountIs($expectedGroupCount)
  119. {
  120. $countDql = "SELECT count(g.id) FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g WHERE u.username = 'gblanco'";
  121. $this->assertEquals(
  122. $expectedGroupCount,
  123. $this->_em->createQuery($countDql)->getSingleScalarResult(),
  124. "Failed to verify that CmsUser with username 'gblanco' has a group count of 10 with a DQL count query."
  125. );
  126. }
  127. public function testRetrieveManyToManyAndAddMore()
  128. {
  129. $user = $this->addCmsUserGblancoWithGroups(2);
  130. $group = new CmsGroup();
  131. $group->name = 'Developers_Fresh';
  132. $this->_em->persist($group);
  133. $this->_em->flush();
  134. $this->_em->clear();
  135. /* @var $freshUser CmsUser */
  136. $freshUser = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $user->getId());
  137. $newGroup = new CmsGroup();
  138. $newGroup->setName('12Monkeys');
  139. $freshUser->addGroup($newGroup);
  140. $this->assertFalse($freshUser->groups->isInitialized(), "CmsUser::groups Collection has to be uninitialized for this test.");
  141. $this->_em->flush();
  142. $this->assertFalse($freshUser->groups->isInitialized(), "CmsUser::groups Collection has to be uninitialized for this test.");
  143. $this->assertEquals(3, count($freshUser->getGroups()));
  144. $this->assertEquals(3, count($freshUser->getGroups()->getSnapshot()), "Snapshot of CmsUser::groups should contain 3 entries.");
  145. $this->_em->clear();
  146. $freshUser = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $user->getId());
  147. $this->assertEquals(3, count($freshUser->getGroups()));
  148. }
  149. /**
  150. * @group DDC-130
  151. */
  152. public function testRemoveUserWithManyGroups()
  153. {
  154. $user = $this->addCmsUserGblancoWithGroups(2);
  155. $userId = $user->getId();
  156. $this->_em->remove($user);
  157. $this->_em->flush();
  158. $newUser = $this->_em->find(get_class($user), $userId);
  159. $this->assertNull($newUser);
  160. }
  161. /**
  162. * @group DDC-130
  163. */
  164. public function testRemoveGroupWithUser()
  165. {
  166. $user = $this->addCmsUserGblancoWithGroups(2);
  167. foreach ($user->getGroups() AS $group) {
  168. $this->_em->remove($group);
  169. }
  170. $this->_em->flush();
  171. $this->_em->clear();
  172. $newUser = $this->_em->find(get_class($user), $user->getId());
  173. $this->assertEquals(0, count($newUser->getGroups()));
  174. }
  175. public function testDereferenceCollectionDelete()
  176. {
  177. $user = $this->addCmsUserGblancoWithGroups(2);
  178. $user->groups = null;
  179. $this->_em->flush();
  180. $this->_em->clear();
  181. $newUser = $this->_em->find(get_class($user), $user->getId());
  182. $this->assertEquals(0, count($newUser->getGroups()));
  183. }
  184. /**
  185. * @group DDC-839
  186. */
  187. public function testWorkWithDqlHydratedEmptyCollection()
  188. {
  189. $user = $this->addCmsUserGblancoWithGroups(0);
  190. $group = new CmsGroup();
  191. $group->name = "Developers0";
  192. $this->_em->persist($group);
  193. $this->_em->flush();
  194. $this->_em->clear();
  195. $newUser = $this->_em->createQuery('SELECT u, g FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN u.groups g WHERE u.id = ?1')
  196. ->setParameter(1, $user->getId())
  197. ->getSingleResult();
  198. $this->assertEquals(0, count($newUser->groups));
  199. $this->assertInternalType('array', $newUser->groups->getMapping());
  200. $newUser->addGroup($group);
  201. $this->_em->flush();
  202. $this->_em->clear();
  203. $newUser = $this->_em->find(get_class($user), $user->getId());
  204. $this->assertEquals(1, count($newUser->groups));
  205. }
  206. /**
  207. * @param int $groupCount
  208. * @return CmsUser
  209. */
  210. public function addCmsUserGblancoWithGroups($groupCount = 1)
  211. {
  212. $user = new CmsUser;
  213. $user->name = 'Guilherme';
  214. $user->username = 'gblanco';
  215. $user->status = 'developer';
  216. for ($i=0; $i < $groupCount; ++$i) {
  217. $group = new CmsGroup;
  218. $group->name = 'Developers_' . $i;
  219. $user->addGroup($group);
  220. }
  221. $this->_em->persist($user);
  222. $this->_em->flush();
  223. $this->assertNotNull($user->getId(), "User 'gblanco' should have an ID assigned after the persist()/flush() operation.");
  224. return $user;
  225. }
  226. /**
  227. * @group DDC-980
  228. */
  229. public function testUpdateDeleteSizeSubselectQueries()
  230. {
  231. $this->_em->createQuery("DELETE Doctrine\Tests\Models\CMS\CmsUser u WHERE SIZE(u.groups) = 10")->execute();
  232. $this->_em->createQuery("UPDATE Doctrine\Tests\Models\CMS\CmsUser u SET u.status = 'inactive' WHERE SIZE(u.groups) = 10")->execute();
  233. }
  234. /**
  235. * @group DDC-978
  236. */
  237. public function testClearAndResetCollection()
  238. {
  239. $user = $this->addCmsUserGblancoWithGroups(2);
  240. $group1 = new CmsGroup;
  241. $group1->name = 'Developers_New1';
  242. $group2 = new CmsGroup;
  243. $group2->name = 'Developers_New2';
  244. $this->_em->persist($group1);
  245. $this->_em->persist($group2);
  246. $this->_em->flush();
  247. $this->_em->clear();
  248. $user = $this->_em->find(get_class($user), $user->id);
  249. $coll = new ArrayCollection(array($group1, $group2));
  250. $user->groups = $coll;
  251. $this->_em->flush();
  252. $this->assertInstanceOf('Doctrine\ORM\PersistentCollection', $user->groups,
  253. "UnitOfWork should have replaced ArrayCollection with PersistentCollection.");
  254. $this->_em->flush();
  255. $this->_em->clear();
  256. $user = $this->_em->find(get_class($user), $user->id);
  257. $this->assertEquals(2, count($user->groups));
  258. $this->assertEquals('Developers_New1', $user->groups[0]->name);
  259. $this->assertEquals('Developers_New2', $user->groups[1]->name);
  260. }
  261. /**
  262. * @group DDC-733
  263. */
  264. public function testInitializePersistentCollection()
  265. {
  266. $user = $this->addCmsUserGblancoWithGroups(2);
  267. $this->_em->clear();
  268. $user = $this->_em->find(get_class($user), $user->id);
  269. $this->assertFalse($user->groups->isInitialized(), "Pre-condition: lazy collection");
  270. $this->_em->getUnitOfWork()->initializeObject($user->groups);
  271. $this->assertTrue($user->groups->isInitialized(), "Collection should be initialized after calling UnitOfWork::initializeObject()");
  272. }
  273. /**
  274. * @group DDC-1189
  275. * @group DDC-956
  276. */
  277. public function testClearBeforeLazyLoad()
  278. {
  279. $user = $this->addCmsUserGblancoWithGroups(4);
  280. $this->_em->clear();
  281. $user = $this->_em->find(get_class($user), $user->id);
  282. $user->groups->clear();
  283. $this->assertEquals(0, count($user->groups));
  284. $this->_em->flush();
  285. $user = $this->_em->find(get_class($user), $user->id);
  286. $this->assertEquals(0, count($user->groups));
  287. }
  288. }