ActiveRecordTest.php 16.1 KB
Newer Older
Qiang Xue committed
1
<?php
Qiang Xue committed
2
namespace yiiunit\framework\db;
Qiang Xue committed
3

Qiang Xue committed
4
use yii\db\ActiveQuery;
Qiang Xue committed
5 6
use yiiunit\data\ar\ActiveRecord;
use yiiunit\data\ar\Customer;
7
use yiiunit\data\ar\NullValues;
Qiang Xue committed
8
use yiiunit\data\ar\OrderItem;
Qiang Xue committed
9
use yiiunit\data\ar\Order;
Qiang Xue committed
10
use yiiunit\data\ar\Item;
Qiang Xue committed
11

12 13 14 15
/**
 * @group db
 * @group mysql
 */
Alexander Makarov committed
16
class ActiveRecordTest extends DatabaseTestCase
Qiang Xue committed
17
{
Carsten Brandt committed
18
	protected function setUp()
Qiang Xue committed
19
	{
Alexander Makarov committed
20
		parent::setUp();
Qiang Xue committed
21 22 23
		ActiveRecord::$db = $this->getConnection();
	}

Qiang Xue committed
24 25 26 27 28 29 30 31 32
	public function testFind()
	{
		// find one
		$result = Customer::find();
		$this->assertTrue($result instanceof ActiveQuery);
		$customer = $result->one();
		$this->assertTrue($customer instanceof Customer);

		// find all
Qiang Xue committed
33
		$customers = Customer::find()->all();
Qiang Xue committed
34 35 36 37 38 39 40 41 42 43
		$this->assertEquals(3, count($customers));
		$this->assertTrue($customers[0] instanceof Customer);
		$this->assertTrue($customers[1] instanceof Customer);
		$this->assertTrue($customers[2] instanceof Customer);

		// find by a single primary key
		$customer = Customer::find(2);
		$this->assertTrue($customer instanceof Customer);
		$this->assertEquals('user2', $customer->name);

Qiang Xue committed
44
		// find by column values
Alexander Makarov committed
45
		$customer = Customer::find(['id' => 2, 'name' => 'user2']);
Qiang Xue committed
46 47
		$this->assertTrue($customer instanceof Customer);
		$this->assertEquals('user2', $customer->name);
Alexander Makarov committed
48
		$customer = Customer::find(['id' => 2, 'name' => 'user1']);
Qiang Xue committed
49 50
		$this->assertNull($customer);

Qiang Xue committed
51
		// find by attributes
Alexander Makarov committed
52
		$customer = Customer::find()->where(['name' => 'user2'])->one();
Qiang Xue committed
53 54 55
		$this->assertTrue($customer instanceof Customer);
		$this->assertEquals(2, $customer->id);

Qiang Xue committed
56
		// find custom column
Alexander Makarov committed
57 58
		$customer = Customer::find()->select(['*', '(status*2) AS status2'])
			->where(['name' => 'user3'])->one();
Qiang Xue committed
59 60
		$this->assertEquals(3, $customer->id);
		$this->assertEquals(4, $customer->status2);
Qiang Xue committed
61

62 63 64 65 66 67 68 69 70 71 72
		// find count, sum, average, min, max, scalar
		$this->assertEquals(3, Customer::find()->count());
		$this->assertEquals(2, Customer::find()->where('id=1 OR id=2')->count());
		$this->assertEquals(6, Customer::find()->sum('id'));
		$this->assertEquals(2, Customer::find()->average('id'));
		$this->assertEquals(1, Customer::find()->min('id'));
		$this->assertEquals(3, Customer::find()->max('id'));
		$this->assertEquals(3, Customer::find()->select('COUNT(*)')->scalar());

		// scope
		$this->assertEquals(2, Customer::find()->active()->count());
Qiang Xue committed
73 74 75

		// asArray
		$customer = Customer::find()->where('id=2')->asArray()->one();
Alexander Makarov committed
76
		$this->assertEquals([
Qiang Xue committed
77 78 79 80 81
			'id' => '2',
			'email' => 'user2@example.com',
			'name' => 'user2',
			'address' => 'address2',
			'status' => '1',
Alexander Makarov committed
82
		], $customer);
Qiang Xue committed
83 84 85 86 87 88 89

		// indexBy
		$customers = Customer::find()->indexBy('name')->orderBy('id')->all();
		$this->assertEquals(3, count($customers));
		$this->assertTrue($customers['user1'] instanceof Customer);
		$this->assertTrue($customers['user2'] instanceof Customer);
		$this->assertTrue($customers['user3'] instanceof Customer);
90 91

		// indexBy callable
Alexander Makarov committed
92
		$customers = Customer::find()->indexBy(function ($customer) {
93 94 95 96 97 98
			return $customer->id . '-' . $customer->name;
		})->orderBy('id')->all();
		$this->assertEquals(3, count($customers));
		$this->assertTrue($customers['1-user1'] instanceof Customer);
		$this->assertTrue($customers['2-user2'] instanceof Customer);
		$this->assertTrue($customers['3-user3'] instanceof Customer);
Qiang Xue committed
99 100 101 102 103 104 105 106 107 108 109 110 111 112
	}

	public function testFindBySql()
	{
		// find one
		$customer = Customer::findBySql('SELECT * FROM tbl_customer ORDER BY id DESC')->one();
		$this->assertTrue($customer instanceof Customer);
		$this->assertEquals('user3', $customer->name);

		// find all
		$customers = Customer::findBySql('SELECT * FROM tbl_customer')->all();
		$this->assertEquals(3, count($customers));

		// find with parameter binding
Alexander Makarov committed
113
		$customer = Customer::findBySql('SELECT * FROM tbl_customer WHERE id=:id', [':id' => 2])->one();
Qiang Xue committed
114 115 116
		$this->assertTrue($customer instanceof Customer);
		$this->assertEquals('user2', $customer->name);
	}
Qiang Xue committed
117

Qiang Xue committed
118 119
	public function testFindLazy()
	{
slavcodev committed
120
		/** @var Customer $customer */
Qiang Xue committed
121
		$customer = Customer::find(2);
122
		$this->assertFalse($customer->isRelationPopulated('orders'));
Qiang Xue committed
123
		$orders = $customer->orders;
124
		$this->assertTrue($customer->isRelationPopulated('orders'));
Qiang Xue committed
125
		$this->assertEquals(2, count($orders));
126
		$this->assertEquals(1, count($customer->populatedRelations));
Qiang Xue committed
127

128 129 130
		/** @var Customer $customer */
		$customer = Customer::find(2);
		$this->assertFalse($customer->isRelationPopulated('orders'));
Qiang Xue committed
131
		$orders = $customer->getOrders()->where('id=3')->all();
132 133 134
		$this->assertFalse($customer->isRelationPopulated('orders'));
		$this->assertEquals(0, count($customer->populatedRelations));

Qiang Xue committed
135 136 137 138 139 140 141 142
		$this->assertEquals(1, count($orders));
		$this->assertEquals(3, $orders[0]->id);
	}

	public function testFindEager()
	{
		$customers = Customer::find()->with('orders')->all();
		$this->assertEquals(3, count($customers));
143 144
		$this->assertTrue($customers[0]->isRelationPopulated('orders'));
		$this->assertTrue($customers[1]->isRelationPopulated('orders'));
Qiang Xue committed
145 146
		$this->assertEquals(1, count($customers[0]->orders));
		$this->assertEquals(2, count($customers[1]->orders));
147 148 149 150 151

		$customer = Customer::find()->with('orders')->one();
		$this->assertTrue($customer->isRelationPopulated('orders'));
		$this->assertEquals(1, count($customer->orders));
		$this->assertEquals(1, count($customer->populatedRelations));
Qiang Xue committed
152 153 154 155
	}

	public function testFindLazyVia()
	{
slavcodev committed
156
		/** @var Order $order */
Qiang Xue committed
157 158 159 160 161 162 163 164
		$order = Order::find(1);
		$this->assertEquals(1, $order->id);
		$this->assertEquals(2, count($order->items));
		$this->assertEquals(1, $order->items[0]->id);
		$this->assertEquals(2, $order->items[1]->id);

		$order = Order::find(1);
		$order->id = 100;
Alexander Makarov committed
165
		$this->assertEquals([], $order->items);
Qiang Xue committed
166 167 168
	}

	public function testFindEagerViaRelation()
Qiang Xue committed
169 170 171 172 173 174 175 176 177 178
	{
		$orders = Order::find()->with('items')->orderBy('id')->all();
		$this->assertEquals(3, count($orders));
		$order = $orders[0];
		$this->assertEquals(1, $order->id);
		$this->assertEquals(2, count($order->items));
		$this->assertEquals(1, $order->items[0]->id);
		$this->assertEquals(2, $order->items[1]->id);
	}

Qiang Xue committed
179 180
	public function testFindLazyViaTable()
	{
slavcodev committed
181
		/** @var Order $order */
Qiang Xue committed
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
		$order = Order::find(1);
		$this->assertEquals(1, $order->id);
		$this->assertEquals(2, count($order->books));
		$this->assertEquals(1, $order->items[0]->id);
		$this->assertEquals(2, $order->items[1]->id);

		$order = Order::find(2);
		$this->assertEquals(2, $order->id);
		$this->assertEquals(0, count($order->books));
	}

	public function testFindEagerViaTable()
	{
		$orders = Order::find()->with('books')->orderBy('id')->all();
		$this->assertEquals(3, count($orders));

		$order = $orders[0];
		$this->assertEquals(1, $order->id);
		$this->assertEquals(2, count($order->books));
		$this->assertEquals(1, $order->books[0]->id);
		$this->assertEquals(2, $order->books[1]->id);

		$order = $orders[1];
		$this->assertEquals(2, $order->id);
		$this->assertEquals(0, count($order->books));

		$order = $orders[2];
		$this->assertEquals(3, $order->id);
		$this->assertEquals(1, count($order->books));
		$this->assertEquals(2, $order->books[0]->id);
	}

Qiang Xue committed
214 215 216 217 218 219 220 221 222 223 224
	public function testFindNestedRelation()
	{
		$customers = Customer::find()->with('orders', 'orders.items')->all();
		$this->assertEquals(3, count($customers));
		$this->assertEquals(1, count($customers[0]->orders));
		$this->assertEquals(2, count($customers[1]->orders));
		$this->assertEquals(0, count($customers[2]->orders));
		$this->assertEquals(2, count($customers[0]->orders[0]->items));
		$this->assertEquals(3, count($customers[1]->orders[0]->items));
		$this->assertEquals(1, count($customers[1]->orders[1]->items));
	}
Qiang Xue committed
225

Qiang Xue committed
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
	public function testLink()
	{
		$customer = Customer::find(2);
		$this->assertEquals(2, count($customer->orders));

		// has many
		$order = new Order;
		$order->total = 100;
		$this->assertTrue($order->isNewRecord);
		$customer->link('orders', $order);
		$this->assertEquals(3, count($customer->orders));
		$this->assertFalse($order->isNewRecord);
		$this->assertEquals(3, count($customer->getOrders()->all()));
		$this->assertEquals(2, $order->customer_id);

		// belongs to
		$order = new Order;
		$order->total = 100;
		$this->assertTrue($order->isNewRecord);
		$customer = Customer::find(1);
		$this->assertNull($order->customer);
		$order->link('customer', $customer);
		$this->assertFalse($order->isNewRecord);
		$this->assertEquals(1, $order->customer_id);
		$this->assertEquals(1, $order->customer->id);

		// via table
		$order = Order::find(2);
		$this->assertEquals(0, count($order->books));
Alexander Makarov committed
255
		$orderItem = OrderItem::find(['order_id' => 2, 'item_id' => 1]);
Qiang Xue committed
256 257
		$this->assertNull($orderItem);
		$item = Item::find(1);
Alexander Makarov committed
258
		$order->link('books', $item, ['quantity' => 10, 'subtotal' => 100]);
Qiang Xue committed
259
		$this->assertEquals(1, count($order->books));
Alexander Makarov committed
260
		$orderItem = OrderItem::find(['order_id' => 2, 'item_id' => 1]);
Qiang Xue committed
261 262 263 264 265 266 267 268
		$this->assertTrue($orderItem instanceof OrderItem);
		$this->assertEquals(10, $orderItem->quantity);
		$this->assertEquals(100, $orderItem->subtotal);

		// via model
		$order = Order::find(1);
		$this->assertEquals(2, count($order->items));
		$this->assertEquals(2, count($order->orderItems));
Alexander Makarov committed
269
		$orderItem = OrderItem::find(['order_id' => 1, 'item_id' => 3]);
Qiang Xue committed
270 271
		$this->assertNull($orderItem);
		$item = Item::find(3);
Alexander Makarov committed
272
		$order->link('items', $item, ['quantity' => 10, 'subtotal' => 100]);
Qiang Xue committed
273 274
		$this->assertEquals(3, count($order->items));
		$this->assertEquals(3, count($order->orderItems));
Alexander Makarov committed
275
		$orderItem = OrderItem::find(['order_id' => 1, 'item_id' => 3]);
Qiang Xue committed
276 277 278 279 280 281 282 283 284 285
		$this->assertTrue($orderItem instanceof OrderItem);
		$this->assertEquals(10, $orderItem->quantity);
		$this->assertEquals(100, $orderItem->subtotal);
	}

	public function testUnlink()
	{
		// has many
		$customer = Customer::find(2);
		$this->assertEquals(2, count($customer->orders));
Qiang Xue committed
286
		$customer->unlink('orders', $customer->orders[1], true);
Qiang Xue committed
287 288 289 290 291 292 293
		$this->assertEquals(1, count($customer->orders));
		$this->assertNull(Order::find(3));

		// via model
		$order = Order::find(2);
		$this->assertEquals(3, count($order->items));
		$this->assertEquals(3, count($order->orderItems));
Qiang Xue committed
294
		$order->unlink('items', $order->items[2], true);
Qiang Xue committed
295 296 297 298 299 300
		$this->assertEquals(2, count($order->items));
		$this->assertEquals(2, count($order->orderItems));

		// via table
		$order = Order::find(1);
		$this->assertEquals(2, count($order->books));
Qiang Xue committed
301
		$order->unlink('books', $order->books[1], true);
Qiang Xue committed
302 303 304 305
		$this->assertEquals(1, count($order->books));
		$this->assertEquals(1, count($order->orderItems));
	}

Qiang Xue committed
306 307 308 309 310 311 312 313 314
	public function testInsert()
	{
		$customer = new Customer;
		$customer->email = 'user4@example.com';
		$customer->name = 'user4';
		$customer->address = 'address4';

		$this->assertNull($customer->id);
		$this->assertTrue($customer->isNewRecord);
315 316
		Customer::$afterSaveNewRecord = null;
		Customer::$afterSaveInsert = null;
Qiang Xue committed
317 318 319 320

		$customer->save();

		$this->assertEquals(4, $customer->id);
321 322
		$this->assertFalse(Customer::$afterSaveNewRecord);
		$this->assertTrue(Customer::$afterSaveInsert);
Qiang Xue committed
323 324 325 326 327 328 329 330 331 332
		$this->assertFalse($customer->isNewRecord);
	}

	public function testUpdate()
	{
		// save
		$customer = Customer::find(2);
		$this->assertTrue($customer instanceof Customer);
		$this->assertEquals('user2', $customer->name);
		$this->assertFalse($customer->isNewRecord);
333 334 335
		Customer::$afterSaveNewRecord = null;
		Customer::$afterSaveInsert = null;

Qiang Xue committed
336 337 338 339
		$customer->name = 'user2x';
		$customer->save();
		$this->assertEquals('user2x', $customer->name);
		$this->assertFalse($customer->isNewRecord);
340 341
		$this->assertFalse(Customer::$afterSaveNewRecord);
		$this->assertFalse(Customer::$afterSaveInsert);
Qiang Xue committed
342 343 344 345
		$customer2 = Customer::find(2);
		$this->assertEquals('user2x', $customer2->name);

		// updateCounters
Alexander Makarov committed
346
		$pk = ['order_id' => 2, 'item_id' => 4];
Qiang Xue committed
347 348
		$orderItem = OrderItem::find($pk);
		$this->assertEquals(1, $orderItem->quantity);
Alexander Makarov committed
349
		$ret = $orderItem->updateCounters(['quantity' => -1]);
Qiang Xue committed
350 351 352 353 354 355 356 357
		$this->assertTrue($ret);
		$this->assertEquals(0, $orderItem->quantity);
		$orderItem = OrderItem::find($pk);
		$this->assertEquals(0, $orderItem->quantity);

		// updateAll
		$customer = Customer::find(3);
		$this->assertEquals('user3', $customer->name);
Alexander Makarov committed
358
		$ret = Customer::updateAll(['name' => 'temp'], ['id' => 3]);
Qiang Xue committed
359 360 361 362 363
		$this->assertEquals(1, $ret);
		$customer = Customer::find(3);
		$this->assertEquals('temp', $customer->name);

		// updateCounters
Alexander Makarov committed
364
		$pk = ['order_id' => 1, 'item_id' => 2];
Qiang Xue committed
365 366
		$orderItem = OrderItem::find($pk);
		$this->assertEquals(2, $orderItem->quantity);
Alexander Makarov committed
367
		$ret = OrderItem::updateAllCounters([
Qiang Xue committed
368 369
			'quantity' => 3,
			'subtotal' => -10,
Alexander Makarov committed
370
		], $pk);
Qiang Xue committed
371 372 373 374 375
		$this->assertEquals(1, $ret);
		$orderItem = OrderItem::find($pk);
		$this->assertEquals(5, $orderItem->quantity);
		$this->assertEquals(30, $orderItem->subtotal);
	}
Qiang Xue committed
376

Qiang Xue committed
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
	public function testDelete()
	{
		// delete
		$customer = Customer::find(2);
		$this->assertTrue($customer instanceof Customer);
		$this->assertEquals('user2', $customer->name);
		$customer->delete();
		$customer = Customer::find(2);
		$this->assertNull($customer);

		// deleteAll
		$customers = Customer::find()->all();
		$this->assertEquals(2, count($customers));
		$ret = Customer::deleteAll();
		$this->assertEquals(2, $ret);
		$customers = Customer::find()->all();
		$this->assertEquals(0, count($customers));
	}
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444

	public function testStoreNull()
	{
		$record = new NullValues();
		$this->assertNull($record->var1);
		$this->assertNull($record->var2);
		$this->assertNull($record->var3);
		$this->assertNull($record->stringcol);

		$record->id = 1;

		$record->var1 = 123;
		$record->var2 = 456;
		$record->var3 = 789;
		$record->stringcol = 'hello!';

		$record->save(false);
		$this->assertTrue($record->refresh());

		$this->assertEquals(123, $record->var1);
		$this->assertEquals(456, $record->var2);
		$this->assertEquals(789, $record->var3);
		$this->assertEquals('hello!', $record->stringcol);

		$record->var1 = null;
		$record->var2 = null;
		$record->var3 = null;
		$record->stringcol = null;

		$record->save(false);
		$this->assertTrue($record->refresh());

		$this->assertNull($record->var1);
		$this->assertNull($record->var2);
		$this->assertNull($record->var3);
		$this->assertNull($record->stringcol);

		$record->var1 = 0;
		$record->var2 = 0;
		$record->var3 = 0;
		$record->stringcol = '';

		$record->save(false);
		$this->assertTrue($record->refresh());

		$this->assertEquals(0, $record->var1);
		$this->assertEquals(0, $record->var2);
		$this->assertEquals(0, $record->var3);
		$this->assertEquals('', $record->stringcol);
	}
445

446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
	public function testStoreEmpty()
	{
		$record = new NullValues();
		$record->id = 1;

		// this is to simulate empty html form submission
		$record->var1 = '';
		$record->var2 = '';
		$record->var3 = '';
		$record->stringcol = '';

		$record->save(false);
		$this->assertTrue($record->refresh());

		// https://github.com/yiisoft/yii2/commit/34945b0b69011bc7cab684c7f7095d837892a0d4#commitcomment-4458225
		$this->assertTrue($record->var1 === $record->var2);
		$this->assertTrue($record->var2 === $record->var3);
	}

465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
	/**
	 * Some PDO implementations(e.g. cubrid) do not support boolean values.
	 * Make sure this does not affect AR layer.
	 */
	public function testBooleanAttribute()
	{
		$customer = new Customer();
		$customer->name = 'boolean customer';
		$customer->email = 'mail@example.com';
		$customer->status = true;
		$customer->save(false);

		$customer->refresh();
		$this->assertEquals(1, $customer->status);

		$customer->status = false;
		$customer->save(false);

		$customer->refresh();
		$this->assertEquals(0, $customer->status);

		$customers = Customer::find()->where(['status' => true])->all();
		$this->assertEquals(2, count($customers));

		$customers = Customer::find()->where(['status' => false])->all();
		$this->assertEquals(1, count($customers));
	}
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508

	public function testIsPrimaryKey()
	{
		$this->assertFalse(Customer::isPrimaryKey([]));
		$this->assertTrue(Customer::isPrimaryKey(['id']));
		$this->assertFalse(Customer::isPrimaryKey(['id', 'name']));
		$this->assertFalse(Customer::isPrimaryKey(['name']));
		$this->assertFalse(Customer::isPrimaryKey(['name', 'email']));

		$this->assertFalse(OrderItem::isPrimaryKey([]));
		$this->assertFalse(OrderItem::isPrimaryKey(['order_id']));
		$this->assertFalse(OrderItem::isPrimaryKey(['item_id']));
		$this->assertFalse(OrderItem::isPrimaryKey(['quantity']));
		$this->assertFalse(OrderItem::isPrimaryKey(['quantity', 'subtotal']));
		$this->assertTrue(OrderItem::isPrimaryKey(['order_id', 'item_id']));
		$this->assertFalse(OrderItem::isPrimaryKey(['order_id', 'item_id', 'quantity']));
	}
Zander Baldwin committed
509
}