ActiveRecordTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. <?php
  2. namespace yiiunit\extensions\mongodb;
  3. use MongoDB\BSON\Binary;
  4. use MongoDB\BSON\ObjectID;
  5. use MongoDB\BSON\Regex;
  6. use yii\mongodb\ActiveQuery;
  7. use yiiunit\extensions\mongodb\data\ar\ActiveRecord;
  8. use yiiunit\extensions\mongodb\data\ar\Customer;
  9. use yiiunit\extensions\mongodb\data\ar\Animal;
  10. use yiiunit\extensions\mongodb\data\ar\Dog;
  11. use yiiunit\extensions\mongodb\data\ar\Cat;
  12. class ActiveRecordTest extends TestCase
  13. {
  14. /**
  15. * @var array[] list of test rows.
  16. */
  17. protected $testRows = [];
  18. protected function setUp()
  19. {
  20. parent::setUp();
  21. ActiveRecord::$db = $this->getConnection();
  22. $this->setUpTestRows();
  23. }
  24. protected function tearDown()
  25. {
  26. $this->dropCollection(Customer::collectionName());
  27. parent::tearDown();
  28. }
  29. /**
  30. * Sets up test rows.
  31. */
  32. protected function setUpTestRows()
  33. {
  34. $collection = $this->getConnection()->getCollection('customer');
  35. $rows = [];
  36. for ($i = 1; $i <= 10; $i++) {
  37. $rows[] = [
  38. 'name' => 'name' . $i,
  39. 'email' => 'email' . $i,
  40. 'address' => 'address' . $i,
  41. 'status' => $i,
  42. ];
  43. }
  44. $this->testRows = $collection->batchInsert($rows);
  45. }
  46. // Tests :
  47. public function testFind()
  48. {
  49. // find one
  50. $result = Customer::find();
  51. $this->assertTrue($result instanceof ActiveQuery);
  52. $customer = $result->one();
  53. $this->assertTrue($customer instanceof Customer);
  54. // find all
  55. $customers = Customer::find()->all();
  56. $this->assertEquals(10, count($customers));
  57. $this->assertTrue($customers[0] instanceof Customer);
  58. $this->assertTrue($customers[1] instanceof Customer);
  59. // find by _id
  60. $testId = $this->testRows[0]['_id'];
  61. $customer = Customer::findOne($testId);
  62. $this->assertTrue($customer instanceof Customer);
  63. $this->assertEquals($testId, $customer->_id);
  64. // find by column values
  65. $customer = Customer::findOne(['name' => 'name5']);
  66. $this->assertTrue($customer instanceof Customer);
  67. $this->assertEquals($this->testRows[4]['_id'], $customer->_id);
  68. $this->assertEquals('name5', $customer->name);
  69. $customer = Customer::findOne(['name' => 'unexisting name']);
  70. $this->assertNull($customer);
  71. // find by attributes
  72. $customer = Customer::find()->where(['status' => 4])->one();
  73. $this->assertTrue($customer instanceof Customer);
  74. $this->assertEquals(4, $customer->status);
  75. // find count, sum, average, min, max, distinct
  76. $this->assertEquals(10, Customer::find()->count());
  77. $this->assertEquals(1, Customer::find()->where(['status' => 2])->count());
  78. $this->assertEquals((1+10)/2*10, Customer::find()->sum('status'));
  79. $this->assertEquals((1+10)/2, Customer::find()->average('status'));
  80. $this->assertEquals(1, Customer::find()->min('status'));
  81. $this->assertEquals(10, Customer::find()->max('status'));
  82. $this->assertEquals(range(1, 10), Customer::find()->distinct('status'));
  83. // scope
  84. $this->assertEquals(1, Customer::find()->activeOnly()->count());
  85. // asArray
  86. $testRow = $this->testRows[2];
  87. $customer = Customer::find()->where(['_id' => $testRow['_id']])->asArray()->one();
  88. $this->assertEquals($testRow, $customer);
  89. // indexBy
  90. $customers = Customer::find()->indexBy('name')->all();
  91. $this->assertTrue($customers['name1'] instanceof Customer);
  92. $this->assertTrue($customers['name2'] instanceof Customer);
  93. // indexBy callable
  94. $customers = Customer::find()->indexBy(function ($customer) {
  95. return $customer->status . '-' . $customer->status;
  96. })->all();
  97. $this->assertTrue($customers['1-1'] instanceof Customer);
  98. $this->assertTrue($customers['2-2'] instanceof Customer);
  99. }
  100. public function testInsert()
  101. {
  102. $record = new Customer();
  103. $record->name = 'new name';
  104. $record->email = 'new email';
  105. $record->address = 'new address';
  106. $record->status = 7;
  107. $this->assertTrue($record->isNewRecord);
  108. $record->save();
  109. $this->assertTrue($record->_id instanceof ObjectID);
  110. $this->assertFalse($record->isNewRecord);
  111. }
  112. /**
  113. * @depends testInsert
  114. */
  115. public function testUpdate()
  116. {
  117. $record = new Customer();
  118. $record->name = 'new name';
  119. $record->email = 'new email';
  120. $record->address = 'new address';
  121. $record->status = 7;
  122. $record->save();
  123. // save
  124. $record = Customer::findOne($record->_id);
  125. $this->assertTrue($record instanceof Customer);
  126. $this->assertEquals(7, $record->status);
  127. $this->assertFalse($record->isNewRecord);
  128. $record->status = 9;
  129. $record->save();
  130. $this->assertEquals(9, $record->status);
  131. $this->assertFalse($record->isNewRecord);
  132. $record2 = Customer::findOne($record->_id);
  133. $this->assertEquals(9, $record2->status);
  134. $this->assertEquals('new name', $record2->name);
  135. // updateAll
  136. $pk = ['_id' => $record->_id];
  137. $ret = Customer::updateAll(['status' => 55], $pk);
  138. $this->assertEquals(1, $ret);
  139. $record = Customer::findOne($pk);
  140. $this->assertEquals(55, $record->status);
  141. }
  142. /**
  143. * @depends testInsert
  144. */
  145. public function testDelete()
  146. {
  147. // delete
  148. $record = new Customer();
  149. $record->name = 'new name';
  150. $record->email = 'new email';
  151. $record->address = 'new address';
  152. $record->status = 7;
  153. $record->save();
  154. $record = Customer::findOne($record->_id);
  155. $record->delete();
  156. $record = Customer::findOne($record->_id);
  157. $this->assertNull($record);
  158. // deleteAll
  159. $record = new Customer();
  160. $record->name = 'new name';
  161. $record->email = 'new email';
  162. $record->address = 'new address';
  163. $record->status = 7;
  164. $record->save();
  165. $ret = Customer::deleteAll(['name' => 'new name']);
  166. $this->assertEquals(1, $ret);
  167. $records = Customer::find()->where(['name' => 'new name'])->all();
  168. $this->assertEquals(0, count($records));
  169. }
  170. public function testUpdateAllCounters()
  171. {
  172. $this->assertEquals(1, Customer::updateAllCounters(['status' => 10], ['status' => 10]));
  173. $record = Customer::findOne(['status' => 10]);
  174. $this->assertNull($record);
  175. }
  176. /**
  177. * @depends testUpdateAllCounters
  178. */
  179. public function testUpdateCounters()
  180. {
  181. $record = Customer::findOne($this->testRows[9]);
  182. $originalCounter = $record->status;
  183. $counterIncrement = 20;
  184. $record->updateCounters(['status' => $counterIncrement]);
  185. $this->assertEquals($originalCounter + $counterIncrement, $record->status);
  186. $refreshedRecord = Customer::findOne($record->_id);
  187. $this->assertEquals($originalCounter + $counterIncrement, $refreshedRecord->status);
  188. }
  189. /**
  190. * @depends testUpdate
  191. */
  192. public function testUpdateNestedAttribute()
  193. {
  194. $record = new Customer();
  195. $record->name = 'new name';
  196. $record->email = 'new email';
  197. $record->address = [
  198. 'city' => 'SomeCity',
  199. 'street' => 'SomeStreet',
  200. ];
  201. $record->status = 7;
  202. $record->save();
  203. // save
  204. $record = Customer::findOne($record->_id);
  205. $newAddress = [
  206. 'city' => 'AnotherCity'
  207. ];
  208. $record->address = $newAddress;
  209. $record->save();
  210. $record2 = Customer::findOne($record->_id);
  211. $this->assertEquals($newAddress, $record2->address);
  212. }
  213. /**
  214. * @depends testFind
  215. * @depends testInsert
  216. */
  217. public function testQueryByIntegerField()
  218. {
  219. $record = new Customer();
  220. $record->name = 'new name';
  221. $record->status = 7;
  222. $record->save();
  223. $row = Customer::find()->where(['status' => 7])->one();
  224. $this->assertNotEmpty($row);
  225. $this->assertEquals(7, $row->status);
  226. $rowRefreshed = Customer::find()->where(['status' => $row->status])->one();
  227. $this->assertNotEmpty($rowRefreshed);
  228. $this->assertEquals(7, $rowRefreshed->status);
  229. }
  230. public function testExists()
  231. {
  232. $exists = Customer::find()
  233. ->where(['name' => 'name1'])
  234. ->exists();
  235. $this->assertTrue($exists);
  236. $exists = Customer::find()
  237. ->where(['name' => 'not existing name'])
  238. ->exists();
  239. $this->assertFalse($exists);
  240. }
  241. public function testScalar()
  242. {
  243. $connection = $this->getConnection();
  244. $result = Customer::find()
  245. ->select(['name' => true, '_id' => false])
  246. ->orderBy(['name' => SORT_ASC])
  247. ->limit(1)
  248. ->scalar($connection);
  249. $this->assertSame('name1', $result);
  250. $result = Customer::find()
  251. ->select(['name' => true, '_id' => false])
  252. ->andWhere(['status' => -1])
  253. ->scalar($connection);
  254. $this->assertSame(false, $result);
  255. $result = Customer::find()
  256. ->select(['name'])
  257. ->orderBy(['name' => SORT_ASC])
  258. ->limit(1)
  259. ->scalar($connection);
  260. $this->assertSame('name1', $result);
  261. $result = Customer::find()
  262. ->select(['_id'])
  263. ->limit(1)
  264. ->scalar($connection);
  265. $this->assertTrue($result instanceof ObjectID);
  266. }
  267. public function testColumn()
  268. {
  269. $connection = $this->getConnection();
  270. $result = Customer::find()
  271. ->select(['name' => true, '_id' => false])
  272. ->orderBy(['name' => SORT_ASC])
  273. ->limit(2)
  274. ->column($connection);
  275. $this->assertEquals(['name1', 'name10'], $result);
  276. $result = Customer::find()
  277. ->select(['name' => true, '_id' => false])
  278. ->andWhere(['status' => -1])
  279. ->orderBy(['name' => SORT_ASC])
  280. ->limit(2)
  281. ->column($connection);
  282. $this->assertEquals([], $result);
  283. $result = Customer::find()
  284. ->select(['name'])
  285. ->orderBy(['name' => SORT_ASC])
  286. ->limit(2)
  287. ->column($connection);
  288. $this->assertEquals(['name1', 'name10'], $result);
  289. $result = Customer::find()
  290. ->select(['_id'])
  291. ->orderBy(['name' => SORT_ASC])
  292. ->limit(2)
  293. ->column($connection);
  294. $this->assertTrue($result[0] instanceof ObjectID);
  295. $this->assertTrue($result[1] instanceof ObjectID);
  296. }
  297. public function testModify()
  298. {
  299. $searchName = 'name7';
  300. $newName = 'new name';
  301. $customer = Customer::find()
  302. ->where(['name' => $searchName])
  303. ->modify(['$set' => ['name' => $newName]], ['new' => true]);
  304. $this->assertTrue($customer instanceof Customer);
  305. $this->assertEquals($newName, $customer->name);
  306. $customer = Customer::find()
  307. ->where(['name' => 'not existing name'])
  308. ->modify(['$set' => ['name' => $newName]], ['new' => false]);
  309. $this->assertNull($customer);
  310. }
  311. /**
  312. * @depends testInsert
  313. *
  314. * @see https://github.com/yiisoft/yii2/issues/6026
  315. */
  316. public function testInsertEmptyAttributes()
  317. {
  318. $record = new Customer();
  319. $record->save(false);
  320. $this->assertTrue($record->_id instanceof ObjectID);
  321. $this->assertFalse($record->isNewRecord);
  322. }
  323. /**
  324. * @depends testFind
  325. * @depends testInsert
  326. */
  327. public function testPopulateRecordCallWhenQueryingOnParentClass()
  328. {
  329. (new Cat())->save(false);
  330. (new Dog())->save(false);
  331. $animal = Animal::find()->where(['type' => Dog::className()])->one();
  332. $this->assertEquals('bark', $animal->getDoes());
  333. $animal = Animal::find()->where(['type' => Cat::className()])->one();
  334. $this->assertEquals('meow', $animal->getDoes());
  335. }
  336. /**
  337. * @see https://github.com/yiisoft/yii2-mongodb/issues/79
  338. */
  339. public function testToArray()
  340. {
  341. $record = new Customer();
  342. $record->name = 'test name';
  343. $record->email = new Regex('[a-z]@[a-z]', 'i');
  344. $record->address = new Binary('abcdef', Binary::TYPE_MD5);
  345. $record->status = 1;
  346. $record->file_id = new Binary('Test Binary', Binary::TYPE_GENERIC);;
  347. $record->save(false);
  348. $this->assertEquals($record->attributes, $record->toArray([], [], false));
  349. $array = $record->toArray([], [], true);
  350. $this->assertTrue(is_string($array['_id']));
  351. $this->assertEquals('/[a-z]@[a-z]/i', $array['email']);
  352. $this->assertEquals('abcdef', $array['address']);
  353. $this->assertEquals('Test Binary', $array['file_id']);
  354. }
  355. /**
  356. * @depends testInsert
  357. *
  358. * @see https://github.com/yiisoft/yii2-mongodb/pull/146
  359. */
  360. public function testInsertCustomId()
  361. {
  362. $record = new Customer();
  363. $record->_id = 'custom';
  364. $record->name = 'new name';
  365. $record->email = 'new email';
  366. $record->address = 'new address';
  367. $record->status = 7;
  368. $record->save(false);
  369. $this->assertEquals('custom', $record->_id);
  370. }
  371. public function testEmulateExecution()
  372. {
  373. if (!Customer::find()->hasMethod('emulateExecution')) {
  374. $this->markTestSkipped('"yii2" version 2.0.11 or higher required');
  375. }
  376. $this->assertGreaterThan(0, Customer::find()->from('customer')->count());
  377. $rows = Customer::find()
  378. ->from('customer')
  379. ->emulateExecution()
  380. ->all();
  381. $this->assertSame([], $rows);
  382. $row = Customer::find()
  383. ->from('customer')
  384. ->emulateExecution()
  385. ->one();
  386. $this->assertSame(null, $row);
  387. $exists = Customer::find()
  388. ->from('customer')
  389. ->emulateExecution()
  390. ->exists();
  391. $this->assertSame(false, $exists);
  392. $count = Customer::find()
  393. ->from('customer')
  394. ->emulateExecution()
  395. ->count();
  396. $this->assertSame(0, $count);
  397. $sum = Customer::find()
  398. ->from('customer')
  399. ->emulateExecution()
  400. ->sum('id');
  401. $this->assertSame(0, $sum);
  402. $sum = Customer::find()
  403. ->from('customer')
  404. ->emulateExecution()
  405. ->average('id');
  406. $this->assertSame(0, $sum);
  407. $max = Customer::find()
  408. ->from('customer')
  409. ->emulateExecution()
  410. ->max('id');
  411. $this->assertSame(null, $max);
  412. $min = Customer::find()
  413. ->from('customer')
  414. ->emulateExecution()
  415. ->min('id');
  416. $this->assertSame(null, $min);
  417. $scalar = Customer::find()
  418. ->select(['id'])
  419. ->from('customer')
  420. ->emulateExecution()
  421. ->scalar();
  422. $this->assertSame(null, $scalar);
  423. $column = Customer::find()
  424. ->select(['id'])
  425. ->from('customer')
  426. ->emulateExecution()
  427. ->column();
  428. $this->assertSame([], $column);
  429. $row = Customer::find()
  430. ->select(['id'])
  431. ->from('customer')
  432. ->emulateExecution()
  433. ->modify(['name' => 'new name']);
  434. $this->assertSame(null, $row);
  435. $values = Customer::find()
  436. ->select(['id'])
  437. ->from('customer')
  438. ->emulateExecution()
  439. ->distinct('name');
  440. $this->assertSame([], $values);
  441. }
  442. }