diff --git a/tests/ActiveQueryFindTest.php b/tests/ActiveQueryFindTest.php index 179817c66..d501e996c 100644 --- a/tests/ActiveQueryFindTest.php +++ b/tests/ActiveQueryFindTest.php @@ -101,7 +101,7 @@ public function testFindLazyViaTable(): void $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->findOne(2); - $this->assertCount(0, $orders->books); + $this->assertCount(0, $orders->getBooks()); $this->assertEquals(2, $orders->getAttribute('id')); $orders = $orderQuery->where(['id' => 1])->asArray()->one(); @@ -117,19 +117,19 @@ public function testFindEagerViaTable(): void $this->assertCount(3, $orders); $order = $orders[0]; - $this->assertCount(2, $order->books); + $this->assertCount(2, $order->getBooks()); $this->assertEquals(1, $order->getAttribute('id')); - $this->assertEquals(1, $order->books[0]->getAttribute('id')); - $this->assertEquals(2, $order->books[1]->getAttribute('id')); + $this->assertEquals(1, $order->getBooks()[0]->getAttribute('id')); + $this->assertEquals(2, $order->getBooks()[1]->getAttribute('id')); $order = $orders[1]; - $this->assertCount(0, $order->books); + $this->assertCount(0, $order->getBooks()); $this->assertEquals(2, $order->getAttribute('id')); $order = $orders[2]; - $this->assertCount(1, $order->books); + $this->assertCount(1, $order->getBooks()); $this->assertEquals(3, $order->getAttribute('id')); - $this->assertEquals(2, $order->books[0]->getAttribute('id')); + $this->assertEquals(2, $order->getBooks()[0]->getAttribute('id')); /** https://github.com/yiisoft/yii2/issues/1402 */ $orderQuery = new ActiveQuery(Order::class, $this->db); @@ -158,10 +158,10 @@ public function testFindCompositeRelationWithJoin(): void /** @var $orderItems OrderItem */ $orderItems = $orderItemQuery->findOne([1, 1]); - $orderItemNoJoin = $orderItems->orderItemCompositeNoJoin; + $orderItemNoJoin = $orderItems->getOrderItemCompositeNoJoin(); $this->assertInstanceOf(OrderItem::class, $orderItemNoJoin); - $orderItemWithJoin = $orderItems->orderItemCompositeWithJoin; + $orderItemWithJoin = $orderItems->getOrderItemCompositeWithJoin(); $this->assertInstanceOf(OrderItem::class, $orderItemWithJoin); } @@ -172,13 +172,13 @@ public function testFindSimpleRelationWithJoin(): void $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->findOne(1); - $customerNoJoin = $orders->customer; + $customerNoJoin = $orders->getCustomer(); $this->assertInstanceOf(Customer::class, $customerNoJoin); - $customerWithJoin = $orders->customerJoinedWithProfile; + $customerWithJoin = $orders->getCustomerJoinedWithProfile(); $this->assertInstanceOf(Customer::class, $customerWithJoin); - $customerWithJoinIndexOrdered = $orders->customerJoinedWithProfileIndexOrdered; + $customerWithJoinIndexOrdered = $orders->getCustomerJoinedWithProfileIndexOrdered(); $this->assertArrayHasKey('user1', $customerWithJoinIndexOrdered); $this->assertInstanceOf(Customer::class, $customerWithJoinIndexOrdered['user1']); $this->assertIsArray($customerWithJoinIndexOrdered); @@ -192,12 +192,12 @@ public function testFindOneByColumnName(): void $customerQuery = new CustomerQuery(Customer::class, $this->db); $arClass = $customer->findOne(['id' => 1]); - $this->assertEquals(1, $arClass->id); + $this->assertEquals(1, $arClass->getId()); $customerQuery->joinWithProfile = true; $arClass = $customer->findOne(['customer.id' => 1]); - $this->assertEquals(1, $arClass->id); + $this->assertEquals(1, $arClass->getId()); $customerQuery->joinWithProfile = false; } @@ -225,7 +225,7 @@ public function testFind(): void $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(2); $this->assertInstanceOf(Customer::class, $customer); - $this->assertEquals('user2', $customer->name); + $this->assertEquals('user2', $customer->getName()); $customer = $customerQuery->findOne(5); $this->assertNull($customer); @@ -241,7 +241,7 @@ public function testFind(): void $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(['id' => 2, 'name' => 'user2']); $this->assertInstanceOf(Customer::class, $customer); - $this->assertEquals('user2', $customer->name); + $this->assertEquals('user2', $customer->getName()); $customer = $customerQuery->findOne(['id' => 2, 'name' => 'user1']); $this->assertNull($customer); @@ -256,7 +256,7 @@ public function testFind(): void $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->where(['name' => 'user2'])->onePopulate(); $this->assertInstanceOf(Customer::class, $customer); - $this->assertEquals(2, $customer->id); + $this->assertEquals(2, $customer->getId()); /** scope */ $customerQuery = new CustomerQuery(Customer::class, $this->db); @@ -317,7 +317,10 @@ public function testFindIndexBy(): void /** indexBy callable */ $customer = new ActiveQuery(Customer::class, $this->db); - $customers = $customer->indexBy(fn (Customer $customer) => $customer->id . '-' . $customer->name)->orderBy('id')->all(); + $customers = $customer + ->indexBy(fn (Customer $customer) => $customer->getId() . '-' . $customer->getName()) + ->orderBy('id') + ->all(); $this->assertCount(3, $customers); $this->assertInstanceOf(Customer::class, $customers['1-user1']); @@ -394,7 +397,7 @@ public function testFindLimit(): void /** one */ $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->orderBy('id')->onePopulate(); - $this->assertEquals('user1', $customer->name); + $this->assertEquals('user1', $customer->getName()); /** all */ $customerQuery = new ActiveQuery(Customer::class, $this->db); @@ -405,20 +408,20 @@ public function testFindLimit(): void $customerQuery = new ActiveQuery(Customer::class, $this->db); $customers = $customerQuery->orderBy('id')->limit(1)->allPopulate(); $this->assertCount(1, $customers); - $this->assertEquals('user1', $customers[0]->name); + $this->assertEquals('user1', $customers[0]->getName()); $customers = $customerQuery->orderBy('id')->limit(1)->offset(1)->allPopulate(); $this->assertCount(1, $customers); - $this->assertEquals('user2', $customers[0]->name); + $this->assertEquals('user2', $customers[0]->getName()); $customers = $customerQuery->orderBy('id')->limit(1)->offset(2)->allPopulate(); $this->assertCount(1, $customers); - $this->assertEquals('user3', $customers[0]->name); + $this->assertEquals('user3', $customers[0]->getName()); $customers = $customerQuery->orderBy('id')->limit(2)->offset(1)->allPopulate(); $this->assertCount(2, $customers); - $this->assertEquals('user2', $customers[0]->name); - $this->assertEquals('user3', $customers[1]->name); + $this->assertEquals('user2', $customers[0]->getName()); + $this->assertEquals('user3', $customers[1]->getName()); $customers = $customerQuery->limit(2)->offset(3)->allPopulate(); $this->assertCount(0, $customers); @@ -426,13 +429,13 @@ public function testFindLimit(): void /** offset */ $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->orderBy('id')->offset(0)->onePopulate(); - $this->assertEquals('user1', $customer->name); + $this->assertEquals('user1', $customer->getName()); $customer = $customerQuery->orderBy('id')->offset(1)->onePopulate(); - $this->assertEquals('user2', $customer->name); + $this->assertEquals('user2', $customer->getName()); $customer = $customerQuery->orderBy('id')->offset(2)->onePopulate(); - $this->assertEquals('user3', $customer->name); + $this->assertEquals('user3', $customer->getName()); $customer = $customerQuery->offset(3)->onePopulate(); $this->assertNull($customer); @@ -482,12 +485,12 @@ public function testFindNullValues(): void $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(2); - $customer->name = null; + $customer->setName(null); $customer->save(); $result = $customerQuery->where(['name' => null])->all(); $this->assertCount(1, $result); - $this->assertEquals(2, reset($result)->primaryKey); + $this->assertEquals(2, reset($result)->getPrimaryKey()); } public function testFindEager(): void @@ -502,17 +505,17 @@ public function testFindEager(): void $this->assertTrue($customers[1]->isRelationPopulated('orders')); $this->assertTrue($customers[2]->isRelationPopulated('orders')); $this->assertTrue($customers[3]->isRelationPopulated('orders')); - $this->assertCount(1, $customers[1]->orders); - $this->assertCount(2, $customers[2]->orders); - $this->assertCount(0, $customers[3]->orders); + $this->assertCount(1, $customers[1]->getOrders()); + $this->assertCount(2, $customers[2]->getOrders()); + $this->assertCount(0, $customers[3]->getOrders()); - unset($customers[1]->orders); + $customers[1]->resetRelation('orders'); $this->assertFalse($customers[1]->isRelationPopulated('orders')); $customer = $customerQuery->where(['id' => 1])->with('orders')->onePopulate(); $this->assertTrue($customer->isRelationPopulated('orders')); - $this->assertCount(1, $customer->orders); - $this->assertCount(1, $customer->relatedRecords); + $this->assertCount(1, $customer->getOrders()); + $this->assertCount(1, $customer->getRelatedRecords()); /** multiple with() calls */ $orderQuery = new ActiveQuery(Order::class, $this->db); @@ -536,11 +539,11 @@ public function testFindEagerViaRelation(): void $this->assertCount(3, $orders); $order = $orders[0]; - $this->assertEquals(1, $order->id); + $this->assertEquals(1, $order->getId()); $this->assertTrue($order->isRelationPopulated('items')); - $this->assertCount(2, $order->items); - $this->assertEquals(1, $order->items[0]->id); - $this->assertEquals(2, $order->items[1]->id); + $this->assertCount(2, $order->getItems()); + $this->assertEquals(1, $order->getItems()[0]->getId()); + $this->assertEquals(2, $order->getItems()[1]->getId()); } public function testFindNestedRelation(): void @@ -555,23 +558,23 @@ public function testFindNestedRelation(): void $this->assertTrue($customers[1]->isRelationPopulated('orders')); $this->assertTrue($customers[2]->isRelationPopulated('orders')); $this->assertTrue($customers[3]->isRelationPopulated('orders')); - $this->assertCount(1, $customers[1]->orders); - $this->assertCount(2, $customers[2]->orders); - $this->assertCount(0, $customers[3]->orders); - $this->assertTrue($customers[1]->orders[0]->isRelationPopulated('items')); - $this->assertTrue($customers[2]->orders[0]->isRelationPopulated('items')); - $this->assertTrue($customers[2]->orders[1]->isRelationPopulated('items')); - $this->assertCount(2, $customers[1]->orders[0]->items); - $this->assertCount(3, $customers[2]->orders[0]->items); - $this->assertCount(1, $customers[2]->orders[1]->items); + $this->assertCount(1, $customers[1]->getOrders()); + $this->assertCount(2, $customers[2]->getOrders()); + $this->assertCount(0, $customers[3]->getOrders()); + $this->assertTrue($customers[1]->getOrders()[0]->isRelationPopulated('items')); + $this->assertTrue($customers[2]->getOrders()[0]->isRelationPopulated('items')); + $this->assertTrue($customers[2]->getOrders()[1]->isRelationPopulated('items')); + $this->assertCount(2, $customers[1]->getOrders()[0]->getItems()); + $this->assertCount(3, $customers[2]->getOrders()[0]->getItems()); + $this->assertCount(1, $customers[2]->getOrders()[1]->getItems()); $customers = $customerQuery->where(['id' => 1])->with('ordersWithItems')->onePopulate(); $this->assertTrue($customers->isRelationPopulated('ordersWithItems')); - $this->assertCount(1, $customers->ordersWithItems); + $this->assertCount(1, $customers->getOrdersWithItems()); - $order = $customers->ordersWithItems[0]; + $order = $customers->getOrdersWithItems()[0]; $this->assertTrue($order->isRelationPopulated('orderItems')); - $this->assertCount(2, $order->orderItems); + $this->assertCount(2, $order->getOrderItems()); } /** @@ -588,25 +591,25 @@ public function testFindEagerViaRelationPreserveOrder(): void $this->assertCount(3, $orders); $order = $orders[0]; - $this->assertEquals(1, $order->id); + $this->assertEquals(1, $order->getId()); $this->assertTrue($order->isRelationPopulated('itemsInOrder1')); - $this->assertCount(2, $order->itemsInOrder1); - $this->assertEquals(1, $order->itemsInOrder1[0]->id); - $this->assertEquals(2, $order->itemsInOrder1[1]->id); + $this->assertCount(2, $order->getItemsInOrder1()); + $this->assertEquals(1, $order->getItemsInOrder1()[0]->getId()); + $this->assertEquals(2, $order->getItemsInOrder1()[1]->getId()); $order = $orders[1]; - $this->assertEquals(2, $order->id); + $this->assertEquals(2, $order->getId()); $this->assertTrue($order->isRelationPopulated('itemsInOrder1')); - $this->assertCount(3, $order->itemsInOrder1); - $this->assertEquals(5, $order->itemsInOrder1[0]->id); - $this->assertEquals(3, $order->itemsInOrder1[1]->id); - $this->assertEquals(4, $order->itemsInOrder1[2]->id); + $this->assertCount(3, $order->getItemsInOrder1()); + $this->assertEquals(5, $order->getItemsInOrder1()[0]->getId()); + $this->assertEquals(3, $order->getItemsInOrder1()[1]->getId()); + $this->assertEquals(4, $order->getItemsInOrder1()[2]->getId()); $order = $orders[2]; - $this->assertEquals(3, $order->id); + $this->assertEquals(3, $order->getId()); $this->assertTrue($order->isRelationPopulated('itemsInOrder1')); - $this->assertCount(1, $order->itemsInOrder1); - $this->assertEquals(2, $order->itemsInOrder1[0]->id); + $this->assertCount(1, $order->getItemsInOrder1()); + $this->assertEquals(2, $order->getItemsInOrder1()[0]->getId()); } public function testFindEagerViaRelationPreserveOrderB(): void @@ -619,25 +622,25 @@ public function testFindEagerViaRelationPreserveOrderB(): void $this->assertCount(3, $orders); $order = $orders[0]; - $this->assertEquals(1, $order->id); + $this->assertEquals(1, $order->getId()); $this->assertTrue($order->isRelationPopulated('itemsInOrder2')); - $this->assertCount(2, $order->itemsInOrder2); - $this->assertEquals(1, $order->itemsInOrder2[0]->id); - $this->assertEquals(2, $order->itemsInOrder2[1]->id); + $this->assertCount(2, $order->getItemsInOrder2()); + $this->assertEquals(1, $order->getItemsInOrder2()[0]->getId()); + $this->assertEquals(2, $order->getItemsInOrder2()[1]->getId()); $order = $orders[1]; - $this->assertEquals(2, $order->id); + $this->assertEquals(2, $order->getId()); $this->assertTrue($order->isRelationPopulated('itemsInOrder2')); - $this->assertCount(3, $order->itemsInOrder2); - $this->assertEquals(5, $order->itemsInOrder2[0]->id); - $this->assertEquals(3, $order->itemsInOrder2[1]->id); - $this->assertEquals(4, $order->itemsInOrder2[2]->id); + $this->assertCount(3, $order->getItemsInOrder2()); + $this->assertEquals(5, $order->getItemsInOrder2()[0]->getId()); + $this->assertEquals(3, $order->getItemsInOrder2()[1]->getId()); + $this->assertEquals(4, $order->getItemsInOrder2()[2]->getId()); $order = $orders[2]; - $this->assertEquals(3, $order->id); + $this->assertEquals(3, $order->getId()); $this->assertTrue($order->isRelationPopulated('itemsInOrder2')); - $this->assertCount(1, $order->itemsInOrder2); - $this->assertEquals(2, $order->itemsInOrder2[0]->id); + $this->assertCount(1, $order->getItemsInOrder2()); + $this->assertEquals(2, $order->getItemsInOrder2()[0]->getId()); } public function testFindEmptyInCondition(): void @@ -666,7 +669,7 @@ public function testFindEagerIndexBy(): void $order = $orderQuery->with('itemsIndexed')->where(['id' => 1])->onePopulate(); $this->assertTrue($order->isRelationPopulated('itemsIndexed')); - $items = $order->itemsIndexed; + $items = $order->getItemsIndexed(); $this->assertCount(2, $items); $this->assertTrue(isset($items[1])); $this->assertTrue(isset($items[2])); @@ -674,7 +677,7 @@ public function testFindEagerIndexBy(): void $order = $orderQuery->with('itemsIndexed')->where(['id' => 2])->onePopulate(); $this->assertTrue($order->isRelationPopulated('itemsIndexed')); - $items = $order->itemsIndexed; + $items = $order->getItemsIndexed(); $this->assertCount(3, $items); $this->assertTrue(isset($items[3])); $this->assertTrue(isset($items[4])); @@ -689,12 +692,12 @@ public function testFindLazy(): void $customer = $customerQuery->findOne(2); $this->assertFalse($customer->isRelationPopulated('orders')); - $orders = $customer->orders; + $orders = $customer->getOrders(); $this->assertTrue($customer->isRelationPopulated('orders')); $this->assertCount(2, $orders); - $this->assertCount(1, $customer->relatedRecords); + $this->assertCount(1, $customer->getRelatedRecords()); - unset($customer['orders']); + $customer->resetRelation('orders'); $this->assertFalse($customer->isRelationPopulated('orders')); $customer = $customerQuery->findOne(2); @@ -702,9 +705,9 @@ public function testFindLazy(): void $orders = $customer->getOrdersQuery()->where(['id' => 3])->all(); $this->assertFalse($customer->isRelationPopulated('orders')); - $this->assertCount(0, $customer->relatedRecords); + $this->assertCount(0, $customer->getRelatedRecords()); $this->assertCount(1, $orders); - $this->assertEquals(3, $orders[0]->id); + $this->assertEquals(3, $orders[0]->getId()); } public function testFindLazyVia(): void @@ -714,9 +717,9 @@ public function testFindLazyVia(): void $orderQuery = new ActiveQuery(Order::class, $this->db); $order = $orderQuery->findOne(1); - $this->assertEquals(1, $order->id); - $this->assertCount(2, $order->items); - $this->assertEquals(1, $order->items[0]->id); - $this->assertEquals(2, $order->items[1]->id); + $this->assertEquals(1, $order->getId()); + $this->assertCount(2, $order->getItems()); + $this->assertEquals(1, $order->getItems()[0]->getId()); + $this->assertEquals(2, $order->getItems()[1]->getId()); } } diff --git a/tests/ActiveQueryTest.php b/tests/ActiveQueryTest.php index 73469fd46..46f0d828d 100644 --- a/tests/ActiveQueryTest.php +++ b/tests/ActiveQueryTest.php @@ -326,22 +326,22 @@ public function testDeeplyNestedTableRelationWith(): void $category = $categories[1]; $this->assertNotNull($category); - $orders = $category->orders; + $orders = $category->getOrders(); $this->assertCount(2, $orders); $this->assertInstanceOf(Order::class, $orders[0]); $this->assertInstanceOf(Order::class, $orders[1]); - $ids = [$orders[0]->id, $orders[1]->id]; + $ids = [$orders[0]->getId(), $orders[1]->getId()]; sort($ids); $this->assertEquals([1, 3], $ids); $category = $categories[2]; $this->assertNotNull($category); - $orders = $category->orders; + $orders = $category->getOrders(); $this->assertCount(1, $orders); $this->assertInstanceOf(Order::class, $orders[0]); - $this->assertEquals(2, $orders[0]->id); + $this->assertEquals(2, $orders[0]->getId()); } public function testGetSql(): void @@ -417,7 +417,7 @@ public function testDeeplyNestedTableRelation(): void $customers = $customerQuery->findOne(1); $this->assertNotNull($customerQuery); - $items = $customers->orderItems; + $items = $customers->getOrderItems(); $this->assertCount(2, $items); $this->assertEquals(1, $items[0]->getAttribute('id')); @@ -441,19 +441,19 @@ public function testDeeplyNestedTableRelation2(): void $categories = $categoryQuery->where(['id' => 1])->onePopulate(); $this->assertNotNull($categories); - $orders = $categories->orders; + $orders = $categories->getOrders(); $this->assertCount(2, $orders); $this->assertInstanceOf(Order::class, $orders[0]); $this->assertInstanceOf(Order::class, $orders[1]); - $ids = [$orders[0]->id, $orders[1]->getAttribute('id')]; + $ids = [$orders[0]->getId(), $orders[1]->getAttribute('id')]; sort($ids); $this->assertEquals([1, 3], $ids); $categories = $categoryQuery->where(['id' => 2])->onePopulate(); $this->assertNotNull($categories); - $orders = $categories->orders; + $orders = $categories->getOrders(); $this->assertCount(1, $orders); $this->assertEquals(2, $orders[0]->getAttribute('id')); $this->assertInstanceOf(Order::class, $orders[0]); @@ -467,9 +467,9 @@ public function testJoinWith(): void $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->joinWith('customer')->orderBy('customer.id DESC, order.id')->all(); $this->assertCount(3, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); - $this->assertEquals(1, $orders[2]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); + $this->assertEquals(1, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); $this->assertTrue($orders[1]->isRelationPopulated('customer')); $this->assertTrue($orders[2]->isRelationPopulated('customer')); @@ -484,8 +484,8 @@ public function testJoinWith(): void ] )->orderBy('order.id')->all(); $this->assertCount(2, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); $this->assertTrue($orders[1]->isRelationPopulated('customer')); @@ -499,7 +499,7 @@ public function testJoinWith(): void ] )->where(['order.id' => [1, 2]])->orderBy('order.id')->all(); $this->assertCount(1, $orders); - $this->assertEquals(2, $orders[0]->id); + $this->assertEquals(2, $orders[0]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); /** inner join filtering without eager loading */ @@ -513,8 +513,8 @@ public function testJoinWith(): void false )->orderBy('order.id')->all(); $this->assertCount(2, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); $this->assertFalse($orders[0]->isRelationPopulated('customer')); $this->assertFalse($orders[1]->isRelationPopulated('customer')); @@ -529,17 +529,17 @@ public function testJoinWith(): void false )->where(['order.id' => [1, 2]])->orderBy('order.id')->all(); $this->assertCount(1, $orders); - $this->assertEquals(2, $orders[0]->id); + $this->assertEquals(2, $orders[0]->getId()); $this->assertFalse($orders[0]->isRelationPopulated('customer')); /** join with via-relation */ $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->innerJoinWith('books')->orderBy('order.id')->all(); $this->assertCount(2, $orders); - $this->assertCount(2, $orders[0]->books); - $this->assertCount(1, $orders[1]->books); - $this->assertEquals(1, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); + $this->assertCount(2, $orders[0]->getBooks()); + $this->assertCount(1, $orders[1]->getBooks()); + $this->assertEquals(1, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('books')); $this->assertTrue($orders[1]->isRelationPopulated('books')); @@ -556,11 +556,11 @@ public function testJoinWith(): void ] )->orderBy('order.id')->all(); $this->assertCount(1, $orders); - $this->assertCount(3, $orders[0]->items); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(2, $orders[0]->items[0]->category->id); + $this->assertCount(3, $orders[0]->getItems()); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(2, $orders[0]->getItems()[0]->getCategory()->getId()); $this->assertTrue($orders[0]->isRelationPopulated('items')); - $this->assertTrue($orders[0]->items[0]->isRelationPopulated('category')); + $this->assertTrue($orders[0]->getItems()[0]->isRelationPopulated('category')); /** join with table alias */ $orderQuery = new ActiveQuery(Order::class, $this->db); @@ -572,9 +572,9 @@ public function testJoinWith(): void ] )->orderBy('c.id DESC, order.id')->all(); $this->assertCount(3, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); - $this->assertEquals(1, $orders[2]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); + $this->assertEquals(1, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); $this->assertTrue($orders[1]->isRelationPopulated('customer')); $this->assertTrue($orders[2]->isRelationPopulated('customer')); @@ -583,9 +583,9 @@ public function testJoinWith(): void $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->joinWith('customer as c')->orderBy('c.id DESC, order.id')->all(); $this->assertCount(3, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); - $this->assertEquals(1, $orders[2]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); + $this->assertEquals(1, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); $this->assertTrue($orders[1]->isRelationPopulated('customer')); $this->assertTrue($orders[2]->isRelationPopulated('customer')); @@ -603,22 +603,22 @@ public function testJoinWith(): void ] )->orderBy('order.id')->all(); $this->assertCount(1, $orders); - $this->assertCount(3, $orders[0]->items); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(2, $orders[0]->items[0]->category->id); + $this->assertCount(3, $orders[0]->getItems()); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(2, $orders[0]->getItems()[0]->getCategory()->getId()); $this->assertTrue($orders[0]->isRelationPopulated('items')); - $this->assertTrue($orders[0]->items[0]->isRelationPopulated('category')); + $this->assertTrue($orders[0]->getItems()[0]->isRelationPopulated('category')); /** join with ON condition */ $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->joinWith('books2')->orderBy('order.id')->all(); $this->assertCount(3, $orders); - $this->assertCount(2, $orders[0]->books2); - $this->assertCount(0, $orders[1]->books2); - $this->assertCount(1, $orders[2]->books2); - $this->assertEquals(1, $orders[0]->id); - $this->assertEquals(2, $orders[1]->id); - $this->assertEquals(3, $orders[2]->id); + $this->assertCount(2, $orders[0]->getBooks2()); + $this->assertCount(0, $orders[1]->getBooks2()); + $this->assertCount(1, $orders[2]->getBooks2()); + $this->assertEquals(1, $orders[0]->getId()); + $this->assertEquals(2, $orders[1]->getId()); + $this->assertEquals(3, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('books2')); $this->assertTrue($orders[1]->isRelationPopulated('books2')); $this->assertTrue($orders[2]->isRelationPopulated('books2')); @@ -626,26 +626,26 @@ public function testJoinWith(): void /** lazy loading with ON condition */ $orderQuery = new ActiveQuery(Order::class, $this->db); $order = $orderQuery->findOne(1); - $this->assertCount(2, $order->books2); + $this->assertCount(2, $order->getBooks2()); $orderQuery = new ActiveQuery(Order::class, $this->db); $order = $orderQuery->findOne(2); - $this->assertCount(0, $order->books2); + $this->assertCount(0, $order->getBooks2()); $order = new ActiveQuery(Order::class, $this->db); $order = $order->findOne(3); - $this->assertCount(1, $order->books2); + $this->assertCount(1, $order->getBooks2()); /** eager loading with ON condition */ $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->with('books2')->all(); $this->assertCount(3, $orders); - $this->assertCount(2, $orders[0]->books2); - $this->assertCount(0, $orders[1]->books2); - $this->assertCount(1, $orders[2]->books2); - $this->assertEquals(1, $orders[0]->id); - $this->assertEquals(2, $orders[1]->id); - $this->assertEquals(3, $orders[2]->id); + $this->assertCount(2, $orders[0]->getBooks2()); + $this->assertCount(0, $orders[1]->getBooks2()); + $this->assertCount(1, $orders[2]->getBooks2()); + $this->assertEquals(1, $orders[0]->getId()); + $this->assertEquals(2, $orders[1]->getId()); + $this->assertEquals(3, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('books2')); $this->assertTrue($orders[1]->isRelationPopulated('books2')); $this->assertTrue($orders[2]->isRelationPopulated('books2')); @@ -669,7 +669,7 @@ public function testJoinWith(): void }, ] )->onePopulate(); - $this->assertEquals(1, $customer->id); + $this->assertEquals(1, $customer->getId()); $orderQuery = new ActiveQuery(Order::class, $this->db); $order = $orderQuery->joinWith( @@ -695,11 +695,11 @@ public function testJoinWith(): void ] )->orderBy('order.id')->all(); $this->assertCount(1, $orders); - $this->assertCount(3, $orders[0]->items); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(2, $orders[0]->items[0]->category->id); + $this->assertCount(3, $orders[0]->getItems()); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(2, $orders[0]->getItems()[0]->getCategory()->getId()); $this->assertTrue($orders[0]->isRelationPopulated('items')); - $this->assertTrue($orders[0]->items[0]->isRelationPopulated('category')); + $this->assertTrue($orders[0]->getItems()[0]->isRelationPopulated('category')); } /** @@ -713,17 +713,17 @@ public function testJoinWithAndScope(): void $customer = new CustomerQuery(Customer::class, $this->db); $customers = $customer->active()->innerJoinWith('profile')->orderBy('customer.id')->all(); $this->assertCount(1, $customers); - $this->assertEquals(1, $customers[0]->id); + $this->assertEquals(1, $customers[0]->getId()); $this->assertTrue($customers[0]->isRelationPopulated('profile')); /** hasOne outer join */ $customer = new CustomerQuery(Customer::class, $this->db); $customers = $customer->active()->joinWith('profile')->orderBy('customer.id')->all(); $this->assertCount(2, $customers); - $this->assertEquals(1, $customers[0]->id); - $this->assertEquals(2, $customers[1]->id); - $this->assertInstanceOf(Profile::class, $customers[0]->profile); - $this->assertNull($customers[1]->profile); + $this->assertEquals(1, $customers[0]->getId()); + $this->assertEquals(2, $customers[1]->getId()); + $this->assertInstanceOf(Profile::class, $customers[0]->getProfile()); + $this->assertNull($customers[1]->getProfile()); $this->assertTrue($customers[0]->isRelationPopulated('profile')); $this->assertTrue($customers[1]->isRelationPopulated('profile')); @@ -737,8 +737,8 @@ public function testJoinWithAndScope(): void ] )->orderBy('customer.id DESC, order.id')->all(); $this->assertCount(2, $customers); - $this->assertEquals(2, $customers[0]->id); - $this->assertEquals(1, $customers[1]->id); + $this->assertEquals(2, $customers[0]->getId()); + $this->assertEquals(1, $customers[1]->getId()); $this->assertTrue($customers[0]->isRelationPopulated('orders')); $this->assertTrue($customers[1]->isRelationPopulated('orders')); } @@ -806,9 +806,9 @@ public function testJoinWithAlias(string $aliasMethod): void } $this->assertCount(3, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); - $this->assertEquals(1, $orders[2]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); + $this->assertEquals(1, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); $this->assertTrue($orders[1]->isRelationPopulated('customer')); $this->assertTrue($orders[2]->isRelationPopulated('customer')); @@ -828,8 +828,8 @@ public function testJoinWithAlias(string $aliasMethod): void } $this->assertCount(2, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); $this->assertTrue($orders[1]->isRelationPopulated('customer')); @@ -848,8 +848,8 @@ public function testJoinWithAlias(string $aliasMethod): void } $this->assertCount(2, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); $this->assertFalse($orders[0]->isRelationPopulated('customer')); $this->assertFalse($orders[1]->isRelationPopulated('customer')); @@ -872,10 +872,10 @@ public function testJoinWithAlias(string $aliasMethod): void } $this->assertCount(2, $orders); - $this->assertCount(2, $orders[0]->books); - $this->assertCount(1, $orders[1]->books); - $this->assertEquals(1, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); + $this->assertCount(2, $orders[0]->getBooks()); + $this->assertCount(1, $orders[1]->getBooks()); + $this->assertEquals(1, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('books')); $this->assertTrue($orders[1]->isRelationPopulated('books')); @@ -915,11 +915,11 @@ public function testJoinWithAlias(string $aliasMethod): void } $this->assertCount(1, $orders); - $this->assertCount(3, $orders[0]->items); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(2, $orders[0]->items[0]->category->id); + $this->assertCount(3, $orders[0]->getItems()); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(2, $orders[0]->getItems()[0]->getCategory()->getId()); $this->assertTrue($orders[0]->isRelationPopulated('items')); - $this->assertTrue($orders[0]->items[0]->isRelationPopulated('category')); + $this->assertTrue($orders[0]->getItems()[0]->isRelationPopulated('category')); /** join with ON condition */ if ($aliasMethod === 'explicit' || $aliasMethod === 'querysyntax') { @@ -929,12 +929,12 @@ public function testJoinWithAlias(string $aliasMethod): void $orders = $orderQuery->joinWith(["$relationName b"])->orderBy('order.id')->all(); $this->assertCount(3, $orders); - $this->assertCount(2, $orders[0]->$relationName); - $this->assertCount(0, $orders[1]->$relationName); - $this->assertCount(1, $orders[2]->$relationName); - $this->assertEquals(1, $orders[0]->id); - $this->assertEquals(2, $orders[1]->id); - $this->assertEquals(3, $orders[2]->id); + $this->assertCount(2, $orders[0]->relation($relationName)); + $this->assertCount(0, $orders[1]->relation($relationName)); + $this->assertCount(1, $orders[2]->relation($relationName)); + $this->assertEquals(1, $orders[0]->getId()); + $this->assertEquals(2, $orders[1]->getId()); + $this->assertEquals(3, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated($relationName)); $this->assertTrue($orders[1]->isRelationPopulated($relationName)); $this->assertTrue($orders[2]->isRelationPopulated($relationName)); @@ -948,12 +948,12 @@ public function testJoinWithAlias(string $aliasMethod): void $orders = $orderQuery->joinWith([(string)$relationName])->orderBy('order.id')->all(); $this->assertCount(3, $orders); - $this->assertCount(2, $orders[0]->$relationName); - $this->assertCount(0, $orders[1]->$relationName); - $this->assertCount(1, $orders[2]->$relationName); - $this->assertEquals(1, $orders[0]->id); - $this->assertEquals(2, $orders[1]->id); - $this->assertEquals(3, $orders[2]->id); + $this->assertCount(2, $orders[0]->relation($relationName)); + $this->assertCount(0, $orders[1]->relation($relationName)); + $this->assertCount(1, $orders[2]->relation($relationName)); + $this->assertEquals(1, $orders[0]->getId()); + $this->assertEquals(2, $orders[1]->getId()); + $this->assertEquals(3, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated($relationName)); $this->assertTrue($orders[1]->isRelationPopulated($relationName)); $this->assertTrue($orders[2]->isRelationPopulated($relationName)); @@ -990,7 +990,7 @@ public function testJoinWithAlias(string $aliasMethod): void $customer = $customerQuery->where([$query->applyAlias('order', 'id') => 1])->onePopulate(); } - $this->assertEquals(1, $customer->id); + $this->assertEquals(1, $customer->getId()); $this->assertNotNull($customer); /** join with sub-relation called inside Closure */ @@ -1014,11 +1014,11 @@ public function testJoinWithAlias(string $aliasMethod): void )->orderBy('order.id')->all(); $this->assertCount(1, $orders); - $this->assertCount(3, $orders[0]->items); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(2, $orders[0]->items[0]->category->id); + $this->assertCount(3, $orders[0]->getItems()); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(2, $orders[0]->getItems()[0]->getCategory()->getId()); $this->assertTrue($orders[0]->isRelationPopulated('items')); - $this->assertTrue($orders[0]->items[0]->isRelationPopulated('category')); + $this->assertTrue($orders[0]->getItems()[0]->isRelationPopulated('category')); } /** @@ -1040,7 +1040,7 @@ public function testJoinWithSameTable(): void $orders, $query->createCommand()->getRawSql() . print_r($orders, true) ); - $this->assertEquals(2, $orders[0]->id); + $this->assertEquals(2, $orders[0]->getId()); $this->assertFalse($orders[0]->isRelationPopulated('bookItems')); $this->assertFalse($orders[0]->isRelationPopulated('movieItems')); @@ -1053,9 +1053,9 @@ public function testJoinWithSameTable(): void $orders, $query->createCommand()->getRawSql() . print_r($orders, true) ); - $this->assertCount(0, $orders[0]->bookItems); - $this->assertCount(3, $orders[0]->movieItems); - $this->assertEquals(2, $orders[0]->id); + $this->assertCount(0, $orders[0]->getBookItems()); + $this->assertCount(3, $orders[0]->getMovieItems()); + $this->assertEquals(2, $orders[0]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('bookItems')); $this->assertTrue($orders[0]->isRelationPopulated('movieItems')); @@ -1086,7 +1086,7 @@ public function testJoinWithSameTable(): void $orders, $query->createCommand()->getRawSql() . print_r($orders, true) ); - $this->assertEquals(2, $orders[0]->id); + $this->assertEquals(2, $orders[0]->getId()); $this->assertFalse($orders[0]->isRelationPopulated('itemsIndexed')); /** with eager loading, only for one relation as it would be overwritten otherwise. */ @@ -1110,8 +1110,8 @@ public function testJoinWithSameTable(): void )->where(['movies.name' => 'Toy Story']); $orders = $query->all(); $this->assertCount(1, $orders, $query->createCommand()->getRawSql() . print_r($orders, true)); - $this->assertCount(3, $orders[0]->itemsIndexed); - $this->assertEquals(2, $orders[0]->id); + $this->assertCount(3, $orders[0]->getItemsIndexed()); + $this->assertEquals(2, $orders[0]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('itemsIndexed')); /** with eager loading, and the other relation */ @@ -1136,8 +1136,8 @@ public function testJoinWithSameTable(): void ->where(['movies.name' => 'Toy Story']); $orders = $query->all(); $this->assertCount(1, $orders, $query->createCommand()->getRawSql() . print_r($orders, true)); - $this->assertCount(0, $orders[0]->itemsIndexed); - $this->assertEquals(2, $orders[0]->id); + $this->assertCount(0, $orders[0]->getItemsIndexed()); + $this->assertEquals(2, $orders[0]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('itemsIndexed')); } @@ -1158,9 +1158,9 @@ public function testJoinWithDuplicateSimple(): void ->all(); $this->assertCount(3, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); - $this->assertEquals(1, $orders[2]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); + $this->assertEquals(1, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); $this->assertTrue($orders[1]->isRelationPopulated('customer')); $this->assertTrue($orders[2]->isRelationPopulated('customer')); @@ -1185,8 +1185,8 @@ public function testJoinWithDuplicateCallbackFiltering(): void ])->orderBy('order.id')->all(); $this->assertCount(2, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); $this->assertTrue($orders[1]->isRelationPopulated('customer')); } @@ -1210,7 +1210,7 @@ public function testJoinWithDuplicateCallbackFilteringConditionsOnPrimary(): voi ])->where(['order.id' => [1, 2]])->orderBy('order.id')->all(); $this->assertCount(1, $orders); - $this->assertEquals(2, $orders[0]->id); + $this->assertEquals(2, $orders[0]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); } @@ -1234,10 +1234,10 @@ public function testJoinWithDuplicateWithSubRelation(): void $this->assertCount(1, $orders); $this->assertTrue($orders[0]->isRelationPopulated('items')); - $this->assertEquals(2, $orders[0]->id); - $this->assertCount(3, $orders[0]->items); - $this->assertTrue($orders[0]->items[0]->isRelationPopulated('category')); - $this->assertEquals(2, $orders[0]->items[0]->category->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertCount(3, $orders[0]->getItems()); + $this->assertTrue($orders[0]->getItems()[0]->isRelationPopulated('category')); + $this->assertEquals(2, $orders[0]->getItems()[0]->getCategory()->getId()); } /** @@ -1259,9 +1259,9 @@ public function testJoinWithDuplicateTableAlias1(): void ])->orderBy('c.id DESC, order.id')->all(); $this->assertCount(3, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); - $this->assertEquals(1, $orders[2]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); + $this->assertEquals(1, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); $this->assertTrue($orders[1]->isRelationPopulated('customer')); $this->assertTrue($orders[2]->isRelationPopulated('customer')); @@ -1284,9 +1284,9 @@ public function testJoinWithDuplicateTableAlias2(): void ->all(); $this->assertCount(3, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); - $this->assertEquals(1, $orders[2]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); + $this->assertEquals(1, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); $this->assertTrue($orders[1]->isRelationPopulated('customer')); $this->assertTrue($orders[2]->isRelationPopulated('customer')); @@ -1316,10 +1316,10 @@ public function testJoinWithDuplicateTableAliasSubRelation(): void $this->assertCount(1, $orders); $this->assertTrue($orders[0]->isRelationPopulated('items')); - $this->assertEquals(2, $orders[0]->id); - $this->assertCount(3, $orders[0]->items); - $this->assertTrue($orders[0]->items[0]->isRelationPopulated('category')); - $this->assertEquals(2, $orders[0]->items[0]->category->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertCount(3, $orders[0]->getItems()); + $this->assertTrue($orders[0]->getItems()[0]->isRelationPopulated('category')); + $this->assertEquals(2, $orders[0]->getItems()[0]->getCategory()->getId()); } /** @@ -1349,10 +1349,10 @@ public function testJoinWithDuplicateSubRelationCalledInsideClosure(): void $this->assertCount(1, $orders); $this->assertTrue($orders[0]->isRelationPopulated('items')); - $this->assertEquals(2, $orders[0]->id); - $this->assertCount(3, $orders[0]->items); - $this->assertTrue($orders[0]->items[0]->isRelationPopulated('category')); - $this->assertEquals(2, $orders[0]->items[0]->category->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertCount(3, $orders[0]->getItems()); + $this->assertTrue($orders[0]->getItems()[0]->isRelationPopulated('category')); + $this->assertEquals(2, $orders[0]->getItems()[0]->getCategory()->getId()); } public function testAlias(): void @@ -1381,28 +1381,28 @@ public function testInverseOf(): void /** eager loading: find one and all */ $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->with('orders2')->where(['id' => 1])->onePopulate(); - $this->assertSame($customer->orders2[0]->customer2, $customer); + $this->assertSame($customer->getOrders2()[0]->getCustomer2(), $customer); //$customerQuery = new ActiveQuery(Customer::class, $this->db); $customers = $customerQuery->with('orders2')->where(['id' => [1, 3]])->all(); - $this->assertEmpty($customers[1]->orders2); - $this->assertSame($customers[0]->orders2[0]->customer2, $customers[0]); + $this->assertEmpty($customers[1]->getOrders2()); + $this->assertSame($customers[0]->getOrders2()[0]->getCustomer2(), $customers[0]); /** lazy loading */ $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(2); - $orders = $customer->orders2; + $orders = $customer->getOrders2(); $this->assertCount(2, $orders); - $this->assertSame($customer->orders2[0]->customer2, $customer); - $this->assertSame($customer->orders2[1]->customer2, $customer); + $this->assertSame($customer->getOrders2()[0]->getCustomer2(), $customer); + $this->assertSame($customer->getOrders2()[1]->getCustomer2(), $customer); /** ad-hoc lazy loading */ $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(2); $orders = $customer->getOrders2Query()->all(); $this->assertCount(2, $orders); - $this->assertSame($orders[0]->customer2, $customer); - $this->assertSame($orders[1]->customer2, $customer); + $this->assertSame($orders[0]->getCustomer2(), $customer); + $this->assertSame($orders[1]->getCustomer2(), $customer); $this->assertTrue( $orders[0]->isRelationPopulated('customer2'), 'inverse relation did not populate the relation' @@ -1424,11 +1424,11 @@ public function testInverseOf(): void $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->with('customer2')->where(['id' => 1])->all(); - $this->assertSame($orders[0]->customer2->orders2, [$orders[0]]); + $this->assertSame($orders[0]->getCustomer2()->getOrders2(), [$orders[0]]); $orderQuery = new ActiveQuery(Order::class, $this->db); $order = $orderQuery->with('customer2')->where(['id' => 1])->onePopulate(); - $this->assertSame($order->customer2->orders2, [$order]); + $this->assertSame($order->getCustomer2()->getOrders2(), [$order]); $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->with('customer2')->where(['id' => 1])->asArray()->all(); @@ -1440,13 +1440,13 @@ public function testInverseOf(): void $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->with('customer2')->where(['id' => [1, 3]])->all(); - $this->assertSame($orders[0]->customer2->orders2, [$orders[0]]); - $this->assertSame($orders[1]->customer2->orders2, [$orders[1]]); + $this->assertSame($orders[0]->getCustomer2()->getOrders2(), [$orders[0]]); + $this->assertSame($orders[1]->getCustomer2()->getOrders2(), [$orders[1]]); $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->with('customer2')->where(['id' => [2, 3]])->orderBy('id')->all(); - $this->assertSame($orders[0]->customer2->orders2, $orders); - $this->assertSame($orders[1]->customer2->orders2, $orders); + $this->assertSame($orders[0]->getCustomer2()->getOrders2(), $orders); + $this->assertSame($orders[1]->getCustomer2()->getOrders2(), $orders); $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->with('customer2')->where(['id' => [2, 3]])->orderBy('id')->asArray()->all(); @@ -1463,7 +1463,7 @@ public function testUnlinkAllViaTable(): void /** via table with delete. */ $orderQuery = new ActiveQuery(Order::class, $this->db); $order = $orderQuery->findOne(1); - $this->assertCount(2, $order->booksViaTable); + $this->assertCount(2, $order->getBooksViaTable()); $orderItemQuery = new ActiveQuery(OrderItem::class, $this->db); $orderItemCount = $orderItemQuery->count(); @@ -1474,17 +1474,17 @@ public function testUnlinkAllViaTable(): void $order->unlinkAll('booksViaTable', true); $this->assertEquals(5, $itemQuery->count()); $this->assertEquals($orderItemCount - 2, $orderItemQuery->count()); - $this->assertCount(0, $order->booksViaTable); + $this->assertCount(0, $order->getBooksViaTable()); /** via table without delete */ - $this->assertCount(2, $order->booksWithNullFKViaTable); + $this->assertCount(2, $order->getBooksWithNullFKViaTable()); $orderItemsWithNullFKQuery = new ActiveQuery(OrderItemWithNullFK::class, $this->db); $orderItemCount = $orderItemsWithNullFKQuery->count(); $this->assertEquals(5, $itemQuery->count()); $order->unlinkAll('booksWithNullFKViaTable', false); - $this->assertCount(0, $order->booksWithNullFKViaTable); + $this->assertCount(0, $order->getBooksWithNullFKViaTable()); $this->assertEquals(2, $orderItemsWithNullFKQuery->where( ['AND', ['item_id' => [1, 2]], ['order_id' => null]] )->count()); @@ -1510,9 +1510,9 @@ public function testIssues(): void $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->with('orderItems')->orderBy('id')->all(); $this->assertCount(3, $orders); - $this->assertCount(2, $orders[0]->orderItems); - $this->assertCount(3, $orders[1]->orderItems); - $this->assertCount(1, $orders[2]->orderItems); + $this->assertCount(2, $orders[0]->getOrderItems()); + $this->assertCount(3, $orders[1]->getOrderItems()); + $this->assertCount(1, $orders[2]->getOrderItems()); $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->with( @@ -1523,19 +1523,19 @@ public function testIssues(): void ] )->orderBy('id')->all(); $this->assertCount(3, $orders); - $this->assertCount(2, $orders[0]->orderItems); - $this->assertCount(3, $orders[1]->orderItems); - $this->assertCount(1, $orders[2]->orderItems); + $this->assertCount(2, $orders[0]->getOrderItems()); + $this->assertCount(3, $orders[1]->getOrderItems()); + $this->assertCount(1, $orders[2]->getOrderItems()); /** {@see https://github.com/yiisoft/yii2/issues/8149} */ $arClass = new Customer($this->db); - $arClass->name = 'test'; - $arClass->email = 'test'; + $arClass->setName('test'); + $arClass->setEmail('test'); $arClass->save(); $arClass->updateCounters(['status' => 1]); - $this->assertEquals(1, $arClass->status); + $this->assertEquals(1, $arClass->getStatus()); } public function testPopulateWithoutPk(): void @@ -1602,9 +1602,9 @@ public function testPopulateWithoutPk(): void $this->assertContainsOnlyInstancesOf(Customer::class, $aggregation); foreach ($aggregation as $item) { - if ($item->status === 1) { + if ($item->getStatus() === 1) { $this->assertEquals(183, $item->sumTotal); - } elseif ($item->status === 2) { + } elseif ($item->getStatus() === 2) { $this->assertEquals(0, $item->sumTotal); } } @@ -1648,12 +1648,12 @@ public function testPopulateWithoutPk(): void $this->assertContainsOnlyInstancesOf(OrderItem::class, $aggregation); foreach ($aggregation as $item) { - if ($item->order_id === 1) { - $this->assertEquals(70, $item->subtotal); - } elseif ($item->order_id === 2) { - $this->assertEquals(33, $item->subtotal); - } elseif ($item->order_id === 3) { - $this->assertEquals(40, $item->subtotal); + if ($item->getOrderId() === 1) { + $this->assertEquals(70, $item->getSubtotal()); + } elseif ($item->getOrderId() === 2) { + $this->assertEquals(33, $item->getSubtotal()); + } elseif ($item->getOrderId() === 3) { + $this->assertEquals(40, $item->getSubtotal()); } } } @@ -1667,13 +1667,13 @@ public function testLinkWhenRelationIsIndexed2(): void $orderItem = new OrderItem($this->db); - $orderItem->order_id = $order->id; - $orderItem->item_id = 3; - $orderItem->quantity = 1; - $orderItem->subtotal = 10.0; + $orderItem->setOrderId($order->getId()); + $orderItem->setItemId(3); + $orderItem->setQuantity(1); + $orderItem->setSubtotal(10.0); $order->link('orderItems2', $orderItem); - $this->assertTrue(isset($order->orderItems2['3'])); + $this->assertTrue(isset($order->getOrderItems2()['3'])); } public function testEmulateExecution(): void @@ -1714,7 +1714,7 @@ public function testUnlinkAllOnCondition(): void * Ensure that limitedItems relation returns only one item (category_id = 2 and id in (1,2,3)) */ $category = $categoryQuery->onePopulate(); - $this->assertCount(1, $category->limitedItems); + $this->assertCount(1, $category->getLimitedItems()); /** Unlink all items in the limitedItems relation */ $category->unlinkAll('limitedItems', true); @@ -1724,7 +1724,7 @@ public function testUnlinkAllOnCondition(): void $this->assertEquals(2, $itemsCount); /** Call $categoryQuery again to ensure no items were found */ - $this->assertCount(0, $categoryQuery->onePopulate()->limitedItems); + $this->assertCount(0, $categoryQuery->onePopulate()->getLimitedItems()); } /** @@ -1746,13 +1746,13 @@ public function testUnlinkAllOnConditionViaTable(): void * Ensure that limitedItems relation returns only one item (category_id = 2 and id in (4, 5)). */ $category = $orderQuery->onePopulate(); - $this->assertCount(2, $category->limitedItems); + $this->assertCount(2, $category->getLimitedItems()); /** Unlink all items in the limitedItems relation */ $category->unlinkAll('limitedItems', true); /** Call $orderQuery again to ensure that links are removed */ - $this->assertCount(0, $orderQuery->onePopulate()->limitedItems); + $this->assertCount(0, $orderQuery->onePopulate()->getLimitedItems()); /** Make sure that only links were removed, the items were not removed */ $this->assertEquals(3, $itemQuery->where(['category_id' => 2])->count()); @@ -1768,15 +1768,15 @@ public function testIndexByAfterLoadingRelations(): void $orderQuery = new ActiveQuery(Order::class, $this->db); $orderQuery->with('customer')->indexBy(function (Order $order) { $this->assertTrue($order->isRelationPopulated('customer')); - $this->assertNotEmpty($order->customer->id); + $this->assertNotEmpty($order->getCustomer()?->getId()); - return $order->customer->id; + return $order->getCustomer()?->getId(); })->all(); $orders = $orderQuery->with('customer')->indexBy('customer.id')->all(); foreach ($orders as $customer_id => $order) { - $this->assertEquals($customer_id, $order->customer_id); + $this->assertEquals($customer_id, $order->getCustomerId()); } } @@ -1881,20 +1881,20 @@ public function testOutdatedRelationsAreResetForExistingRecords(): void $orderItemQuery = new ActiveQuery(OrderItem::class, $this->db); $orderItems = $orderItemQuery->findOne(1); - $this->assertEquals(1, $orderItems->order->id); - $this->assertEquals(1, $orderItems->item->id); + $this->assertEquals(1, $orderItems->getOrder()->getId()); + $this->assertEquals(1, $orderItems->getItem()->getId()); /** test `__set()`. */ - $orderItems->order_id = 2; - $orderItems->item_id = 1; - $this->assertEquals(2, $orderItems->order->id); - $this->assertEquals(1, $orderItems->item->id); + $orderItems->setOrderId(2); + $orderItems->setItemId(1); + $this->assertEquals(2, $orderItems->getOrder()->getId()); + $this->assertEquals(1, $orderItems->getItem()->getId()); /** Test `setAttribute()`. */ $orderItems->setAttribute('order_id', 3); $orderItems->setAttribute('item_id', 1); - $this->assertEquals(3, $orderItems->order->id); - $this->assertEquals(1, $orderItems->item->id); + $this->assertEquals(3, $orderItems->getOrder()->getId()); + $this->assertEquals(1, $orderItems->getItem()->getId()); } public function testOutdatedCompositeKeyRelationsAreReset(): void @@ -1904,26 +1904,27 @@ public function testOutdatedCompositeKeyRelationsAreReset(): void $dossierQuery = new ActiveQuery(Dossier::class, $this->db); $dossiers = $dossierQuery->findOne(['department_id' => 1, 'employee_id' => 1]); - $this->assertEquals('John Doe', $dossiers->employee->fullName); + $this->assertEquals('John Doe', $dossiers->getEmployee()->getFullName()); - $dossiers->department_id = 2; - $this->assertEquals('Ann Smith', $dossiers->employee->fullName); + $dossiers->setDepartmentId(2); + $this->assertEquals('Ann Smith', $dossiers->getEmployee()->getFullName()); - $dossiers->employee_id = 2; - $this->assertEquals('Will Smith', $dossiers->employee->fullName); + $dossiers->setEmployeeId(2); + $this->assertEquals('Will Smith', $dossiers->getEmployee()->getFullName()); - unset($dossiers->employee_id); - $this->assertNull($dossiers->employee); + // Dossier::$employee_id property cannot be null + // unset($dossiers->employee_id); + // $this->assertNull($dossiers->getEmployee()); $dossier = new Dossier($this->db); - $this->assertNull($dossier->employee); + $this->assertNull($dossier->getEmployee()); - $dossier->employee_id = 1; - $dossier->department_id = 2; - $this->assertEquals('Ann Smith', $dossier->employee->fullName); + $dossier->setEmployeeId(1); + $dossier->setDepartmentId(2); + $this->assertEquals('Ann Smith', $dossier->getEmployee()->getFullName()); - $dossier->employee_id = 2; - $this->assertEquals('Will Smith', $dossier->employee->fullName); + $dossier->setEmployeeId(2); + $this->assertEquals('Will Smith', $dossier->getEmployee()->getFullName()); } public function testOutdatedViaTableRelationsAreReset(): void @@ -1933,23 +1934,23 @@ public function testOutdatedViaTableRelationsAreReset(): void $orderQuery = new ActiveQuery(Order::class, $this->db); $orders = $orderQuery->findOne(1); - $orderItemIds = ArArrayHelper::getColumn($orders->items, 'id'); + $orderItemIds = ArArrayHelper::getColumn($orders->getItems(), 'id'); sort($orderItemIds); $this->assertSame([1, 2], $orderItemIds); - $orders->id = 2; + $orders->setId(2); sort($orderItemIds); - $orderItemIds = ArArrayHelper::getColumn($orders->items, 'id'); + $orderItemIds = ArArrayHelper::getColumn($orders->getItems(), 'id'); $this->assertSame([3, 4, 5], $orderItemIds); - unset($orders->id); - $this->assertSame([], $orders->items); + $orders->setId(null); + $this->assertSame([], $orders->getItems()); $order = new Order($this->db); - $this->assertSame([], $order->items); + $this->assertSame([], $order->getItems()); - $order->id = 3; - $orderItemIds = ArArrayHelper::getColumn($order->items, 'id'); + $order->setId(3); + $orderItemIds = ArArrayHelper::getColumn($order->getItems(), 'id'); $this->assertSame([2], $orderItemIds); } @@ -1963,20 +1964,20 @@ public function testInverseOfDynamic(): void /** request the inverseOf relation without explicitly (eagerly) loading it */ $orders2 = $customer->getOrders2Query()->all(); - $this->assertSame($customer, $orders2[0]->customer2); + $this->assertSame($customer, $orders2[0]->getCustomer2()); $orders2 = $customer->getOrders2Query()->onePopulate(); - $this->assertSame($customer, $orders2->customer2); + $this->assertSame($customer, $orders2->getCustomer2()); /** * request the inverseOf relation while also explicitly eager loading it (while possible, this is of course * redundant) */ $orders2 = $customer->getOrders2Query()->with('customer2')->all(); - $this->assertSame($customer, $orders2[0]->customer2); + $this->assertSame($customer, $orders2[0]->getCustomer2()); $orders2 = $customer->getOrders2Query()->with('customer2')->onePopulate(); - $this->assertSame($customer, $orders2->customer2); + $this->assertSame($customer, $orders2->getCustomer2()); /** request the inverseOf relation as array */ $orders2 = $customer->getOrders2Query()->asArray()->all(); @@ -2059,10 +2060,10 @@ public function testUpdateAttributes(): void $order = $orderQuery->findOne(1); $newTotal = 978; $this->assertSame(1, $order->updateAttributes(['total' => $newTotal])); - $this->assertEquals($newTotal, $order->total); + $this->assertEquals($newTotal, $order->getTotal()); $order = $orderQuery->findOne(1); - $this->assertEquals($newTotal, $order->total); + $this->assertEquals($newTotal, $order->getTotal()); /** @see https://github.com/yiisoft/yii2/issues/12143 */ $newOrder = new Order($this->db); @@ -2071,7 +2072,7 @@ public function testUpdateAttributes(): void $newTotal = 200; $this->assertSame(0, $newOrder->updateAttributes(['total' => $newTotal])); $this->assertTrue($newOrder->getIsNewRecord()); - $this->assertEquals($newTotal, $newOrder->total); + $this->assertEquals($newTotal, $newOrder->getTotal()); } /** @@ -2102,7 +2103,7 @@ public function testCustomARRelation(): void $orderItem = $orderItem->findOne(1); - $this->assertInstanceOf(Order::class, $orderItem->custom); + $this->assertInstanceOf(Order::class, $orderItem->getCustom()); } public function testGetAttributes(): void @@ -2297,6 +2298,8 @@ public function testOldAttributeAfterInsertAndUpdate(): void public function testCheckRelationUnknownPropertyException(): void { + self::markTestSkipped('There is no check for access to an unknown property.'); + $this->checkFixture($this->db, 'customer'); $customer = new ActiveQuery(Customer::class, $this->db); @@ -2310,6 +2313,8 @@ public function testCheckRelationUnknownPropertyException(): void public function testCheckRelationInvalidCallException(): void { + self::markTestSkipped('There is no check for access to an unknown property.'); + $this->checkFixture($this->db, 'customer'); $customer = new ActiveQuery(Customer::class, $this->db); @@ -2341,6 +2346,8 @@ public function testGetRelationInvalidArgumentException(): void public function testGetRelationInvalidArgumentExceptionHasNoRelationNamed(): void { + self::markTestSkipped('The same as test testGetRelationInvalidArgumentException()'); + $this->checkFixture($this->db, 'customer'); $customer = new ActiveQuery(Customer::class, $this->db); @@ -2357,6 +2364,8 @@ public function testGetRelationInvalidArgumentExceptionHasNoRelationNamed(): voi public function testGetRelationInvalidArgumentExceptionCaseSensitive(): void { + self::markTestSkipped('The same as test testGetRelationInvalidArgumentException()'); + $this->checkFixture($this->db, 'customer'); $customer = new ActiveQuery(Customer::class, $this->db); @@ -2393,22 +2402,22 @@ public function testUnlink(): void /** has many without delete */ $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(2); - $this->assertCount(2, $customer->ordersWithNullFK); - $customer->unlink('ordersWithNullFK', $customer->ordersWithNullFK[1], false); - $this->assertCount(1, $customer->ordersWithNullFK); + $this->assertCount(2, $customer->getOrdersWithNullFK()); + $customer->unlink('ordersWithNullFK', $customer->getOrdersWithNullFK()[1], false); + $this->assertCount(1, $customer->getOrdersWithNullFK()); $orderWithNullFKQuery = new ActiveQuery(OrderWithNullFK::class, $this->db); $orderWithNullFK = $orderWithNullFKQuery->findOne(3); - $this->assertEquals(3, $orderWithNullFK->id); - $this->assertNull($orderWithNullFK->customer_id); + $this->assertEquals(3, $orderWithNullFK->getId()); + $this->assertNull($orderWithNullFK->getCustomerId()); /** has many with delete */ $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(2); - $this->assertCount(2, $customer->orders); + $this->assertCount(2, $customer->getOrders()); - $customer->unlink('orders', $customer->orders[1], true); - $this->assertCount(1, $customer->orders); + $customer->unlink('orders', $customer->getOrders()[1], true); + $this->assertCount(1, $customer->getOrders()); $orderQuery = new ActiveQuery(Order::class, $this->db); $this->assertNull($orderQuery->findOne(3)); @@ -2416,18 +2425,18 @@ public function testUnlink(): void /** via model with delete */ $orderQuery = new ActiveQuery(Order::class, $this->db); $order = $orderQuery->findOne(2); - $this->assertCount(3, $order->items); - $this->assertCount(3, $order->orderItems); - $order->unlink('items', $order->items[2], true); - $this->assertCount(2, $order->items); - $this->assertCount(2, $order->orderItems); + $this->assertCount(3, $order->getItems()); + $this->assertCount(3, $order->getOrderItems()); + $order->unlink('items', $order->getItems()[2], true); + $this->assertCount(2, $order->getItems()); + $this->assertCount(2, $order->getOrderItems()); /** via model without delete */ - $this->assertCount(2, $order->itemsWithNullFK); - $order->unlink('itemsWithNullFK', $order->itemsWithNullFK[1], false); + $this->assertCount(2, $order->getItemsWithNullFK()); + $order->unlink('itemsWithNullFK', $order->getItemsWithNullFK()[1], false); - $this->assertCount(1, $order->itemsWithNullFK); - $this->assertCount(2, $order->orderItems); + $this->assertCount(1, $order->getItemsWithNullFK()); + $this->assertCount(2, $order->getOrderItems()); } public function testUnlinkAllAndConditionSetNull(): void @@ -2440,20 +2449,20 @@ public function testUnlinkAllAndConditionSetNull(): void $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(1); - $this->assertCount(3, $customer->ordersWithNullFK); - $this->assertCount(1, $customer->expensiveOrdersWithNullFK); + $this->assertCount(3, $customer->getOrdersWithNullFK()); + $this->assertCount(1, $customer->getExpensiveOrdersWithNullFK()); $orderWithNullFKQuery = new ActiveQuery(OrderWithNullFK::class, $this->db); $this->assertEquals(3, $orderWithNullFKQuery->count()); $customer->unlinkAll('expensiveOrdersWithNullFK'); - $this->assertCount(3, $customer->ordersWithNullFK); - $this->assertCount(0, $customer->expensiveOrdersWithNullFK); + $this->assertCount(3, $customer->getOrdersWithNullFK()); + $this->assertCount(0, $customer->getExpensiveOrdersWithNullFK()); $this->assertEquals(3, $orderWithNullFKQuery->count()); $customer = $customerQuery->findOne(1); - $this->assertCount(2, $customer->ordersWithNullFK); - $this->assertCount(0, $customer->expensiveOrdersWithNullFK); + $this->assertCount(2, $customer->getOrdersWithNullFK()); + $this->assertCount(0, $customer->getExpensiveOrdersWithNullFK()); } public function testUnlinkAllAndConditionDelete(): void @@ -2466,20 +2475,20 @@ public function testUnlinkAllAndConditionDelete(): void $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(1); - $this->assertCount(3, $customer->orders); - $this->assertCount(1, $customer->expensiveOrders); + $this->assertCount(3, $customer->getOrders()); + $this->assertCount(1, $customer->getExpensiveOrders()); $orderQuery = new ActiveQuery(Order::class, $this->db); $this->assertEquals(3, $orderQuery->count()); $customer->unlinkAll('expensiveOrders', true); - $this->assertCount(3, $customer->orders); - $this->assertCount(0, $customer->expensiveOrders); + $this->assertCount(3, $customer->getOrders()); + $this->assertCount(0, $customer->getExpensiveOrders()); $this->assertEquals(2, $orderQuery->count()); $customer = $customerQuery->findOne(1); - $this->assertCount(2, $customer->orders); - $this->assertCount(0, $customer->expensiveOrders); + $this->assertCount(2, $customer->getOrders()); + $this->assertCount(0, $customer->getExpensiveOrders()); } public function testUpdate(): void @@ -2534,28 +2543,28 @@ public function testUpdateCounters(): void $pk = ['order_id' => 2, 'item_id' => 4]; $orderItemQuery = new ActiveQuery(OrderItem::class, $this->db); $orderItem = $orderItemQuery->findOne($pk); - $this->assertEquals(1, $orderItem->quantity); + $this->assertEquals(1, $orderItem->getQuantity()); $ret = $orderItem->updateCounters(['quantity' => -1]); $this->assertTrue($ret); - $this->assertEquals(0, $orderItem->quantity); + $this->assertEquals(0, $orderItem->getQuantity()); $orderItem = $orderItemQuery->findOne($pk); - $this->assertEquals(0, $orderItem->quantity); + $this->assertEquals(0, $orderItem->getQuantity()); /** updateAllCounters */ $pk = ['order_id' => 1, 'item_id' => 2]; $orderItemQuery = new ActiveQuery(OrderItem::class, $this->db); $orderItem = $orderItemQuery->findOne($pk); - $this->assertEquals(2, $orderItem->quantity); + $this->assertEquals(2, $orderItem->getQuantity()); $orderItem = new OrderItem($this->db); $ret = $orderItem->updateAllCounters(['quantity' => 3, 'subtotal' => -10], $pk); $this->assertEquals(1, $ret); $orderItem = $orderItemQuery->findOne($pk); - $this->assertEquals(5, $orderItem->quantity); - $this->assertEquals(30, $orderItem->subtotal); + $this->assertEquals(5, $orderItem->getQuantity()); + $this->assertEquals(30, $orderItem->getSubtotal()); } public function testDelete(): void @@ -2566,7 +2575,7 @@ public function testDelete(): void $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(2); $this->assertInstanceOf(Customer::class, $customer); - $this->assertEquals('user2', $customer->name); + $this->assertEquals('user2', $customer->getName()); $customer->delete(); @@ -2600,14 +2609,14 @@ public function testViaWithCallable(): void $order = $orderQuery->findOne(2); - $expensiveItems = $order->expensiveItemsUsingViaWithCallable; - $cheapItems = $order->cheapItemsUsingViaWithCallable; + $expensiveItems = $order->getExpensiveItemsUsingViaWithCallable(); + $cheapItems = $order->getCheapItemsUsingViaWithCallable(); $this->assertCount(2, $expensiveItems); - $this->assertEquals(4, $expensiveItems[0]->id); - $this->assertEquals(5, $expensiveItems[1]->id); + $this->assertEquals(4, $expensiveItems[0]->getId()); + $this->assertEquals(5, $expensiveItems[1]->getId()); $this->assertCount(1, $cheapItems); - $this->assertEquals(3, $cheapItems[0]->id); + $this->assertEquals(3, $cheapItems[0]->getId()); } public function testLink(): void @@ -2616,36 +2625,36 @@ public function testLink(): void $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(2); - $this->assertCount(2, $customer->orders); + $this->assertCount(2, $customer->getOrders()); /** has many */ $order = new Order($this->db); - $order->total = 100; - $order->created_at = time(); - $this->assertTrue($order->isNewRecord); + $order->setTotal(100); + $order->setCreatedAt(time()); + $this->assertTrue($order->getIsNewRecord()); /** belongs to */ $order = new Order($this->db); - $order->total = 100; - $order->created_at = time(); - $this->assertTrue($order->isNewRecord); + $order->setTotal(100); + $order->setCreatedAt(time()); + $this->assertTrue($order->getIsNewRecord()); $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(1); - $this->assertNull($order->customer); + $this->assertNull($order->getCustomer()); $order->link('customer', $customer); - $this->assertFalse($order->isNewRecord); - $this->assertEquals(1, $order->customer_id); - $this->assertEquals(1, $order->customer->primaryKey); + $this->assertFalse($order->getIsNewRecord()); + $this->assertEquals(1, $order->getCustomerId()); + $this->assertEquals(1, $order->getCustomer()->getPrimaryKey()); /** via model */ $orderQuery = new ActiveQuery(Order::class, $this->db); $order = $orderQuery->findOne(1); - $this->assertCount(2, $order->items); - $this->assertCount(2, $order->orderItems); + $this->assertCount(2, $order->getItems()); + $this->assertCount(2, $order->getOrderItems()); $orderItemQuery = new ActiveQuery(OrderItem::class, $this->db); $orderItem = $orderItemQuery->findOne(['order_id' => 1, 'item_id' => 3]); @@ -2654,14 +2663,14 @@ public function testLink(): void $itemQuery = new ActiveQuery(Item::class, $this->db); $item = $itemQuery->findOne(3); $order->link('items', $item, ['quantity' => 10, 'subtotal' => 100]); - $this->assertCount(3, $order->items); - $this->assertCount(3, $order->orderItems); + $this->assertCount(3, $order->getItems()); + $this->assertCount(3, $order->getOrderItems()); $orderItemQuery = new ActiveQuery(OrderItem::class, $this->db); $orderItem = $orderItemQuery->findOne(['order_id' => 1, 'item_id' => 3]); $this->assertInstanceOf(OrderItem::class, $orderItem); - $this->assertEquals(10, $orderItem->quantity); - $this->assertEquals(100, $orderItem->subtotal); + $this->assertEquals(10, $orderItem->getQuantity()); + $this->assertEquals(100, $orderItem->getSubtotal()); } public function testEqual(): void diff --git a/tests/ActiveRecordFactoryTest.php b/tests/ActiveRecordFactoryTest.php index ac4dd0abc..59ed3f938 100644 --- a/tests/ActiveRecordFactoryTest.php +++ b/tests/ActiveRecordFactoryTest.php @@ -87,6 +87,6 @@ public function testGetArInstanceWithConstructor(): void $query = $this->arFactory->createQueryTo(CustomerWithConstructor::class); $customer = $query->onePopulate(); - $this->assertNotNull($customer->profile); + $this->assertNotNull($customer->getProfile()); } } diff --git a/tests/ActiveRecordTest.php b/tests/ActiveRecordTest.php index 02d6d8ef8..6b448abb1 100644 --- a/tests/ActiveRecordTest.php +++ b/tests/ActiveRecordTest.php @@ -13,7 +13,6 @@ use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerClosureField; use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerForArrayable; use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerWithAlias; -use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerWithProperties; use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Dog; use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Item; use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\NoExist; @@ -86,10 +85,9 @@ public function testStoreEmpty(): void $record = new NullValues($this->db); - /** this is to simulate empty html form submission */ - $record->var1 = ''; - $record->var2 = ''; - $record->var3 = ''; + $record->var1 = null; + $record->var2 = null; + $record->var3 = null; $record->stringcol = ''; $record->save(); @@ -128,22 +126,21 @@ public function testOutdatedRelationsAreResetForNewRecords(): void $orderItem = new OrderItem($this->db); - $orderItem->order_id = 1; - $orderItem->item_id = 3; - $this->assertEquals(1, $orderItem->order->id); - $this->assertEquals(3, $orderItem->item->id); + $orderItem->setOrderId(1); + $orderItem->setItemId(3); + $this->assertEquals(1, $orderItem->getOrder()->getId()); + $this->assertEquals(3, $orderItem->getItem()->getId()); - /** test `__set()`. */ - $orderItem->order_id = 2; - $orderItem->item_id = 1; - $this->assertEquals(2, $orderItem->order->id); - $this->assertEquals(1, $orderItem->item->id); + $orderItem->setOrderId(2); + $orderItem->setItemId(1); + $this->assertEquals(2, $orderItem->getOrder()->getId()); + $this->assertEquals(1, $orderItem->getItem()->getId()); /** test `setAttribute()`. */ $orderItem->setAttribute('order_id', 2); $orderItem->setAttribute('item_id', 2); - $this->assertEquals(2, $orderItem->order->id); - $this->assertEquals(2, $orderItem->item->id); + $this->assertEquals(2, $orderItem->getOrder()->getId()); + $this->assertEquals(2, $orderItem->getItem()->getId()); } public function testDefaultValues(): void @@ -243,21 +240,21 @@ public function testNoTablenameReplacement(): void $customer = new Customer($this->db); - $customer->name = 'Some {{weird}} name'; - $customer->email = 'test@example.com'; - $customer->address = 'Some {{%weird}} address'; + $customer->setName('Some {{weird}} name'); + $customer->setEmail('test@example.com'); + $customer->setAddress('Some {{%weird}} address'); $customer->insert(); $customer->refresh(); - $this->assertEquals('Some {{weird}} name', $customer->name); - $this->assertEquals('Some {{%weird}} address', $customer->address); + $this->assertEquals('Some {{weird}} name', $customer->getName()); + $this->assertEquals('Some {{%weird}} address', $customer->getAddress()); - $customer->name = 'Some {{updated}} name'; - $customer->address = 'Some {{%updated}} address'; + $customer->setName('Some {{updated}} name'); + $customer->setAddress('Some {{%updated}} address'); $customer->update(); - $this->assertEquals('Some {{updated}} name', $customer->name); - $this->assertEquals('Some {{%updated}} address', $customer->address); + $this->assertEquals('Some {{updated}} name', $customer->getName()); + $this->assertEquals('Some {{%updated}} address', $customer->getAddress()); } public static function legalValuesForFindByCondition(): array @@ -373,23 +370,25 @@ public function testResetNotSavedRelation(): void $order = new Order($this->db); - $order->customer_id = 1; - $order->created_at = 1_325_502_201; - $order->total = 0; + $order->setCustomerId(1); + $order->setCreatedAt(1_325_502_201); + $order->setTotal(0); $orderItem = new OrderItem($this->db); - $order->orderItems; + $order->getOrderItems(); $order->populateRelation('orderItems', [$orderItem]); $order->save(); - $this->assertCount(1, $order->orderItems); + $this->assertCount(1, $order->getOrderItems()); } public function testIssetException(): void { + self::markTestSkipped('There are no magic properties in the Cat class'); + $this->checkFixture($this->db, 'cat'); $cat = new Cat($this->db); @@ -400,6 +399,8 @@ public function testIssetException(): void public function testIssetThrowable(): void { + self::markTestSkipped('There are no magic properties in the Cat class'); + $this->checkFixture($this->db, 'cat'); $cat = new Cat($this->db); @@ -410,6 +411,8 @@ public function testIssetThrowable(): void public function testIssetNonExisting(): void { + self::markTestSkipped('There are no magic properties in the Cat class'); + $this->checkFixture($this->db, 'cat'); $cat = new Cat($this->db); @@ -443,13 +446,15 @@ public function testSetAttributes(): void public function testSetAttributeNoExist(): void { + self::markTestSkipped('There are no magic properties in the Cat class'); + $this->checkFixture($this->db, 'cat'); $cat = new Cat($this->db); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage( - 'Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Cat has no attribute named "noExist"' + 'Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\Cat has no attribute named "noExist"' ); $cat->setAttribute('noExist', 1); @@ -489,9 +494,9 @@ public function testIsAttributeChangedNotChanged(): void $customer = new Customer($this->db); - $this->assertEmpty($customer->getAttribute('name')); - $this->assertEmpty($customer->getOldAttribute('name')); - $this->assertFalse($customer->isAttributeChanged('name', false)); + $this->assertEmpty($customer->getAttribute('email')); + $this->assertEmpty($customer->getOldAttribute('email')); + $this->assertFalse($customer->isAttributeChanged('email', false)); } public function testTableSchemaException(): void @@ -509,17 +514,17 @@ public function testInsert(): void $customer = new Customer($this->db); - $customer->email = 'user4@example.com'; - $customer->name = 'user4'; - $customer->address = 'address4'; + $customer->setEmail('user4@example.com'); + $customer->setName('user4'); + $customer->setAddress('address4'); - $this->assertNull($customer->id); - $this->assertTrue($customer->isNewRecord); + $this->assertNull($customer->getAttribute('id')); + $this->assertTrue($customer->getIsNewRecord()); $customer->save(); - $this->assertNotNull($customer->id); - $this->assertFalse($customer->isNewRecord); + $this->assertNotNull($customer->getId()); + $this->assertFalse($customer->getIsNewRecord()); } /** @@ -533,31 +538,33 @@ public function testBooleanAttribute(): void $customer = new Customer($this->db); - $customer->name = 'boolean customer'; - $customer->email = 'mail@example.com'; - $customer->status = true; + $customer->setName('boolean customer'); + $customer->setEmail('mail@example.com'); + $customer->setStatus(1); $customer->save(); $customer->refresh(); - $this->assertEquals(1, $customer->status); + $this->assertEquals(1, $customer->getStatus()); - $customer->status = false; + $customer->setStatus(0); $customer->save(); $customer->refresh(); - $this->assertEquals(0, $customer->status); + $this->assertEquals(0, $customer->getStatus()); $customerQuery = new ActiveQuery(Customer::class, $this->db); - $customers = $customerQuery->where(['status' => true])->all(); + $customers = $customerQuery->where(['status' => 1])->all(); $this->assertCount(2, $customers); $customerQuery = new ActiveQuery(Customer::class, $this->db); - $customers = $customerQuery->where(['status' => false])->all(); + $customers = $customerQuery->where(['status' => 0])->all(); $this->assertCount(1, $customers); } public function testAttributeAccess(): void { + self::markTestSkipped('There are no magic properties in the Cat class'); + $this->checkFixture($this->db, 'customer'); $arClass = new Customer($this->db); @@ -639,10 +646,10 @@ public function testRefresh(): void $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(1); - $customer->name = 'to be refreshed'; + $customer->setName('to be refreshed'); $this->assertTrue($customer->refresh()); - $this->assertEquals('user1', $customer->name); + $this->assertEquals('user1', $customer->getName()); } public function testEquals(): void @@ -679,12 +686,12 @@ public function testUnlinkWithViaOnCondition($delete, $count) $orderQuery = new ActiveQuery(Order::class, $this->db); $order = $orderQuery->findOne(2); - $this->assertCount(1, $order->itemsFor8); - $order->unlink('itemsFor8', $order->itemsFor8[0], $delete); + $this->assertCount(1, $order->getItemsFor8()); + $order->unlink('itemsFor8', $order->getItemsFor8()[0], $delete); $order = $orderQuery->findOne(2); - $this->assertCount(0, $order->itemsFor8); - $this->assertCount(2, $order->orderItemsWithNullFK); + $this->assertCount(0, $order->getItemsFor8()); + $this->assertCount(2, $order->getOrderItemsWithNullFK()); $orderItemQuery = new ActiveQuery(OrderItemWithNullFK::class, $this->db); $this->assertCount(1, $orderItemQuery->findAll([ @@ -705,7 +712,7 @@ public function testVirtualRelation() /** @var Order $order */ $order = $orderQuery->findOne(2); - $order->setVirtualCustomerId($order->customer_id); + $order->setVirtualCustomerId($order->getCustomerId()); $this->assertNotNull($order->getVirtualCustomerQuery()); } @@ -722,14 +729,14 @@ public function testJoinWithEager() $eagerCustomers = $customerQuery->joinWith(['items2'])->all(); $eagerItemsCount = 0; foreach ($eagerCustomers as $customer) { - $eagerItemsCount += is_countable($customer->items2) ? count($customer->items2) : 0; + $eagerItemsCount += is_countable($customer->getItems2()) ? count($customer->getItems2()) : 0; } $customerQuery = new ActiveQuery(Customer::class, $this->db); $lazyCustomers = $customerQuery->all(); $lazyItemsCount = 0; foreach ($lazyCustomers as $customer) { - $lazyItemsCount += is_countable($customer->items2) ? count($customer->items2) : 0; + $lazyItemsCount += is_countable($customer->getItems2()) ? count($customer->getItems2()) : 0; } $this->assertEquals($eagerItemsCount, $lazyItemsCount); @@ -859,7 +866,7 @@ public function testGetOldPrimaryKey(): void $customerQuery = new ActiveQuery(Customer::class, $this->db); $customer = $customerQuery->findOne(1); - $customer->id = 2; + $customer->setId(2); $this->assertSame(1, $customer->getOldPrimaryKey()); $this->assertSame(['id' => 1], $customer->getOldPrimaryKey(true)); @@ -871,18 +878,38 @@ public function testGetDirtyAttributesOnNewRecord(): void $customer = new Customer($this->db); - $this->assertSame([], $customer->getDirtyAttributes()); + $this->assertSame( + [ + 'name' => null, + 'address' => null, + 'status' => 0, + 'profile_id' => null, + ], + $customer->getDirtyAttributes() + ); $customer->setAttribute('name', 'Adam'); $customer->setAttribute('email', 'adam@example.com'); $customer->setAttribute('address', null); + $this->assertEquals([], $customer->getDirtyAttributes([])); + $this->assertEquals( - ['name' => 'Adam', 'email' => 'adam@example.com', 'address' => null], + [ + 'name' => 'Adam', + 'email' => 'adam@example.com', + 'address' => null, + 'status' => 0, + 'profile_id' => null, + ], $customer->getDirtyAttributes() ); $this->assertEquals( - ['email' => 'adam@example.com', 'address' => null], + [ + 'email' => 'adam@example.com', + 'address' => null, + 'status' => 0, + ], $customer->getDirtyAttributes(['id', 'email', 'address', 'status', 'unknown']), ); @@ -916,34 +943,4 @@ public function testGetDirtyAttributesAfterFind(): void $customer->getDirtyAttributes(['id', 'email', 'address', 'status', 'unknown']), ); } - - public function testGetDirtyAttributesWithProperties(): void - { - $this->checkFixture($this->db, 'customer'); - - $customer = new CustomerWithProperties($this->db); - $this->assertSame([ - 'name' => null, - 'address' => null, - ], $customer->getDirtyAttributes()); - - $customerQuery = new ActiveQuery(CustomerWithProperties::class, $this->db); - $customer = $customerQuery->findOne(1); - - $this->assertSame([], $customer->getDirtyAttributes()); - - $customer->setEmail('adam@example.com'); - $customer->setName('Adam'); - $customer->setAddress(null); - $customer->setStatus(null); - - $this->assertEquals( - ['email' => 'adam@example.com', 'name' => 'Adam', 'address' => null, 'status' => null], - $customer->getDirtyAttributes(), - ); - $this->assertEquals( - ['email' => 'adam@example.com', 'address' => null], - $customer->getDirtyAttributes(['id', 'email', 'address', 'unknown']), - ); - } } diff --git a/tests/BatchQueryResultTest.php b/tests/BatchQueryResultTest.php index c7de6fd97..c03c96f67 100644 --- a/tests/BatchQueryResultTest.php +++ b/tests/BatchQueryResultTest.php @@ -131,9 +131,9 @@ public function testActiveQuery(): void } $this->assertCount(3, $customers); - $this->assertCount(1, $customers[0]->orders); - $this->assertCount(2, $customers[1]->orders); - $this->assertCount(0, $customers[2]->orders); + $this->assertCount(1, $customers[0]->getOrders()); + $this->assertCount(2, $customers[1]->getOrders()); + $this->assertCount(0, $customers[2]->getOrders()); } public function testBatchWithIndexBy(): void @@ -147,9 +147,9 @@ public function testBatchWithIndexBy(): void $customers = $this->getAllRowsFromBatch($query->batch(2)); $this->assertCount(3, $customers); - $this->assertEquals('user1', $customers[0]->name); - $this->assertEquals('user2', $customers[1]->name); - $this->assertEquals('user3', $customers[2]->name); + $this->assertEquals('user1', $customers[0]->getName()); + $this->assertEquals('user2', $customers[1]->getName()); + $this->assertEquals('user3', $customers[2]->getName()); } protected function getAllRowsFromBatch(BatchQueryResultInterface $batch): array diff --git a/tests/Driver/Mssql/MagicActiveRecordTest.php b/tests/Driver/Mssql/MagicActiveRecordTest.php new file mode 100644 index 000000000..219c6da92 --- /dev/null +++ b/tests/Driver/Mssql/MagicActiveRecordTest.php @@ -0,0 +1,68 @@ +db = $mssqlHelper->createConnection(); + } + + protected function tearDown(): void + { + parent::tearDown(); + + $this->db->close(); + + unset($this->db); + } + + public function testSaveWithTrigger(): void + { + $this->checkFixture($this->db, 'test_trigger'); + + // drop trigger if exist + $sql = <<db->createCommand($sql)->execute(); + + // create trigger + $sql = <<db->createCommand($sql)->execute(); + + $record = new TestTrigger($this->db); + + $record->stringcol = 'test'; + + $this->assertTrue($record->save()); + $this->assertEquals(1, $record->id); + + $testRecordQuery = new ActiveQuery(TestTriggerAlert::class, $this->db); + + $this->assertEquals('test', $testRecordQuery->findOne(1)->stringcol); + } +} diff --git a/tests/Driver/Mysql/ActiveRecordTest.php b/tests/Driver/Mysql/ActiveRecordTest.php index 9f72399a7..0b502d231 100644 --- a/tests/Driver/Mysql/ActiveRecordTest.php +++ b/tests/Driver/Mysql/ActiveRecordTest.php @@ -34,17 +34,17 @@ public function testExplicitPkOnAutoIncrement(): void $customer = new Customer($this->db); - $customer->id = 1337; - $customer->email = 'user1337@example.com'; - $customer->name = 'user1337'; - $customer->address = 'address1337'; + $customer->setId(1337); + $customer->setEmail('user1337@example.com'); + $customer->setName('user1337'); + $customer->setAddress('address1337'); - $this->assertTrue($customer->isNewRecord); + $this->assertTrue($customer->getIsNewRecord()); $customer->save(); - $this->assertEquals(1337, $customer->id); - $this->assertFalse($customer->isNewRecord); + $this->assertEquals(1337, $customer->getId()); + $this->assertFalse($customer->getIsNewRecord()); } /** @@ -64,9 +64,9 @@ public function testEagerLoadingUsingStringIdentifiers(): void /** @var Beta[] $betas */ foreach ($betas as $beta) { - $this->assertNotNull($beta->alpha); - $this->assertEquals($beta->alpha_string_identifier, $beta->alpha->string_identifier); - $alphaIdentifiers[] = $beta->alpha->string_identifier; + $this->assertNotNull($beta->getAlpha()); + $this->assertEquals($beta->getAlphaStringIdentifier(), $beta->getAlpha()->getStringIdentifier()); + $alphaIdentifiers[] = $beta->getAlpha()->getStringIdentifier(); } $this->assertEquals(['1', '01', '001', '001', '2', '2b', '2b', '02'], $alphaIdentifiers); diff --git a/tests/Driver/Mysql/MagicActiveRecordTest.php b/tests/Driver/Mysql/MagicActiveRecordTest.php new file mode 100644 index 000000000..411dbe03e --- /dev/null +++ b/tests/Driver/Mysql/MagicActiveRecordTest.php @@ -0,0 +1,74 @@ +db = $mysqlHelper->createConnection(); + } + + protected function tearDown(): void + { + parent::tearDown(); + + $this->db->close(); + + unset($this->db); + } + + public function testExplicitPkOnAutoIncrement(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new Customer($this->db); + + $customer->id = 1337; + $customer->email = 'user1337@example.com'; + $customer->name = 'user1337'; + $customer->address = 'address1337'; + + $this->assertTrue($customer->isNewRecord); + + $customer->save(); + + $this->assertEquals(1337, $customer->id); + $this->assertFalse($customer->isNewRecord); + } + + /** + * {@see https://github.com/yiisoft/yii2/issues/15482} + */ + public function testEagerLoadingUsingStringIdentifiers(): void + { + $this->checkFixture($this->db, 'beta'); + + $betaQuery = new ActiveQuery(Beta::class, $this->db); + + $betas = $betaQuery->with('alpha')->all(); + + $this->assertNotEmpty($betas); + + $alphaIdentifiers = []; + + /** @var Beta[] $betas */ + foreach ($betas as $beta) { + $this->assertNotNull($beta->alpha); + $this->assertEquals($beta->alpha_string_identifier, $beta->alpha->string_identifier); + $alphaIdentifiers[] = $beta->alpha->string_identifier; + } + + $this->assertEquals(['1', '01', '001', '001', '2', '2b', '2b', '02'], $alphaIdentifiers); + } +} diff --git a/tests/Driver/Oracle/ActiveQueryFindTest.php b/tests/Driver/Oracle/ActiveQueryFindTest.php index 965bb5da8..0b495a120 100644 --- a/tests/Driver/Oracle/ActiveQueryFindTest.php +++ b/tests/Driver/Oracle/ActiveQueryFindTest.php @@ -40,17 +40,17 @@ public function testFindEager(): void $this->assertTrue($customers[1]->isRelationPopulated('orders')); $this->assertTrue($customers[2]->isRelationPopulated('orders')); $this->assertTrue($customers[3]->isRelationPopulated('orders')); - $this->assertCount(1, $customers[1]->orders); - $this->assertCount(2, $customers[2]->orders); - $this->assertCount(0, $customers[3]->orders); + $this->assertCount(1, $customers[1]->getOrders()); + $this->assertCount(2, $customers[2]->getOrders()); + $this->assertCount(0, $customers[3]->getOrders()); - unset($customers[1]->orders); + $customers[1]->resetRelation('orders'); $this->assertFalse($customers[1]->isRelationPopulated('orders')); $customer = $customerQuery->where(['id' => 1])->with('orders')->onePopulate(); $this->assertTrue($customer->isRelationPopulated('orders')); - $this->assertCount(1, $customer->orders); - $this->assertCount(1, $customer->relatedRecords); + $this->assertCount(1, $customer->getOrders()); + $this->assertCount(1, $customer->getRelatedRecords()); /** multiple with() calls */ $orderQuery = new ActiveQuery(Order::class, $this->db); diff --git a/tests/Driver/Oracle/ActiveQueryTest.php b/tests/Driver/Oracle/ActiveQueryTest.php index 13d9a3695..ccce1fa4e 100644 --- a/tests/Driver/Oracle/ActiveQueryTest.php +++ b/tests/Driver/Oracle/ActiveQueryTest.php @@ -7,7 +7,7 @@ use Throwable; use Yiisoft\ActiveRecord\ActiveQuery; use Yiisoft\ActiveRecord\Tests\Driver\Oracle\Stubs\Order; -use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\BitValues; +use Yiisoft\ActiveRecord\Tests\Driver\Oracle\Stubs\BitValues; use Yiisoft\ActiveRecord\Tests\Support\OracleHelper; use Yiisoft\Db\Exception\Exception; use Yiisoft\Db\Exception\InvalidConfigException; @@ -62,9 +62,9 @@ public function testJoinWithAlias(string $aliasMethod): void } $this->assertCount(3, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); - $this->assertEquals(1, $orders[2]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); + $this->assertEquals(1, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); $this->assertTrue($orders[1]->isRelationPopulated('customer')); $this->assertTrue($orders[2]->isRelationPopulated('customer')); @@ -84,8 +84,8 @@ public function testJoinWithAlias(string $aliasMethod): void } $this->assertCount(2, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('customer')); $this->assertTrue($orders[1]->isRelationPopulated('customer')); @@ -104,8 +104,8 @@ public function testJoinWithAlias(string $aliasMethod): void } $this->assertCount(2, $orders); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); $this->assertFalse($orders[0]->isRelationPopulated('customer')); $this->assertFalse($orders[1]->isRelationPopulated('customer')); @@ -128,10 +128,10 @@ public function testJoinWithAlias(string $aliasMethod): void } $this->assertCount(2, $orders); - $this->assertCount(2, $orders[0]->books); - $this->assertCount(1, $orders[1]->books); - $this->assertEquals(1, $orders[0]->id); - $this->assertEquals(3, $orders[1]->id); + $this->assertCount(2, $orders[0]->getBooks()); + $this->assertCount(1, $orders[1]->getBooks()); + $this->assertEquals(1, $orders[0]->getId()); + $this->assertEquals(3, $orders[1]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('books')); $this->assertTrue($orders[1]->isRelationPopulated('books')); @@ -171,11 +171,11 @@ public function testJoinWithAlias(string $aliasMethod): void } $this->assertCount(1, $orders); - $this->assertCount(3, $orders[0]->items); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(2, $orders[0]->items[0]->category->id); + $this->assertCount(3, $orders[0]->getItems()); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(2, $orders[0]->getItems()[0]->getCategory()->getId()); $this->assertTrue($orders[0]->isRelationPopulated('items')); - $this->assertTrue($orders[0]->items[0]->isRelationPopulated('category')); + $this->assertTrue($orders[0]->getItems()[0]->isRelationPopulated('category')); /** join with ON condition */ if ($aliasMethod === 'explicit' || $aliasMethod === 'querysyntax') { @@ -185,12 +185,12 @@ public function testJoinWithAlias(string $aliasMethod): void $orders = $orderQuery->joinWith(["$relationName b"])->orderBy('order.id')->all(); $this->assertCount(3, $orders); - $this->assertCount(2, $orders[0]->$relationName); - $this->assertCount(0, $orders[1]->$relationName); - $this->assertCount(1, $orders[2]->$relationName); - $this->assertEquals(1, $orders[0]->id); - $this->assertEquals(2, $orders[1]->id); - $this->assertEquals(3, $orders[2]->id); + $this->assertCount(2, $orders[0]->relation($relationName)); + $this->assertCount(0, $orders[1]->relation($relationName)); + $this->assertCount(1, $orders[2]->relation($relationName)); + $this->assertEquals(1, $orders[0]->getId()); + $this->assertEquals(2, $orders[1]->getId()); + $this->assertEquals(3, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated($relationName)); $this->assertTrue($orders[1]->isRelationPopulated($relationName)); $this->assertTrue($orders[2]->isRelationPopulated($relationName)); @@ -204,12 +204,12 @@ public function testJoinWithAlias(string $aliasMethod): void $orders = $orderQuery->joinWith([(string)$relationName])->orderBy('order.id')->all(); $this->assertCount(3, $orders); - $this->assertCount(2, $orders[0]->$relationName); - $this->assertCount(0, $orders[1]->$relationName); - $this->assertCount(1, $orders[2]->$relationName); - $this->assertEquals(1, $orders[0]->id); - $this->assertEquals(2, $orders[1]->id); - $this->assertEquals(3, $orders[2]->id); + $this->assertCount(2, $orders[0]->relation($relationName)); + $this->assertCount(0, $orders[1]->relation($relationName)); + $this->assertCount(1, $orders[2]->relation($relationName)); + $this->assertEquals(1, $orders[0]->getId()); + $this->assertEquals(2, $orders[1]->getId()); + $this->assertEquals(3, $orders[2]->getId()); $this->assertTrue($orders[0]->isRelationPopulated($relationName)); $this->assertTrue($orders[1]->isRelationPopulated($relationName)); $this->assertTrue($orders[2]->isRelationPopulated($relationName)); @@ -246,7 +246,7 @@ public function testJoinWithAlias(string $aliasMethod): void $customer = $customerQuery->where([$query->applyAlias('order', 'id') => 1])->onePopulate(); } - $this->assertEquals(1, $customer->id); + $this->assertEquals(1, $customer->getId()); $this->assertNotNull($customer); /** join with sub-relation called inside Closure */ @@ -270,11 +270,11 @@ public function testJoinWithAlias(string $aliasMethod): void )->orderBy('order.id')->all(); $this->assertCount(1, $orders); - $this->assertCount(3, $orders[0]->items); - $this->assertEquals(2, $orders[0]->id); - $this->assertEquals(2, $orders[0]->items[0]->category->id); + $this->assertCount(3, $orders[0]->getItems()); + $this->assertEquals(2, $orders[0]->getId()); + $this->assertEquals(2, $orders[0]->getItems()[0]->getCategory()->getId()); $this->assertTrue($orders[0]->isRelationPopulated('items')); - $this->assertTrue($orders[0]->items[0]->isRelationPopulated('category')); + $this->assertTrue($orders[0]->getItems()[0]->isRelationPopulated('category')); } /** @@ -299,7 +299,7 @@ public function testJoinWithSameTable(): void $orders, $query->createCommand()->getRawSql() . print_r($orders, true) ); - $this->assertEquals(2, $orders[0]->id); + $this->assertEquals(2, $orders[0]->getId()); $this->assertFalse($orders[0]->isRelationPopulated('bookItems')); $this->assertFalse($orders[0]->isRelationPopulated('movieItems')); @@ -312,9 +312,9 @@ public function testJoinWithSameTable(): void $orders, $query->createCommand()->getRawSql() . print_r($orders, true) ); - $this->assertCount(0, $orders[0]->bookItems); - $this->assertCount(3, $orders[0]->movieItems); - $this->assertEquals(2, $orders[0]->id); + $this->assertCount(0, $orders[0]->getBookItems()); + $this->assertCount(3, $orders[0]->getMovieItems()); + $this->assertEquals(2, $orders[0]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('bookItems')); $this->assertTrue($orders[0]->isRelationPopulated('movieItems')); @@ -345,7 +345,7 @@ public function testJoinWithSameTable(): void $orders, $query->createCommand()->getRawSql() . print_r($orders, true) ); - $this->assertEquals(2, $orders[0]->id); + $this->assertEquals(2, $orders[0]->getId()); $this->assertFalse($orders[0]->isRelationPopulated('itemsIndexed')); /** with eager loading, only for one relation as it would be overwritten otherwise. */ @@ -369,8 +369,8 @@ public function testJoinWithSameTable(): void )->where(['{{movies}}.[[name]]' => 'Toy Story']); $orders = $query->all(); $this->assertCount(1, $orders, $query->createCommand()->getRawSql() . print_r($orders, true)); - $this->assertCount(3, $orders[0]->itemsIndexed); - $this->assertEquals(2, $orders[0]->id); + $this->assertCount(3, $orders[0]->getItemsIndexed()); + $this->assertEquals(2, $orders[0]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('itemsIndexed')); /** with eager loading, and the other relation */ @@ -395,8 +395,8 @@ public function testJoinWithSameTable(): void ->where(['{{movies}}.[[name]]' => 'Toy Story']); $orders = $query->all(); $this->assertCount(1, $orders, $query->createCommand()->getRawSql() . print_r($orders, true)); - $this->assertCount(0, $orders[0]->itemsIndexed); - $this->assertEquals(2, $orders[0]->id); + $this->assertCount(0, $orders[0]->getItemsIndexed()); + $this->assertEquals(2, $orders[0]->getId()); $this->assertTrue($orders[0]->isRelationPopulated('itemsIndexed')); } diff --git a/tests/Driver/Oracle/ActiveRecordTest.php b/tests/Driver/Oracle/ActiveRecordTest.php index dbad51704..5b41b4541 100644 --- a/tests/Driver/Oracle/ActiveRecordTest.php +++ b/tests/Driver/Oracle/ActiveRecordTest.php @@ -102,22 +102,22 @@ public function testBooleanAttribute(): void $customer = new Customer($this->db); - $customer->name = 'boolean customer'; - $customer->email = 'mail@example.com'; - $customer->status = '1'; + $customer->setName('boolean customer'); + $customer->setEmail('mail@example.com'); + $customer->setStatus(1); $customer->save(); $customer->refresh(); - $this->assertEquals('1', $customer->status); + $this->assertEquals(1, $customer->getStatus()); - $customer->status = '0'; + $customer->setStatus(0); $customer->save(); $customer->refresh(); - $this->assertEquals('0', $customer->status); + $this->assertEquals(0, $customer->getStatus()); $customerQuery = new ActiveQuery(Customer::class, $this->db); - $customers = $customerQuery->where(['status' => '1'])->all(); + $customers = $customerQuery->where(['status' => 1])->all(); $this->assertCount(2, $customers); $customerQuery = new ActiveQuery(Customer::class, $this->db); diff --git a/tests/Driver/Oracle/MagicActiveRecordTest.php b/tests/Driver/Oracle/MagicActiveRecordTest.php new file mode 100644 index 000000000..0222f5fb7 --- /dev/null +++ b/tests/Driver/Oracle/MagicActiveRecordTest.php @@ -0,0 +1,169 @@ +db = $oracleHelper->createConnection(); + } + + protected function tearDown(): void + { + parent::tearDown(); + + $this->db->close(); + + unset($this->db); + } + + public function testCastValues(): void + { + $this->markTestSkipped('Cant bind floats without support from a custom PDO driver.'); + + $this->checkFixture($this->db, 'customer'); + + $arClass = new Type($this->db); + $arClass->int_col = 123; + $arClass->int_col2 = 456; + $arClass->smallint_col = 42; + $arClass->char_col = '1337'; + $arClass->char_col2 = 'test'; + $arClass->char_col3 = 'test123'; + /** can't bind floats without support from a custom PDO driver */ + $arClass->float_col = 2; + $arClass->float_col2 = 1; + $arClass->bool_col = 1; + $arClass->bool_col2 = 0; + $arClass->save(); + + $aqClass = new ActiveQuery(Type::class, $this->db); + $query = $aqClass->onePopulate(); + + $this->assertSame(123, $query->int_col); + $this->assertSame(456, $query->int_col2); + $this->assertSame(42, $query->smallint_col); + $this->assertSame('1337', trim($query->char_col)); + $this->assertSame('test', $query->char_col2); + $this->assertSame('test123', $query->char_col3); + $this->assertSame(2.0, $query->float_col); + $this->assertSame(1.0, $query->float_col2); + $this->assertEquals('1', $query->bool_col); + $this->assertEquals('0', $query->bool_col2); + } + + public function testDefaultValues(): void + { + $this->checkFixture($this->db, 'customer'); + + $arClass = new Type($this->db); + $arClass->loadDefaultValues(); + $this->assertEquals(1, $arClass->int_col2); + $this->assertEquals('something', $arClass->char_col2); + $this->assertEquals(1.23, $arClass->float_col2); + $this->assertEquals(33.22, $arClass->numeric_col); + $this->assertEquals('1', $arClass->bool_col2); + + // not testing $arClass->time, because oci\Schema can't read default value + + $arClass = new Type($this->db); + $arClass->char_col2 = 'not something'; + + $arClass->loadDefaultValues(); + $this->assertEquals('not something', $arClass->char_col2); + + $arClass = new Type($this->db); + $arClass->char_col2 = 'not something'; + + $arClass->loadDefaultValues(false); + $this->assertEquals('something', $arClass->char_col2); + } + + /** + * Some PDO implementations (e.g. cubrid) do not support boolean values. + * + * Make sure this does not affect AR layer. + */ + public function testBooleanAttribute(): void + { + $this->checkFixture($this->db, 'customer', true); + + $customer = new Customer($this->db); + + $customer->name = 'boolean customer'; + $customer->email = 'mail@example.com'; + $customer->status = '1'; + + $customer->save(); + $customer->refresh(); + $this->assertEquals('1', $customer->status); + + $customer->status = '0'; + $customer->save(); + + $customer->refresh(); + $this->assertEquals('0', $customer->status); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $customers = $customerQuery->where(['status' => '1'])->all(); + $this->assertCount(2, $customers); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $customers = $customerQuery->where(['status' => '0'])->all(); + $this->assertCount(1, $customers); + } + + public function testToArray(): void + { + $this->checkFixture($this->db, 'customer', true); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $customer = $customerQuery->findOne(1); + + $this->assertSame( + [ + 'id' => 1, + 'email' => 'user1@example.com', + 'name' => 'user1', + 'address' => 'address1', + 'status' => 1, + 'bool_status' => '1', + 'profile_id' => 1, + ], + $customer->toArray(), + ); + } + + public function testToArrayWithClosure(): void + { + $this->checkFixture($this->db, 'customer', true); + + $customerQuery = new ActiveQuery(CustomerClosureField::class, $this->db); + $customer = $customerQuery->findOne(1); + + $this->assertSame( + [ + 'id' => 1, + 'email' => 'user1@example.com', + 'name' => 'user1', + 'address' => 'address1', + 'status' => 'active', + 'bool_status' => '1', + 'profile_id' => 1, + ], + $customer->toArray(), + ); + } +} diff --git a/tests/Driver/Oracle/Stubs/BitValues.php b/tests/Driver/Oracle/Stubs/BitValues.php new file mode 100644 index 000000000..a077b6ec7 --- /dev/null +++ b/tests/Driver/Oracle/Stubs/BitValues.php @@ -0,0 +1,19 @@ +checkFixture($this->db, 'customer'); $customer = new Customer($this->db); - $customer->id = 1337; - $customer->email = 'user1337@example.com'; - $customer->name = 'user1337'; - $customer->address = 'address1337'; - $this->assertTrue($customer->isNewRecord); + $customer->setId(1337); + $customer->setEmail('user1337@example.com'); + $customer->setName('user1337'); + $customer->setAddress('address1337'); + $this->assertTrue($customer->getIsNewRecord()); $customer->save(); - $this->assertEquals(1337, $customer->id); - $this->assertFalse($customer->isNewRecord); + $this->assertEquals(1337, $customer->getId()); + $this->assertFalse($customer->getIsNewRecord()); } /** @@ -70,9 +70,9 @@ public function testEagerLoadingUsingStringIdentifiers(): void /** @var Beta[] $betas */ foreach ($betas as $beta) { - $this->assertNotNull($beta->alpha); - $this->assertEquals($beta->alpha_string_identifier, $beta->alpha->string_identifier); - $alphaIdentifiers[] = $beta->alpha->string_identifier; + $this->assertNotNull($beta->getAlpha()); + $this->assertEquals($beta->getAlphaStringIdentifier(), $beta->getAlpha()->getStringIdentifier()); + $alphaIdentifiers[] = $beta->getAlpha()->getStringIdentifier(); } $this->assertEquals(['1', '01', '001', '001', '2', '2b', '2b', '02'], $alphaIdentifiers); @@ -83,19 +83,19 @@ public function testBooleanAttribute(): void $this->checkFixture($this->db, 'customer', true); $customer = new Customer($this->db); - $customer->name = 'boolean customer'; - $customer->email = 'mail@example.com'; - $customer->bool_status = false; + $customer->setName('boolean customer'); + $customer->setEmail('mail@example.com'); + $customer->setBoolStatus(false); $customer->save(); $customer->refresh(); - $this->assertFalse($customer->bool_status); + $this->assertFalse($customer->getBoolStatus()); - $customer->bool_status = true; + $customer->setBoolStatus(true); $customer->save(); $customer->refresh(); - $this->assertTrue($customer->bool_status); + $this->assertTrue($customer->getBoolStatus()); $customerQuery = new ActiveQuery(Customer::class, $this->db); $customers = $customerQuery->where(['bool_status' => true])->all(); @@ -177,8 +177,8 @@ public function testBooleanDefaultValues(): void $arClass = new BoolAR($this->db); $this->assertNull($arClass->bool_col); - $this->assertNull($arClass->default_true); - $this->assertNull($arClass->default_false); + $this->assertTrue($arClass->default_true); + $this->assertFalse($arClass->default_false); $arClass->loadDefaultValues(); @@ -198,7 +198,7 @@ public function testPrimaryKeyAfterSave(): void $record->save(); - $this->assertEquals(5, $record->primaryKey); + $this->assertEquals(5, $record->getPrimaryKey()); } public static function arrayValuesProvider(): array @@ -303,7 +303,7 @@ public function testArrayValues($attributes): void $type = new ArrayAndJsonTypes($this->db); foreach ($attributes as $attribute => $expected) { - $type->$attribute = $expected[0]; + $type->setAttribute($attribute, $expected[0]); } $type->save(); @@ -314,7 +314,7 @@ public function testArrayValues($attributes): void foreach ($attributes as $attribute => $expected) { $expected = $expected[1] ?? $expected[0]; - $value = $type->$attribute; + $value = $type->getAttribute($attribute); if ($expected instanceof ArrayExpression) { $expected = $expected->getValue(); @@ -326,7 +326,7 @@ public function testArrayValues($attributes): void $this->assertInstanceOf(ArrayAccess::class, $value); $this->assertInstanceOf(Traversable::class, $value); /** testing arrayaccess */ - foreach ($type->$attribute as $key => $v) { + foreach ($type->getAttribute($attribute) as $key => $v) { $this->assertSame($expected[$key], $value[$key]); } } diff --git a/tests/Driver/Pgsql/MagicActiveRecordTest.php b/tests/Driver/Pgsql/MagicActiveRecordTest.php new file mode 100644 index 000000000..20821bcb9 --- /dev/null +++ b/tests/Driver/Pgsql/MagicActiveRecordTest.php @@ -0,0 +1,384 @@ +db = $pgsqlHelper->createConnection(); + } + + protected function tearDown(): void + { + parent::tearDown(); + + $this->db->close(); + + unset($this->db); + } + + public function testExplicitPkOnAutoIncrement(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new Customer($this->db); + $customer->id = 1337; + $customer->email = 'user1337@example.com'; + $customer->name = 'user1337'; + $customer->address = 'address1337'; + $this->assertTrue($customer->isNewRecord); + + $customer->save(); + $this->assertEquals(1337, $customer->id); + $this->assertFalse($customer->isNewRecord); + } + + /** + * {@see https://github.com/yiisoft/yii2/issues/15482} + */ + public function testEagerLoadingUsingStringIdentifiers(): void + { + $this->checkFixture($this->db, 'beta'); + + $betaQuery = new ActiveQuery(Beta::class, $this->db); + $betas = $betaQuery->with('alpha')->all(); + $this->assertNotEmpty($betas); + + $alphaIdentifiers = []; + + /** @var Beta[] $betas */ + foreach ($betas as $beta) { + $this->assertNotNull($beta->alpha); + $this->assertEquals($beta->alpha_string_identifier, $beta->alpha->string_identifier); + $alphaIdentifiers[] = $beta->alpha->string_identifier; + } + + $this->assertEquals(['1', '01', '001', '001', '2', '2b', '2b', '02'], $alphaIdentifiers); + } + + public function testBooleanAttribute(): void + { + $this->checkFixture($this->db, 'customer', true); + + $customer = new Customer($this->db); + $customer->name = 'boolean customer'; + $customer->email = 'mail@example.com'; + $customer->bool_status = false; + $customer->save(); + + $customer->refresh(); + $this->assertFalse($customer->bool_status); + + $customer->bool_status = true; + + $customer->save(); + $customer->refresh(); + $this->assertTrue($customer->bool_status); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $customers = $customerQuery->where(['bool_status' => true])->all(); + $this->assertCount(3, $customers); + + $customers = $customerQuery->where(['bool_status' => false])->all(); + $this->assertCount(1, $customers); + } + + public function testBooleanValues(): void + { + $this->checkFixture($this->db, 'bool_values'); + + $command = $this->db->createCommand(); + $command->batchInsert('bool_values', ['bool_col'], [[true], [false]])->execute(); + $boolARQuery = new ActiveQuery(BoolAR::class, $this->db); + + $this->assertTrue($boolARQuery->where(['bool_col' => true])->onePopulate()->bool_col); + $this->assertFalse($boolARQuery->where(['bool_col' => false])->onePopulate()->bool_col); + + $this->assertEquals(1, $boolARQuery->where('bool_col = TRUE')->count('*')); + $this->assertEquals(1, $boolARQuery->where('bool_col = FALSE')->count('*')); + $this->assertEquals(2, $boolARQuery->where('bool_col IN (TRUE, FALSE)')->count('*')); + + $this->assertEquals(1, $boolARQuery->where(['bool_col' => true])->count('*')); + $this->assertEquals(1, $boolARQuery->where(['bool_col' => false])->count('*')); + $this->assertEquals(2, $boolARQuery->where(['bool_col' => [true, false]])->count('*')); + + $this->assertEquals(1, $boolARQuery->where('bool_col = :bool_col', ['bool_col' => true])->count('*')); + $this->assertEquals(1, $boolARQuery->where('bool_col = :bool_col', ['bool_col' => false])->count('*')); + } + + /** + * {@see https://github.com/yiisoft/yii2/issues/4672} + */ + public function testBooleanValues2(): void + { + $this->checkFixture($this->db, 'bool_user'); + + //$this->db->setCharset('utf8'); + $this->db->createCommand('DROP TABLE IF EXISTS bool_user;')->execute(); + $this->db->createCommand()->createTable('bool_user', [ + 'id' => SchemaPgsql::TYPE_PK, + 'username' => SchemaPgsql::TYPE_STRING . ' NOT NULL', + 'auth_key' => SchemaPgsql::TYPE_STRING . '(32) NOT NULL', + 'password_hash' => SchemaPgsql::TYPE_STRING . ' NOT NULL', + 'password_reset_token' => SchemaPgsql::TYPE_STRING, + 'email' => SchemaPgsql::TYPE_STRING . ' NOT NULL', + 'role' => SchemaPgsql::TYPE_SMALLINT . ' NOT NULL DEFAULT 10', + 'status' => SchemaPgsql::TYPE_SMALLINT . ' NOT NULL DEFAULT 10', + 'created_at' => SchemaPgsql::TYPE_INTEGER . ' NOT NULL', + 'updated_at' => SchemaPgsql::TYPE_INTEGER . ' NOT NULL', + ])->execute(); + $this->db->createCommand()->addColumn( + 'bool_user', + 'is_deleted', + SchemaPgsql::TYPE_BOOLEAN . ' NOT NULL DEFAULT FALSE' + )->execute(); + + $user = new UserAR($this->db); + $user->username = 'test'; + $user->auth_key = 'test'; + $user->password_hash = 'test'; + $user->email = 'test@example.com'; + $user->created_at = time(); + $user->updated_at = time(); + $user->save(); + + $userQuery = new ActiveQuery(UserAR::class, $this->db); + $this->assertCount(1, $userQuery->where(['is_deleted' => false])->all()); + $this->assertCount(0, $userQuery->where(['is_deleted' => true])->all()); + $this->assertCount(1, $userQuery->where(['is_deleted' => [true, false]])->all()); + } + + public function testBooleanDefaultValues(): void + { + $this->checkFixture($this->db, 'bool_values'); + + $arClass = new BoolAR($this->db); + + $this->assertNull($arClass->bool_col); + $this->assertNull($arClass->default_true); + $this->assertNull($arClass->default_false); + + $arClass->loadDefaultValues(); + + $this->assertNull($arClass->bool_col); + $this->assertTrue($arClass->default_true); + $this->assertFalse($arClass->default_false); + $this->assertTrue($arClass->save()); + } + + public function testPrimaryKeyAfterSave(): void + { + $this->checkFixture($this->db, 'default_pk'); + + $record = new DefaultPk($this->db); + + $record->type = 'type'; + + $record->save(); + + $this->assertEquals(5, $record->primaryKey); + } + + public static function arrayValuesProvider(): array + { + return [ + 'simple arrays values' => [[ + 'intarray_col' => [ + new ArrayExpression([1,-2,null,'42'], 'int4', 1), + new ArrayExpression([1,-2,null,42], 'int4', 1), + ], + 'textarray2_col' => [ + new ArrayExpression([['text'], [null], [1]], 'text', 2), + new ArrayExpression([['text'], [null], ['1']], 'text', 2), + ], + 'json_col' => [['a' => 1, 'b' => null, 'c' => [1,3,5]]], + 'jsonb_col' => [[null, 'a', 'b', '\"', '{"af"}']], + 'jsonarray_col' => [new ArrayExpression([[',', 'null', true, 'false', 'f']], 'json')], + ]], + 'null arrays values' => [[ + 'intarray_col' => [ + null, + ], + 'textarray2_col' => [ + [null, null], + new ArrayExpression([null, null], 'text', 2), + ], + 'json_col' => [ + null, + ], + 'jsonarray_col' => [ + null, + ], + ]], + 'empty arrays values' => [[ + 'textarray2_col' => [ + [[], []], + new ArrayExpression([], 'text', 2), + ], + ]], + 'nested objects' => [[ + 'intarray_col' => [ + new ArrayExpression(new ArrayExpression([1,2,3]), 'int', 1), + new ArrayExpression([1,2,3], 'int4', 1), + ], + 'textarray2_col' => [ + new ArrayExpression([new ArrayExpression(['text']), [null], [1]], 'text', 2), + new ArrayExpression([['text'], [null], ['1']], 'text', 2), + ], + 'json_col' => [ + new JsonExpression(new JsonExpression(new JsonExpression(['a' => 1, 'b' => null, 'c' => new JsonExpression([1,3,5])]))), + ['a' => 1, 'b' => null, 'c' => [1,3,5]], + ], + 'jsonb_col' => [ + new JsonExpression(new ArrayExpression([1,2,3])), + [1,2,3], + ], + 'jsonarray_col' => [ + new ArrayExpression([new JsonExpression(['1', 2]), [3,4,5]], 'json'), + new ArrayExpression([['1', 2], [3,4,5]], 'json'), + ], + ]], + 'arrays packed in classes' => [[ + 'intarray_col' => [ + new ArrayExpression([1,-2,null,'42'], 'int', 1), + new ArrayExpression([1,-2,null,42], 'int4', 1), + ], + 'textarray2_col' => [ + new ArrayExpression([['text'], [null], [1]], 'text', 2), + new ArrayExpression([['text'], [null], ['1']], 'text', 2), + ], + 'json_col' => [ + new JsonExpression(['a' => 1, 'b' => null, 'c' => [1,3,5]]), + ['a' => 1, 'b' => null, 'c' => [1,3,5]], + ], + 'jsonb_col' => [ + new JsonExpression([null, 'a', 'b', '\"', '{"af"}']), + [null, 'a', 'b', '\"', '{"af"}'], + ], + 'jsonarray_col' => [ + new Expression("array['[\",\",\"null\",true,\"false\",\"f\"]'::json]::json[]"), + new ArrayExpression([[',', 'null', true, 'false', 'f']], 'json'), + ], + ]], + 'scalars' => [[ + 'json_col' => [ + '5.8', + ], + 'jsonb_col' => [ + M_PI, + ], + ]], + ]; + } + + /** + * @dataProvider arrayValuesProvider + */ + public function testArrayValues($attributes): void + { + $this->checkFixture($this->db, 'array_and_json_types', true); + + $type = new ArrayAndJsonTypes($this->db); + + foreach ($attributes as $attribute => $expected) { + $type->$attribute = $expected[0]; + } + + $type->save(); + + $typeQuery = new ActiveQuery($type::class, $this->db); + + $type = $typeQuery->onePopulate(); + + foreach ($attributes as $attribute => $expected) { + $expected = $expected[1] ?? $expected[0]; + $value = $type->$attribute; + + if ($expected instanceof ArrayExpression) { + $expected = $expected->getValue(); + } + + $this->assertEquals($expected, $value, 'In column ' . $attribute); + + if ($value instanceof ArrayExpression) { + $this->assertInstanceOf(ArrayAccess::class, $value); + $this->assertInstanceOf(Traversable::class, $value); + /** testing arrayaccess */ + foreach ($type->$attribute as $key => $v) { + $this->assertSame($expected[$key], $value[$key]); + } + } + } + + /** Testing update */ + foreach ($attributes as $attribute => $expected) { + $type->markAttributeDirty($attribute); + } + + $this->assertSame(1, $type->update(), 'The record got updated'); + } + + public function testToArray(): void + { + $this->checkFixture($this->db, 'customer', true); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $customer = $customerQuery->findOne(1); + + $this->assertSame( + [ + 'id' => 1, + 'email' => 'user1@example.com', + 'name' => 'user1', + 'address' => 'address1', + 'status' => 1, + 'bool_status' => true, + 'profile_id' => 1, + ], + $customer->toArray(), + ); + } + + public function testToArrayWithClosure(): void + { + $this->checkFixture($this->db, 'customer', true); + + $customerQuery = new ActiveQuery(CustomerClosureField::class, $this->db); + $customer = $customerQuery->findOne(1); + + $this->assertSame( + [ + 'id' => 1, + 'email' => 'user1@example.com', + 'name' => 'user1', + 'address' => 'address1', + 'status' => 'active', + 'bool_status' => true, + 'profile_id' => 1, + ], + $customer->toArray(), + ); + } +} diff --git a/tests/Driver/Sqlite/ActiveRecordTest.php b/tests/Driver/Sqlite/ActiveRecordTest.php index 30ac51608..0d4ecb520 100644 --- a/tests/Driver/Sqlite/ActiveRecordTest.php +++ b/tests/Driver/Sqlite/ActiveRecordTest.php @@ -34,16 +34,16 @@ public function testExplicitPkOnAutoIncrement(): void $customer = new Customer($this->db); - $customer->id = 1337; - $customer->email = 'user1337@example.com'; - $customer->name = 'user1337'; - $customer->address = 'address1337'; + $customer->setId(1337); + $customer->setEmail('user1337@example.com'); + $customer->setName('user1337'); + $customer->setAddress('address1337'); - $this->assertTrue($customer->isNewRecord); + $this->assertTrue($customer->getIsNewRecord()); $customer->save(); - $this->assertEquals(1337, $customer->id); - $this->assertFalse($customer->isNewRecord); + $this->assertEquals(1337, $customer->getId()); + $this->assertFalse($customer->getIsNewRecord()); } /** @@ -63,9 +63,9 @@ public function testEagerLoadingUsingStringIdentifiers(): void /** @var Beta[] $betas */ foreach ($betas as $beta) { - $this->assertNotNull($beta->alpha); - $this->assertEquals($beta->alpha_string_identifier, $beta->alpha->string_identifier); - $alphaIdentifiers[] = $beta->alpha->string_identifier; + $this->assertNotNull($beta->getAlpha()); + $this->assertEquals($beta->getAlphaStringIdentifier(), $beta->getAlpha()->getStringIdentifier()); + $alphaIdentifiers[] = $beta->getAlpha()->getStringIdentifier(); } $this->assertEquals(['1', '01', '001', '001', '2', '2b', '2b', '02'], $alphaIdentifiers); diff --git a/tests/Driver/Sqlite/MagicActiveRecordTest.php b/tests/Driver/Sqlite/MagicActiveRecordTest.php new file mode 100644 index 000000000..fa8dabbd7 --- /dev/null +++ b/tests/Driver/Sqlite/MagicActiveRecordTest.php @@ -0,0 +1,73 @@ +db = $sqliteHelper->createConnection(); + } + + protected function tearDown(): void + { + parent::tearDown(); + + $this->db->close(); + + unset($this->db); + } + + public function testExplicitPkOnAutoIncrement(): void + { + $this->checkFixture($this->db, 'customer', true); + + $customer = new Customer($this->db); + + $customer->id = 1337; + $customer->email = 'user1337@example.com'; + $customer->name = 'user1337'; + $customer->address = 'address1337'; + + $this->assertTrue($customer->isNewRecord); + $customer->save(); + + $this->assertEquals(1337, $customer->id); + $this->assertFalse($customer->isNewRecord); + } + + /** + * {@see https://github.com/yiisoft/yii2/issues/15482} + */ + public function testEagerLoadingUsingStringIdentifiers(): void + { + $this->checkFixture($this->db, 'beta'); + + $betaQuery = new ActiveQuery(Beta::class, $this->db); + + $betas = $betaQuery->with('alpha')->all(); + + $this->assertNotEmpty($betas); + + $alphaIdentifiers = []; + + /** @var Beta[] $betas */ + foreach ($betas as $beta) { + $this->assertNotNull($beta->alpha); + $this->assertEquals($beta->alpha_string_identifier, $beta->alpha->string_identifier); + $alphaIdentifiers[] = $beta->alpha->string_identifier; + } + + $this->assertEquals(['1', '01', '001', '001', '2', '2b', '2b', '02'], $alphaIdentifiers); + } +} diff --git a/tests/MagicActiveRecordTest.php b/tests/MagicActiveRecordTest.php new file mode 100644 index 000000000..093662570 --- /dev/null +++ b/tests/MagicActiveRecordTest.php @@ -0,0 +1,949 @@ +checkFixture($this->db, 'null_values', true); + + $record = new NullValues($this->db); + + $this->assertNull($record->getAttribute('var1')); + $this->assertNull($record->getAttribute('var2')); + $this->assertNull($record->getAttribute('var3')); + $this->assertNull($record->getAttribute('stringcol')); + + $record->setAttribute('var1', 123); + $record->setAttribute('var2', 456); + $record->setAttribute('var3', 789); + $record->setAttribute('stringcol', 'hello!'); + $record->save(); + + $this->assertTrue($record->refresh()); + $this->assertEquals(123, $record->getAttribute('var1')); + $this->assertEquals(456, $record->getAttribute('var2')); + $this->assertEquals(789, $record->getAttribute('var3')); + $this->assertEquals('hello!', $record->getAttribute('stringcol')); + + $record->setAttribute('var1', null); + $record->setAttribute('var2', null); + $record->setAttribute('var3', null); + $record->setAttribute('stringcol', null); + $record->save(); + + $this->assertTrue($record->refresh()); + $this->assertNull($record->getAttribute('var1')); + $this->assertNull($record->getAttribute('var2')); + $this->assertNull($record->getAttribute('var3')); + $this->assertNull($record->getAttribute('>stringcol')); + + $record->setAttribute('var1', 0); + $record->setAttribute('var2', 0); + $record->setAttribute('var3', 0); + $record->setAttribute('stringcol', ''); + $record->save(); + + $this->assertTrue($record->refresh()); + $this->assertEquals(0, $record->getAttribute('var1')); + $this->assertEquals(0, $record->getAttribute('var2')); + $this->assertEquals(0, $record->getAttribute('var3')); + $this->assertEquals('', $record->getAttribute('stringcol')); + } + + public function testStoreEmpty(): void + { + $this->checkFixture($this->db, 'null_values'); + + $record = new NullValues($this->db); + + /** this is to simulate empty html form submission */ + $record->var1 = ''; + $record->var2 = ''; + $record->var3 = ''; + $record->stringcol = ''; + $record->save(); + + $this->assertTrue($record->refresh()); + + /** {@see https://github.com/yiisoft/yii2/commit/34945b0b69011bc7cab684c7f7095d837892a0d4#commitcomment-4458225} */ + $this->assertSame($record->var1, $record->var2); + $this->assertSame($record->var2, $record->var3); + } + + public function testIsPrimaryKey(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new Customer($this->db); + $orderItem = new OrderItem($this->db); + + $this->assertTrue($customer->isPrimaryKey(['id'])); + $this->assertFalse($customer->isPrimaryKey([])); + $this->assertFalse($customer->isPrimaryKey(['id', 'name'])); + $this->assertFalse($customer->isPrimaryKey(['name'])); + $this->assertFalse($customer->isPrimaryKey(['name', 'email'])); + + $this->assertTrue($orderItem->isPrimaryKey(['order_id', 'item_id'])); + $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->assertFalse($orderItem->isPrimaryKey(['order_id', 'item_id', 'quantity'])); + } + + public function testOutdatedRelationsAreResetForNewRecords(): void + { + $this->checkFixture($this->db, 'order_item'); + + $orderItem = new OrderItem($this->db); + + $orderItem->order_id = 1; + $orderItem->item_id = 3; + $this->assertEquals(1, $orderItem->order->id); + $this->assertEquals(3, $orderItem->item->id); + + /** test `__set()`. */ + $orderItem->order_id = 2; + $orderItem->item_id = 1; + $this->assertEquals(2, $orderItem->order->id); + $this->assertEquals(1, $orderItem->item->id); + + /** test `setAttribute()`. */ + $orderItem->setAttribute('order_id', 2); + $orderItem->setAttribute('item_id', 2); + $this->assertEquals(2, $orderItem->order->id); + $this->assertEquals(2, $orderItem->item->id); + } + + public function testDefaultValues(): void + { + $this->checkFixture($this->db, 'type'); + + $arClass = new Type($this->db); + + $arClass->loadDefaultValues(); + + $this->assertEquals(1, $arClass->int_col2); + $this->assertEquals('something', $arClass->char_col2); + $this->assertEquals(1.23, $arClass->float_col2); + $this->assertEquals(33.22, $arClass->numeric_col); + $this->assertEquals(true, $arClass->bool_col2); + $this->assertEquals('2002-01-01 00:00:00', $arClass->time); + + $arClass = new Type($this->db); + $arClass->char_col2 = 'not something'; + + $arClass->loadDefaultValues(); + $this->assertEquals('not something', $arClass->char_col2); + + $arClass = new Type($this->db); + $arClass->char_col2 = 'not something'; + + $arClass->loadDefaultValues(false); + $this->assertEquals('something', $arClass->char_col2); + } + + public function testCastValues(): void + { + $this->checkFixture($this->db, 'type'); + + $arClass = new Type($this->db); + + $arClass->int_col = 123; + $arClass->int_col2 = 456; + $arClass->smallint_col = 42; + $arClass->char_col = '1337'; + $arClass->char_col2 = 'test'; + $arClass->char_col3 = 'test123'; + $arClass->float_col = 3.742; + $arClass->float_col2 = 42.1337; + $arClass->bool_col = true; + $arClass->bool_col2 = false; + + $arClass->save(); + + /** @var $model Type */ + $aqClass = new ActiveQuery(Type::class, $this->db); + $query = $aqClass->onePopulate(); + + $this->assertSame(123, $query->int_col); + $this->assertSame(456, $query->int_col2); + $this->assertSame(42, $query->smallint_col); + $this->assertSame('1337', trim($query->char_col)); + $this->assertSame('test', $query->char_col2); + $this->assertSame('test123', $query->char_col3); + } + + public function testPopulateRecordCallWhenQueryingOnParentClass(): void + { + $this->checkFixture($this->db, 'cat'); + + $cat = new Cat($this->db); + $cat->save(); + + $dog = new Dog($this->db); + $dog->save(); + + $animal = new ActiveQuery(Animal::class, $this->db); + + $animals = $animal->where(['type' => Dog::class])->onePopulate(); + $this->assertEquals('bark', $animals->getDoes()); + + $animals = $animal->where(['type' => Cat::class])->onePopulate(); + $this->assertEquals('meow', $animals->getDoes()); + } + + public function testSaveEmpty(): void + { + $this->checkFixture($this->db, 'null_values', true); + + $record = new NullValues($this->db); + + $this->assertTrue($record->save()); + $this->assertEquals(1, $record->id); + } + + /** + * Verify that {{}} are not going to be replaced in parameters. + */ + public function testNoTablenameReplacement(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new Customer($this->db); + + $customer->name = 'Some {{weird}} name'; + $customer->email = 'test@example.com'; + $customer->address = 'Some {{%weird}} address'; + $customer->insert(); + $customer->refresh(); + + $this->assertEquals('Some {{weird}} name', $customer->name); + $this->assertEquals('Some {{%weird}} address', $customer->address); + + $customer->name = 'Some {{updated}} name'; + $customer->address = 'Some {{%updated}} address'; + $customer->update(); + + $this->assertEquals('Some {{updated}} name', $customer->name); + $this->assertEquals('Some {{%updated}} address', $customer->address); + } + + public static function legalValuesForFindByCondition(): array + { + return [ + [Customer::class, ['id' => 1]], + [Customer::class, ['customer.id' => 1]], + [Customer::class, ['[[id]]' => 1]], + [Customer::class, ['{{customer}}.[[id]]' => 1]], + [Customer::class, ['{{%customer}}.[[id]]' => 1]], + [CustomerWithAlias::class, ['id' => 1]], + [CustomerWithAlias::class, ['customer.id' => 1]], + [CustomerWithAlias::class, ['[[id]]' => 1]], + [CustomerWithAlias::class, ['{{customer}}.[[id]]' => 1]], + [CustomerWithAlias::class, ['{{%customer}}.[[id]]' => 1]], + [CustomerWithAlias::class, ['csr.id' => 1], 'csr'], + [CustomerWithAlias::class, ['{{csr}}.[[id]]' => 1], 'csr'], + ]; + } + + /** + * @dataProvider legalValuesForFindByCondition + * + * @throws ReflectionException + */ + public function testLegalValuesForFindByCondition( + string $modelClassName, + array $validFilter, + ?string $alias = null + ): void { + $this->checkFixture($this->db, 'customer'); + + $activeQuery = new ActiveQuery($modelClassName, $this->db); + + if ($alias !== null) { + $activeQuery->alias('csr'); + } + + /** @var Query $query */ + $query = Assert::invokeMethod($activeQuery, 'findByCondition', [$validFilter]); + + + $this->db->getQueryBuilder()->build($query); + + $this->assertTrue(true); + } + + public static function illegalValuesForFindByCondition(): array + { + return [ + [Customer::class, [['`id`=`id` and 1' => 1]]], + [Customer::class, [[ + 'legal' => 1, + '`id`=`id` and 1' => 1, + ]]], + [Customer::class, [[ + 'nested_illegal' => [ + 'false or 1=' => 1, + ], + ]]], + [Customer::class, [['true--' => 1]]], + + [CustomerWithAlias::class, [['`csr`.`id`=`csr`.`id` and 1' => 1]]], + [CustomerWithAlias::class, [[ + 'legal' => 1, + '`csr`.`id`=`csr`.`id` and 1' => 1, + ]]], + [CustomerWithAlias::class, [[ + 'nested_illegal' => [ + 'false or 1=' => 1, + ], + ]]], + [CustomerWithAlias::class, [['true--' => 1]]], + ]; + } + + /** + * @dataProvider illegalValuesForFindByCondition + * + * @throws ReflectionException + */ + public function testValueEscapingInFindByCondition(string $modelClassName, array $filterWithInjection): void + { + $this->checkFixture($this->db, 'customer'); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessageMatches( + '/^Key "(.+)?" is not a column name and can not be used as a filter$/' + ); + + $query = new ActiveQuery($modelClassName, $this->db); + + /** @var Query $query */ + $query = Assert::invokeMethod($query, 'findByCondition', $filterWithInjection); + + $this->db->getQueryBuilder()->build($query); + } + + public function testRefreshQuerySetAliasFindRecord(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new CustomerWithAlias($this->db); + + $customer->id = 1; + $customer->refresh(); + + $this->assertEquals(1, $customer->id); + } + + public function testResetNotSavedRelation(): void + { + $this->checkFixture($this->db, 'order'); + + $order = new Order($this->db); + + $order->customer_id = 1; + $order->created_at = 1_325_502_201; + $order->total = 0; + + $orderItem = new OrderItem($this->db); + + $order->orderItems; + + $order->populateRelation('orderItems', [$orderItem]); + + $order->save(); + + $this->assertCount(1, $order->orderItems); + } + + public function testIssetException(): void + { + $this->checkFixture($this->db, 'cat'); + + $cat = new Cat($this->db); + + $this->expectException(Exception::class); + isset($cat->exception); + } + + public function testIssetThrowable(): void + { + $this->checkFixture($this->db, 'cat'); + + $cat = new Cat($this->db); + + $this->expectException(DivisionByZeroError::class); + isset($cat->throwable); + } + + public function testIssetNonExisting(): void + { + $this->checkFixture($this->db, 'cat'); + + $cat = new Cat($this->db); + + $this->assertFalse(isset($cat->non_existing)); + $this->assertFalse(isset($cat->non_existing_property)); + } + + public function testSetAttributes(): void + { + $attributes = []; + $this->checkFixture($this->db, 'customer'); + + $attributes['email'] = 'samdark@mail.ru'; + $attributes['name'] = 'samdark'; + $attributes['address'] = 'rusia'; + $attributes['status'] = 1; + + if ($this->db->getDriverName() === 'pgsql') { + $attributes['bool_status'] = true; + } + + $attributes['profile_id'] = null; + + $customer = new Customer($this->db); + + $customer->setAttributes($attributes); + + $this->assertTrue($customer->save()); + } + + public function testSetAttributeNoExist(): void + { + $this->checkFixture($this->db, 'cat'); + + $cat = new Cat($this->db); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\Cat has no attribute named "noExist"' + ); + + $cat->setAttribute('noExist', 1); + } + + public function testSetOldAttribute(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new Customer($this->db); + + $this->assertEmpty($customer->getOldAttribute('name')); + + $customer->setOldAttribute('name', 'samdark'); + + $this->assertEquals('samdark', $customer->getOldAttribute('name')); + } + + public function testSetOldAttributeException(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new Customer($this->db); + + $this->assertEmpty($customer->getOldAttribute('name')); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord\Customer has no attribute named "noExist"' + ); + $customer->setOldAttribute('noExist', 'samdark'); + } + + public function testIsAttributeChangedNotChanged(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new Customer($this->db); + + $this->assertEmpty($customer->getAttribute('name')); + $this->assertEmpty($customer->getOldAttribute('name')); + $this->assertFalse($customer->isAttributeChanged('name', false)); + } + + public function testTableSchemaException(): void + { + $noExist = new NoExist($this->db); + + $this->expectException(InvalidConfigException::class); + $this->expectExceptionMessage('The table does not exist: NoExist'); + $noExist->getTableSchema(); + } + + public function testInsert(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new Customer($this->db); + + $customer->email = 'user4@example.com'; + $customer->name = 'user4'; + $customer->address = 'address4'; + + $this->assertNull($customer->id); + $this->assertTrue($customer->isNewRecord); + + $customer->save(); + + $this->assertNotNull($customer->id); + $this->assertFalse($customer->isNewRecord); + } + + /** + * Some PDO implementations (e.g. cubrid) do not support boolean values. + * + * Make sure this does not affect AR layer. + */ + public function testBooleanAttribute(): void + { + $this->checkFixture($this->db, 'customer', true); + + $customer = new Customer($this->db); + + $customer->name = 'boolean customer'; + $customer->email = 'mail@example.com'; + $customer->status = true; + + $customer->save(); + $customer->refresh(); + $this->assertEquals(1, $customer->status); + + $customer->status = false; + $customer->save(); + + $customer->refresh(); + $this->assertEquals(0, $customer->status); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $customers = $customerQuery->where(['status' => true])->all(); + $this->assertCount(2, $customers); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $customers = $customerQuery->where(['status' => false])->all(); + $this->assertCount(1, $customers); + } + + public function testAttributeAccess(): void + { + $this->checkFixture($this->db, 'customer'); + + $arClass = new Customer($this->db); + + $this->assertTrue($arClass->canSetProperty('name')); + $this->assertTrue($arClass->canGetProperty('name')); + $this->assertFalse($arClass->canSetProperty('unExistingColumn')); + $this->assertFalse(isset($arClass->name)); + + $arClass->name = 'foo'; + $this->assertTrue(isset($arClass->name)); + + unset($arClass->name); + $this->assertNull($arClass->name); + + /** {@see https://github.com/yiisoft/yii2-gii/issues/190} */ + $baseModel = new Customer($this->db); + $this->assertFalse($baseModel->hasProperty('unExistingColumn')); + + $customer = new Customer($this->db); + $this->assertInstanceOf(Customer::class, $customer); + $this->assertTrue($customer->canGetProperty('id')); + $this->assertTrue($customer->canSetProperty('id')); + + /** tests that we really can get and set this property */ + $this->assertNull($customer->id); + $customer->id = 10; + $this->assertNotNull($customer->id); + + /** Let's test relations */ + $this->assertTrue($customer->canGetProperty('orderItems')); + $this->assertFalse($customer->canSetProperty('orderItems')); + + /** Newly created model must have empty relation */ + $this->assertSame([], $customer->orderItems); + + /** does it still work after accessing the relation? */ + $this->assertTrue($customer->canGetProperty('orderItems')); + $this->assertFalse($customer->canSetProperty('orderItems')); + + $this->expectException(InvalidCallException::class); + $this->expectExceptionMessage('Setting read-only property: ' . Customer::class . '::orderItems'); + $customer->orderItems = [new Item($this->db)]; + + /** related attribute $customer->orderItems didn't change cause it's read-only */ + $this->assertSame([], $customer->orderItems); + $this->assertFalse($customer->canGetProperty('non_existing_property')); + $this->assertFalse($customer->canSetProperty('non_existing_property')); + + $this->expectException(UnknownPropertyException::class); + $this->expectExceptionMessage('Setting unknown property: ' . Customer::class . '::non_existing_property'); + $customer->non_existing_property = null; + } + + public function testHasAttribute(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new Customer($this->db); + + $this->assertTrue($customer->hasAttribute('id')); + $this->assertTrue($customer->hasAttribute('email')); + $this->assertFalse($customer->hasAttribute('notExist')); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $customer = $customerQuery->findOne(1); + $this->assertTrue($customer->hasAttribute('id')); + $this->assertTrue($customer->hasAttribute('email')); + $this->assertFalse($customer->hasAttribute('notExist')); + } + + public function testRefresh(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new Customer($this->db); + + $this->assertFalse($customer->refresh()); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $customer = $customerQuery->findOne(1); + $customer->name = 'to be refreshed'; + + $this->assertTrue($customer->refresh()); + $this->assertEquals('user1', $customer->name); + } + + public function testEquals(): void + { + $this->checkFixture($this->db, 'customer'); + + $customerA = new Customer($this->db); + $customerB = new Customer($this->db); + $this->assertFalse($customerA->equals($customerB)); + + $customerA = new Customer($this->db); + $customerB = new Item($this->db); + $this->assertFalse($customerA->equals($customerB)); + } + + public static function providerForUnlinkDelete() + { + return [ + 'with delete' => [true, 0], + 'without delete' => [false, 1], + ]; + } + + /** + * @dataProvider providerForUnlinkDelete + * + * @see https://github.com/yiisoft/yii2/issues/17174 + */ + public function testUnlinkWithViaOnCondition($delete, $count) + { + $this->checkFixture($this->db, 'order', true); + $this->checkFixture($this->db, 'order_item_with_null_fk', true); + + $orderQuery = new ActiveQuery(Order::class, $this->db); + $order = $orderQuery->findOne(2); + + $this->assertCount(1, $order->itemsFor8); + $order->unlink('itemsFor8', $order->itemsFor8[0], $delete); + + $order = $orderQuery->findOne(2); + $this->assertCount(0, $order->itemsFor8); + $this->assertCount(2, $order->orderItemsWithNullFK); + + $orderItemQuery = new ActiveQuery(OrderItemWithNullFK::class, $this->db); + $this->assertCount(1, $orderItemQuery->findAll([ + 'order_id' => 2, + 'item_id' => 5, + ])); + $this->assertCount($count, $orderItemQuery->findAll([ + 'order_id' => null, + 'item_id' => null, + ])); + } + + public function testVirtualRelation() + { + $this->checkFixture($this->db, 'order', true); + + $orderQuery = new ActiveQuery(Order::class, $this->db); + /** @var Order $order */ + $order = $orderQuery->findOne(2); + + $order->setVirtualCustomerId($order->customer_id); + $this->assertNotNull($order->getVirtualCustomerQuery()); + } + + /** + * Test joinWith eager loads via relation + * + * @see https://github.com/yiisoft/yii2/issues/19507 + */ + public function testJoinWithEager() + { + $this->checkFixture($this->db, 'customer', true); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $eagerCustomers = $customerQuery->joinWith(['items2'])->all(); + $eagerItemsCount = 0; + foreach ($eagerCustomers as $customer) { + $eagerItemsCount += is_countable($customer->items2) ? count($customer->items2) : 0; + } + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $lazyCustomers = $customerQuery->all(); + $lazyItemsCount = 0; + foreach ($lazyCustomers as $customer) { + $lazyItemsCount += is_countable($customer->items2) ? count($customer->items2) : 0; + } + + $this->assertEquals($eagerItemsCount, $lazyItemsCount); + } + + public function testToArray(): void + { + $this->checkFixture($this->db, 'customer', true); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $customer = $customerQuery->findOne(1); + + $this->assertSame( + [ + 'id' => 1, + 'email' => 'user1@example.com', + 'name' => 'user1', + 'address' => 'address1', + 'status' => 1, + 'profile_id' => 1, + ], + $customer->toArray(), + ); + } + + public function testToArrayWithClosure(): void + { + $this->checkFixture($this->db, 'customer', true); + + $customerQuery = new ActiveQuery(CustomerClosureField::class, $this->db); + $customer = $customerQuery->findOne(1); + + $this->assertSame( + [ + 'id' => 1, + 'email' => 'user1@example.com', + 'name' => 'user1', + 'address' => 'address1', + 'status' => 'active', + 'profile_id' => 1, + ], + $customer->toArray(), + ); + } + + public function testToArrayForArrayable(): void + { + $this->checkFixture($this->db, 'customer', true); + + $customerQuery = new ActiveQuery(CustomerForArrayable::class, $this->db); + + /** @var CustomerForArrayable $customer */ + $customer = $customerQuery->findOne(1); + /** @var CustomerForArrayable $customer2 */ + $customer2 = $customerQuery->findOne(2); + /** @var CustomerForArrayable $customer3 */ + $customer3 = $customerQuery->findOne(3); + + $customer->setItem($customer2); + $customer->setItems($customer3); + + $this->assertSame( + [ + 'id' => 1, + 'email' => 'user1@example.com', + 'name' => 'user1', + 'address' => 'address1', + 'status' => 'active', + 'item' => [ + 'id' => 2, + 'email' => 'user2@example.com', + 'name' => 'user2', + 'status' => 'active', + ], + 'items' => [ + [ + 'id' => 3, + 'email' => 'user3@example.com', + 'name' => 'user3', + 'status' => 'inactive', + ], + ], + ], + $customer->toArray([ + 'id', + 'name', + 'email', + 'address', + 'status', + 'item.id', + 'item.name', + 'item.email', + 'items.0.id', + 'items.0.name', + 'items.0.email', + ]), + ); + } + + public function testSaveWithoutChanges(): void + { + $this->checkFixture($this->db, 'customer'); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + + $customer = $customerQuery->findOne(1); + + $this->assertTrue($customer->save()); + } + + public function testGetPrimaryKey(): void + { + $this->checkFixture($this->db, 'customer'); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + + $customer = $customerQuery->findOne(1); + + $this->assertSame(1, $customer->getPrimaryKey()); + $this->assertSame(['id' => 1], $customer->getPrimaryKey(true)); + } + + public function testGetOldPrimaryKey(): void + { + $this->checkFixture($this->db, 'customer'); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + + $customer = $customerQuery->findOne(1); + $customer->id = 2; + + $this->assertSame(1, $customer->getOldPrimaryKey()); + $this->assertSame(['id' => 1], $customer->getOldPrimaryKey(true)); + } + + public function testGetDirtyAttributesOnNewRecord(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new Customer($this->db); + + $this->assertSame([], $customer->getDirtyAttributes()); + + $customer->setAttribute('name', 'Adam'); + $customer->setAttribute('email', 'adam@example.com'); + $customer->setAttribute('address', null); + + $this->assertEquals( + ['name' => 'Adam', 'email' => 'adam@example.com', 'address' => null], + $customer->getDirtyAttributes() + ); + $this->assertEquals( + ['email' => 'adam@example.com', 'address' => null], + $customer->getDirtyAttributes(['id', 'email', 'address', 'status', 'unknown']), + ); + + $this->assertTrue($customer->save()); + $this->assertSame([], $customer->getDirtyAttributes()); + + $customer->setAttribute('address', ''); + + $this->assertSame(['address' => ''], $customer->getDirtyAttributes()); + } + + public function testGetDirtyAttributesAfterFind(): void + { + $this->checkFixture($this->db, 'customer'); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $customer = $customerQuery->findOne(1); + + $this->assertSame([], $customer->getDirtyAttributes()); + + $customer->setAttribute('name', 'Adam'); + $customer->setAttribute('email', 'adam@example.com'); + $customer->setAttribute('address', null); + + $this->assertEquals( + ['name' => 'Adam', 'email' => 'adam@example.com', 'address' => null], + $customer->getDirtyAttributes(), + ); + $this->assertEquals( + ['email' => 'adam@example.com', 'address' => null], + $customer->getDirtyAttributes(['id', 'email', 'address', 'status', 'unknown']), + ); + } + + public function testGetDirtyAttributesWithProperties(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new CustomerWithProperties($this->db); + $this->assertSame([ + 'name' => null, + 'address' => null, + ], $customer->getDirtyAttributes()); + + $customerQuery = new ActiveQuery(CustomerWithProperties::class, $this->db); + $customer = $customerQuery->findOne(1); + + $this->assertSame([], $customer->getDirtyAttributes()); + + $customer->setEmail('adam@example.com'); + $customer->setName('Adam'); + $customer->setAddress(null); + $customer->setStatus(null); + + $this->assertEquals( + ['email' => 'adam@example.com', 'name' => 'Adam', 'address' => null, 'status' => null], + $customer->getDirtyAttributes(), + ); + $this->assertEquals( + ['email' => 'adam@example.com', 'address' => null], + $customer->getDirtyAttributes(['id', 'email', 'address', 'unknown']), + ); + } +} diff --git a/tests/Stubs/ActiveRecord/Alpha.php b/tests/Stubs/ActiveRecord/Alpha.php index 16f89e409..3977df7e7 100644 --- a/tests/Stubs/ActiveRecord/Alpha.php +++ b/tests/Stubs/ActiveRecord/Alpha.php @@ -5,6 +5,7 @@ namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; use Yiisoft\ActiveRecord\ActiveQuery; +use Yiisoft\ActiveRecord\ActiveQueryInterface; use Yiisoft\ActiveRecord\ActiveRecord; /** @@ -15,11 +16,38 @@ final class Alpha extends ActiveRecord { public const TABLE_NAME = 'alpha'; + protected int $id; + + protected string $string_identifier; + public function getTableName(): string { return self::TABLE_NAME; } + public function getId(): int + { + return $this->id; + } + + public function getStringIdentifier(): string + { + return $this->string_identifier; + } + + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'betas' => $this->getBetasQuery(), + default => parent::relationQuery($name), + }; + } + + public function getBetas(): array|null + { + return $this->relation('betas'); + } + public function getBetasQuery(): ActiveQuery { return $this->hasMany(Beta::class, ['alpha_string_identifier' => 'string_identifier']); diff --git a/tests/Stubs/ActiveRecord/Animal.php b/tests/Stubs/ActiveRecord/Animal.php index 35a68679e..4cd25bfd1 100644 --- a/tests/Stubs/ActiveRecord/Animal.php +++ b/tests/Stubs/ActiveRecord/Animal.php @@ -18,6 +18,9 @@ class Animal extends ActiveRecord { private string $does; + protected int $id; + protected string $type; + public function getTableName(): string { return 'animal'; diff --git a/tests/Stubs/ActiveRecord/Beta.php b/tests/Stubs/ActiveRecord/Beta.php index 1bed7a3fd..1a049c1c3 100644 --- a/tests/Stubs/ActiveRecord/Beta.php +++ b/tests/Stubs/ActiveRecord/Beta.php @@ -5,6 +5,7 @@ namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; use Yiisoft\ActiveRecord\ActiveQuery; +use Yiisoft\ActiveRecord\ActiveQueryInterface; use Yiisoft\ActiveRecord\ActiveRecord; /** @@ -14,11 +15,38 @@ */ final class Beta extends ActiveRecord { + protected int $id; + protected string $alpha_string_identifier; + protected Alpha $alpha; + public function getTableName(): string { return 'beta'; } + public function getId(): int + { + return $this->id; + } + + public function getAlphaStringIdentifier(): string + { + return $this->alpha_string_identifier; + } + + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'alpha' => $this->getAlphaQuery(), + default => parent::relationQuery($name), + }; + } + + public function getAlpha(): Alpha|null + { + return $this->relation('alpha'); + } + public function getAlphaQuery(): ActiveQuery { return $this->hasOne(Alpha::class, ['string_identifier' => 'alpha_string_identifier']); diff --git a/tests/Stubs/ActiveRecord/BitValues.php b/tests/Stubs/ActiveRecord/BitValues.php index 2c5a0a8c4..d9fd60311 100644 --- a/tests/Stubs/ActiveRecord/BitValues.php +++ b/tests/Stubs/ActiveRecord/BitValues.php @@ -10,8 +10,10 @@ * {@see https://github.com/yiisoft/yii2/issues/9006} * * @property int $id - * @property int $val + * @property bool $val */ final class BitValues extends ActiveRecord { + public int $id; + public bool $val; } diff --git a/tests/Stubs/ActiveRecord/BoolAR.php b/tests/Stubs/ActiveRecord/BoolAR.php index b1d612437..058f6bd1c 100644 --- a/tests/Stubs/ActiveRecord/BoolAR.php +++ b/tests/Stubs/ActiveRecord/BoolAR.php @@ -8,6 +8,11 @@ final class BoolAR extends ActiveRecord { + public int $id; + public bool|null $bool_col = null; + public bool $default_true = true; + public bool $default_false = false; + public function getTableName(): string { return 'bool_values'; diff --git a/tests/Stubs/ActiveRecord/Category.php b/tests/Stubs/ActiveRecord/Category.php index 5b6368d11..49e4c1561 100644 --- a/tests/Stubs/ActiveRecord/Category.php +++ b/tests/Stubs/ActiveRecord/Category.php @@ -5,6 +5,7 @@ namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; use Yiisoft\ActiveRecord\ActiveQuery; +use Yiisoft\ActiveRecord\ActiveQueryInterface; use Yiisoft\ActiveRecord\ActiveRecord; /** @@ -15,26 +16,75 @@ */ final class Category extends ActiveRecord { + protected int|null $id; + protected string $name; + public function getTableName(): string { return 'category'; } + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'items' => $this->getItemsQuery(), + 'limitedItems' => $this->getLimitedItemsQuery(), + 'orderItems' => $this->getOrderItemsQuery(), + 'orders' => $this->getOrdersQuery(), + default => parent::relationQuery($name), + }; + } + + public function getId(): int|null + { + return $this->id; + } + + public function getName(): string + { + return $this->name; + } + + public function setId(int|null $id): void + { + $this->setAttribute('id', $id); + } + + public function getLimitedItems(): array + { + return $this->relation('limitedItems'); + } + public function getLimitedItemsQuery(): ActiveQuery { return $this->hasMany(Item::class, ['category_id' => 'id'])->onCondition(['item.id' => [1, 2, 3]]); } + public function getItems(): array + { + return $this->relation('items'); + } + public function getItemsQuery(): ActiveQuery { return $this->hasMany(Item::class, ['category_id' => 'id']); } + public function getOrderItems(): array + { + return $this->relation('orderItems'); + } + public function getOrderItemsQuery(): ActiveQuery { return $this->hasMany(OrderItem::class, ['item_id' => 'id'])->via('items'); } + public function getOrders(): array + { + return $this->relation('orders'); + } + public function getOrdersQuery(): ActiveQuery { return $this->hasMany(Order::class, ['id' => 'order_id'])->via('orderItems'); diff --git a/tests/Stubs/ActiveRecord/Customer.php b/tests/Stubs/ActiveRecord/Customer.php index 360ea5508..713ad9eb8 100644 --- a/tests/Stubs/ActiveRecord/Customer.php +++ b/tests/Stubs/ActiveRecord/Customer.php @@ -5,6 +5,7 @@ namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; use Yiisoft\ActiveRecord\ActiveQuery; +use Yiisoft\ActiveRecord\ActiveQueryInterface; use Yiisoft\ActiveRecord\ActiveRecord; /** @@ -23,6 +24,13 @@ class Customer extends ActiveRecord public const STATUS_ACTIVE = 1; public const STATUS_INACTIVE = 2; + protected int $id; + protected string $email; + protected string|null $name = null; + protected string|null $address = null; + protected int|null $status = 0; + protected int|null $profile_id = null; + /** * @var int|string */ @@ -37,9 +45,88 @@ public function getTableName(): string return 'customer'; } - public function getName(): string + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'profile' => $this->getProfileQuery(), + 'orders' => $this->getOrdersQuery(), + 'ordersPlain' => $this->getOrdersPlainQuery(), + 'ordersNoOrder' => $this->getOrdersNoOrderQuery(), + 'expensiveOrders' => $this->getExpensiveOrdersQuery(), + 'ordersWithItems' => $this->getOrdersWithItemsQuery(), + 'expensiveOrdersWithNullFK' => $this->getExpensiveOrdersWithNullFKQuery(), + 'ordersWithNullFK' => $this->getOrdersWithNullFKQuery(), + 'orders2' => $this->getOrders2Query(), + 'orderItems' => $this->getOrderItemsQuery(), + 'orderItems2' => $this->getOrderItems2Query(), + 'items2' => $this->getItems2Query(), + default => parent::relationQuery($name), + }; + } + + public function getId(): int + { + return $this->id; + } + + public function getEmail(): string + { + return $this->email; + } + + public function getName(): string|null + { + return $this->name; + } + + public function getAddress(): string|null + { + return $this->address; + } + + public function getStatus(): int|null + { + return $this->status; + } + + public function getProfileId(): int|null + { + return $this->profile_id; + } + + public function setId(int $id): void + { + $this->id = $id; + } + + public function setEmail(string $email): void + { + $this->email = $email; + } + + public function setName(string|null $name): void + { + $this->name = $name; + } + + public function setAddress(string|null $address): void + { + $this->address = $address; + } + + public function setStatus(int|null $status): void + { + $this->status = $status; + } + + public function setProfileId(int|null $profile_id): void + { + $this->setAttribute('profile_id', $profile_id); + } + + public function getProfile(): Profile|null { - return $this->getAttribute('name'); + return $this->relation('profile'); } public function getProfileQuery(): ActiveQuery @@ -47,35 +134,65 @@ public function getProfileQuery(): ActiveQuery return $this->hasOne(Profile::class, ['id' => 'profile_id']); } + public function getOrdersPlain(): array + { + return $this->relation('ordersPlain'); + } + public function getOrdersPlainQuery(): ActiveQuery { return $this->hasMany(Order::class, ['customer_id' => 'id']); } + public function getOrders(): array + { + return $this->relation('orders'); + } + public function getOrdersQuery(): ActiveQuery { return $this->hasMany(Order::class, ['customer_id' => 'id'])->orderBy('[[id]]'); } + public function getOrdersNoOrder(): array + { + return $this->relation('ordersNoOrder'); + } + public function getOrdersNoOrderQuery(): ActiveQuery { return $this->hasMany(Order::class, ['customer_id' => 'id']); } + public function getExpensiveOrders(): array + { + return $this->relation('expensiveOrders'); + } + public function getExpensiveOrdersQuery(): ActiveQuery { return $this->hasMany(Order::class, ['customer_id' => 'id'])->andWhere('[[total]] > 50')->orderBy('id'); } - public function getItemQuery(): void + public function getItem(): void { } + public function getOrdersWithItems(): array + { + return $this->relation('ordersWithItems'); + } + public function getOrdersWithItemsQuery(): ActiveQuery { return $this->hasMany(Order::class, ['customer_id' => 'id'])->with('orderItems'); } + public function getExpensiveOrdersWithNullFK(): array + { + return $this->relation('expensiveOrdersWithNullFK'); + } + public function getExpensiveOrdersWithNullFKQuery(): ActiveQuery { return $this->hasMany( @@ -84,16 +201,31 @@ public function getExpensiveOrdersWithNullFKQuery(): ActiveQuery )->andWhere('[[total]] > 50')->orderBy('id'); } + public function getOrdersWithNullFK(): array + { + return $this->relation('ordersWithNullFK'); + } + public function getOrdersWithNullFKQuery(): ActiveQuery { return $this->hasMany(OrderWithNullFK::class, ['customer_id' => 'id'])->orderBy('id'); } + public function getOrders2(): array + { + return $this->relation('orders2'); + } + public function getOrders2Query(): ActiveQuery { return $this->hasMany(Order::class, ['customer_id' => 'id'])->inverseOf('customer2')->orderBy('id'); } + public function getOrderItems(): array + { + return $this->relation('orderItems'); + } + /** deeply nested table relation */ public function getOrderItemsQuery(): ActiveQuery { @@ -105,8 +237,9 @@ public function getOrderItemsQuery(): ActiveQuery })->orderBy('id'); } - public function setOrdersReadOnly(): void + public function getOrderItems2(): array { + return $this->relation('orderItems2'); } public function getOrderItems2Query(): ActiveQuery @@ -115,6 +248,11 @@ public function getOrderItems2Query(): ActiveQuery ->via('ordersNoOrder'); } + public function getItems2(): array + { + return $this->relation('items2'); + } + public function getItems2Query(): ActiveQuery { return $this->hasMany(Item::class, ['id' => 'item_id']) diff --git a/tests/Stubs/ActiveRecord/CustomerClosureField.php b/tests/Stubs/ActiveRecord/CustomerClosureField.php index ca5220a96..984766321 100644 --- a/tests/Stubs/ActiveRecord/CustomerClosureField.php +++ b/tests/Stubs/ActiveRecord/CustomerClosureField.php @@ -8,15 +8,16 @@ /** * Class CustomerClosureField. - * - * @property int $id - * @property string $name - * @property string $email - * @property string $address - * @property int $status */ final class CustomerClosureField extends ActiveRecord { + protected int $id; + protected string $name; + protected string $email; + protected string $address; + protected int $status; + protected int|null $profile_id; + public function getTableName(): string { return 'customer'; diff --git a/tests/Stubs/ActiveRecord/CustomerForArrayable.php b/tests/Stubs/ActiveRecord/CustomerForArrayable.php index 591cd79cf..3a8c32fe0 100644 --- a/tests/Stubs/ActiveRecord/CustomerForArrayable.php +++ b/tests/Stubs/ActiveRecord/CustomerForArrayable.php @@ -8,12 +8,6 @@ /** * Class CustomerClosureField. - * - * @property int $id - * @property string $name - * @property string $email - * @property string $address - * @property int $status */ class CustomerForArrayable extends ActiveRecord { @@ -21,6 +15,13 @@ class CustomerForArrayable extends ActiveRecord public ?CustomerForArrayable $item = null; + protected int $id; + protected string $name; + protected string $email; + protected string $address; + protected int $status; + protected int|null $profile_id; + public function getTableName(): string { return 'customer'; diff --git a/tests/Stubs/ActiveRecord/CustomerWithAlias.php b/tests/Stubs/ActiveRecord/CustomerWithAlias.php index bb1914f6c..4ba1fa18e 100644 --- a/tests/Stubs/ActiveRecord/CustomerWithAlias.php +++ b/tests/Stubs/ActiveRecord/CustomerWithAlias.php @@ -9,12 +9,6 @@ /** * Class Customer. * - * @property int $id - * @property string $name - * @property string $email - * @property string $address - * @property int $status - * * @method CustomerQuery findBySql($sql, $params = []) static */ final class CustomerWithAlias extends ActiveRecord @@ -25,6 +19,13 @@ final class CustomerWithAlias extends ActiveRecord public int $status2; public float $sumTotal; + public int $id; + public string $name; + public string $email; + public string $address; + public int $status; + public int|null $profile_id; + public function getTableName(): string { return 'customer'; diff --git a/tests/Stubs/ActiveRecord/CustomerWithConstructor.php b/tests/Stubs/ActiveRecord/CustomerWithConstructor.php index 64f198392..678f93c70 100644 --- a/tests/Stubs/ActiveRecord/CustomerWithConstructor.php +++ b/tests/Stubs/ActiveRecord/CustomerWithConstructor.php @@ -5,6 +5,7 @@ namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; use Yiisoft\ActiveRecord\ActiveQuery; +use Yiisoft\ActiveRecord\ActiveQueryInterface; use Yiisoft\ActiveRecord\ActiveRecord; use Yiisoft\Aliases\Aliases; use Yiisoft\Db\Connection\ConnectionInterface; @@ -17,10 +18,16 @@ * @property string $email * @property string $address * @property int $status - * @property ProfileWithConstructor $profile */ final class CustomerWithConstructor extends ActiveRecord { + protected int $id; + protected string $name; + protected string $email; + protected string $address; + protected int $status; + protected int $profile_id; + public function __construct(ConnectionInterface $db, private Aliases $aliases) { parent::__construct($db); @@ -31,6 +38,19 @@ public function getTableName(): string return 'customer'; } + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'profile' => $this->getProfileQuery(), + default => parent::relationQuery($name), + }; + } + + public function getProfile(): Profile|null + { + return $this->relation('profile'); + } + public function getProfileQuery(): ActiveQuery { return $this->hasOne(Profile::class, ['id' => 'profile_id']); diff --git a/tests/Stubs/ActiveRecord/DefaultPk.php b/tests/Stubs/ActiveRecord/DefaultPk.php index 73cae8e7e..7565a1f29 100644 --- a/tests/Stubs/ActiveRecord/DefaultPk.php +++ b/tests/Stubs/ActiveRecord/DefaultPk.php @@ -8,6 +8,9 @@ final class DefaultPk extends ActiveRecord { + public int $id; + public string $type; + public function getTableName(): string { return 'default_pk'; diff --git a/tests/Stubs/ActiveRecord/Department.php b/tests/Stubs/ActiveRecord/Department.php index 32fd4f8e2..c8a275685 100644 --- a/tests/Stubs/ActiveRecord/Department.php +++ b/tests/Stubs/ActiveRecord/Department.php @@ -5,22 +5,34 @@ namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; use Yiisoft\ActiveRecord\ActiveQuery; +use Yiisoft\ActiveRecord\ActiveQueryInterface; use Yiisoft\ActiveRecord\ActiveRecord; +use Yiisoft\ActiveRecord\ActiveRecordInterface; /** * Class Department * * @property int $id * @property string $title - * @property Employee[] $employees */ final class Department extends ActiveRecord { + protected int $id; + protected string $title; + public function getTableName(): string { return 'department'; } + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'employees' => $this->getEmployeesQuery(), + default => parent::relationQuery($name), + }; + } + public function getEmployeesQuery(): ActiveQuery { return $this->hasMany( @@ -30,4 +42,9 @@ public function getEmployeesQuery(): ActiveQuery ] )->inverseOf('department'); } + + public function getEmployees(): ActiveRecordInterface + { + return $this->relation('employees'); + } } diff --git a/tests/Stubs/ActiveRecord/Document.php b/tests/Stubs/ActiveRecord/Document.php index 4ba1f7a2e..8eb7cddd2 100644 --- a/tests/Stubs/ActiveRecord/Document.php +++ b/tests/Stubs/ActiveRecord/Document.php @@ -15,6 +15,12 @@ */ final class Document extends ActiveRecord { + public int $id; + public string $title; + public string $content; + public int $version; + public array $properties; + public function optimisticLock(): ?string { return 'version'; diff --git a/tests/Stubs/ActiveRecord/Dossier.php b/tests/Stubs/ActiveRecord/Dossier.php index fb6851850..bf4a7b6da 100644 --- a/tests/Stubs/ActiveRecord/Dossier.php +++ b/tests/Stubs/ActiveRecord/Dossier.php @@ -5,6 +5,7 @@ namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; use Yiisoft\ActiveRecord\ActiveQuery; +use Yiisoft\ActiveRecord\ActiveQueryInterface; use Yiisoft\ActiveRecord\ActiveRecord; /** @@ -14,15 +15,72 @@ * @property int $department_id * @property int $employee_id * @property string $summary - * @property Employee $employee */ final class Dossier extends ActiveRecord { + protected int $id; + protected int $department_id; + protected int $employee_id; + protected string $summary; + public function getTableName(): string { return 'dossier'; } + public function getId(): int + { + return $this->id; + } + + public function getDepartmentId(): int + { + return $this->department_id; + } + + public function getEmployeeId(): int + { + return $this->employee_id; + } + + public function getSummary(): string + { + return $this->summary; + } + + public function setId(int $id): void + { + $this->id = $id; + } + + public function setDepartmentId(int $departmentId): void + { + $this->setAttribute('department_id', $departmentId); + } + + public function setEmployeeId(int $employeeId): void + { + $this->setAttribute('employee_id', $employeeId); + } + + public function setSummary(string $summary): void + { + $this->summary = $summary; + } + + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'employee' => $this->getEmployeeQuery(), + default => parent::relationQuery($name), + }; + } + + public function getEmployee(): Employee|null + { + return $this->relation('employee'); + } + public function getEmployeeQuery(): ActiveQuery { return $this->hasOne( diff --git a/tests/Stubs/ActiveRecord/Employee.php b/tests/Stubs/ActiveRecord/Employee.php index 422bc053d..43fc16e00 100644 --- a/tests/Stubs/ActiveRecord/Employee.php +++ b/tests/Stubs/ActiveRecord/Employee.php @@ -5,6 +5,7 @@ namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; use Yiisoft\ActiveRecord\ActiveQuery; +use Yiisoft\ActiveRecord\ActiveQueryInterface; use Yiisoft\ActiveRecord\ActiveRecord; /** @@ -15,21 +16,38 @@ * @property string $first_name * @property string $last_name * @property string $fullName - * @property Department $department - * @property Dossier $dossier */ final class Employee extends ActiveRecord { + protected int $id; + protected int $department_id; + protected string $first_name; + protected string $last_name; + public function getTableName(): string { return 'employee'; } + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'department' => $this->getDepartmentQuery(), + 'dossier' => $this->getDossierQuery(), + default => parent::relationQuery($name), + }; + } + public function getFullName(): string { return $this->first_name . ' ' . $this->last_name; } + public function getDepartment(): Department + { + return $this->relation('department'); + } + public function getDepartmentQuery(): ActiveQuery { return $this @@ -40,6 +58,11 @@ public function getDepartmentQuery(): ActiveQuery ; } + public function getDossier(): Dossier + { + return $this->relation('dossier'); + } + public function getDossierQuery(): ActiveQuery { return $this->hasOne( diff --git a/tests/Stubs/ActiveRecord/Item.php b/tests/Stubs/ActiveRecord/Item.php index 7e0e33bb8..43efaabbf 100644 --- a/tests/Stubs/ActiveRecord/Item.php +++ b/tests/Stubs/ActiveRecord/Item.php @@ -5,6 +5,7 @@ namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; use Yiisoft\ActiveRecord\ActiveQuery; +use Yiisoft\ActiveRecord\ActiveQueryInterface; use Yiisoft\ActiveRecord\ActiveRecord; /** @@ -16,11 +17,43 @@ */ final class Item extends ActiveRecord { + protected int $id; + protected string $name; + protected int $category_id; + public function getTableName(): string { return 'item'; } + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'category' => $this->getCategoryQuery(), + default => parent::relationQuery($name), + }; + } + + public function getId(): int + { + return $this->id; + } + + public function getName(): string + { + return $this->name; + } + + public function getCategoryId(): int + { + return $this->category_id; + } + + public function getCategory(): Category + { + return $this->relation('category'); + } + public function getCategoryQuery(): ActiveQuery { return $this->hasOne(Category::class, ['id' => 'category_id']); diff --git a/tests/Stubs/ActiveRecord/NullValues.php b/tests/Stubs/ActiveRecord/NullValues.php index d2d07800a..18d8a09db 100644 --- a/tests/Stubs/ActiveRecord/NullValues.php +++ b/tests/Stubs/ActiveRecord/NullValues.php @@ -17,6 +17,12 @@ */ final class NullValues extends ActiveRecord { + public int $id; + public int|null $var1 = null; + public int|null $var2 = null; + public int|null $var3 = null; + public string|null $stringcol = null; + public function getTableName(): string { return 'null_values'; diff --git a/tests/Stubs/ActiveRecord/Order.php b/tests/Stubs/ActiveRecord/Order.php index 3df48d377..8d2eb6763 100644 --- a/tests/Stubs/ActiveRecord/Order.php +++ b/tests/Stubs/ActiveRecord/Order.php @@ -5,6 +5,7 @@ namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; use Yiisoft\ActiveRecord\ActiveQuery; +use Yiisoft\ActiveRecord\ActiveQueryInterface; use Yiisoft\ActiveRecord\ActiveRecord; /** @@ -13,39 +14,139 @@ * @property int $id * @property int $customer_id * @property int $created_at - * @property string $total + * @property float $total */ class Order extends ActiveRecord { public const TABLE_NAME = 'order'; - private string|int|null $virtualCustomerId = null; + protected int|null $id; + protected int $customer_id; + protected int $created_at; + protected float $total; + + protected string|int|null $virtualCustomerId = null; public function getTableName(): string { return self::TABLE_NAME; } + public function getId(): int|null + { + return $this->id; + } + + public function getCustomerId(): int + { + return $this->customer_id; + } + + public function getCreatedAt(): int + { + return $this->created_at; + } + + public function getTotal(): float + { + return $this->total; + } + + public function setId(int|null $id): void + { + $this->setAttribute('id', $id); + } + + public function setCustomerId(int $customerId): void + { + $this->setAttribute('customer_id', $customerId); + } + + public function setCreatedAt(int $createdAt): void + { + $this->created_at = $createdAt; + } + + public function setTotal(float $total): void + { + $this->total = $total; + } + + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'virtualCustomer' => $this->getVirtualCustomerQuery(), + 'customer' => $this->getCustomerQuery(), + 'customerJoinedWithProfile' => $this->getCustomerJoinedWithProfileQuery(), + 'customerJoinedWithProfileIndexOrdered' => $this->getCustomerJoinedWithProfileIndexOrderedQuery(), + 'customer2' => $this->getCustomer2Query(), + 'orderItems' => $this->getOrderItemsQuery(), + 'orderItems2' => $this->getOrderItems2Query(), + 'orderItems3' => $this->getOrderItems3Query(), + 'orderItemsWithNullFK' => $this->getOrderItemsWithNullFKQuery(), + 'items' => $this->getItemsQuery(), + 'itemsIndexed' => $this->getItemsIndexedQuery(), + 'itemsWithNullFK' => $this->getItemsWithNullFKQuery(), + 'itemsInOrder1' => $this->getItemsInOrder1Query(), + 'itemsInOrder2' => $this->getItemsInOrder2Query(), + 'books' => $this->getBooksQuery(), + 'booksWithNullFK' => $this->getBooksWithNullFKQuery(), + 'booksViaTable' => $this->getBooksViaTableQuery(), + 'booksWithNullFKViaTable' => $this->getBooksWithNullFKViaTableQuery(), + 'books2' => $this->getBooks2Query(), + 'booksExplicit' => $this->getBooksExplicitQuery(), + 'booksExplicitA' => $this->getBooksExplicitAQuery(), + 'bookItems' => $this->getBookItemsQuery(), + 'movieItems' => $this->getMovieItemsQuery(), + 'limitedItems' => $this->getLimitedItemsQuery(), + 'expensiveItemsUsingViaWithCallable' => $this->getExpensiveItemsUsingViaWithCallableQuery(), + 'cheapItemsUsingViaWithCallable' => $this->getCheapItemsUsingViaWithCallableQuery(), + 'orderItemsFor8' => $this->getOrderItemsFor8Query(), + 'itemsFor8' => $this->getItemsFor8Query(), + default => parent::relationQuery($name), + }; + } + public function setVirtualCustomerId(string|int|null $virtualCustomerId = null): void { $this->virtualCustomerId = $virtualCustomerId; } - public function getVirtualCustomerQuery() + public function getVirtualCustomer(): Customer|null + { + return $this->relation('virtualCustomer'); + } + + public function getVirtualCustomerQuery(): ActiveQuery { return $this->hasOne(Customer::class, ['id' => 'virtualCustomerId']); } + public function getCustomer(): Customer|null + { + return $this->relation('customer'); + } + public function getCustomerQuery(): ActiveQuery { return $this->hasOne(Customer::class, ['id' => 'customer_id']); } + public function getCustomerJoinedWithProfile(): Customer|null + { + return $this->relation('customerJoinedWithProfile'); + } + public function getCustomerJoinedWithProfileQuery(): ActiveQuery { return $this->hasOne(Customer::class, ['id' => 'customer_id'])->joinWith('profile'); } + public function getCustomerJoinedWithProfileIndexOrdered(): array + { + return $this->relation('customerJoinedWithProfileIndexOrdered'); + } + public function getCustomerJoinedWithProfileIndexOrderedQuery(): ActiveQuery { return $this->hasMany( @@ -54,21 +155,41 @@ public function getCustomerJoinedWithProfileIndexOrderedQuery(): ActiveQuery )->joinWith('profile')->orderBy(['profile.description' => SORT_ASC])->indexBy('name'); } + public function getCustomer2(): Customer|null + { + return $this->relation('customer2'); + } + public function getCustomer2Query(): ActiveQuery { return $this->hasOne(Customer::class, ['id' => 'customer_id'])->inverseOf('orders2'); } + public function getOrderItems(): array + { + return $this->relation('orderItems'); + } + public function getOrderItemsQuery(): ActiveQuery { return $this->hasMany(OrderItem::class, ['order_id' => 'id']); } + public function getOrderItems2(): array + { + return $this->relation('orderItems2'); + } + public function getOrderItems2Query(): ActiveQuery { return $this->hasMany(OrderItem::class, ['order_id' => 'id'])->indexBy('item_id'); } + public function getOrderItems3(): array + { + return $this->relation('orderItems3'); + } + public function getOrderItems3Query(): ActiveQuery { return $this->hasMany( @@ -77,11 +198,21 @@ public function getOrderItems3Query(): ActiveQuery )->indexBy(fn ($row) => $row['order_id'] . '_' . $row['item_id']); } + public function getOrderItemsWithNullFK(): array + { + return $this->relation('orderItemsWithNullFK'); + } + public function getOrderItemsWithNullFKQuery(): ActiveQuery { return $this->hasMany(OrderItemWithNullFK::class, ['order_id' => 'id']); } + public function getItems(): array + { + return $this->relation('items'); + } + public function getItemsQuery(): ActiveQuery { return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems', static function ($q) { @@ -89,11 +220,21 @@ public function getItemsQuery(): ActiveQuery })->orderBy('item.id'); } + public function getItemsIndexed(): array + { + return $this->relation('itemsIndexed'); + } + public function getItemsIndexedQuery(): ActiveQuery { return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems')->indexBy('id'); } + public function getItemsWithNullFK(): array + { + return $this->relation('itemsWithNullFK'); + } + public function getItemsWithNullFKQuery(): ActiveQuery { return $this->hasMany( @@ -102,6 +243,11 @@ public function getItemsWithNullFKQuery(): ActiveQuery )->viaTable('order_item_with_null_fk', ['order_id' => 'id']); } + public function getItemsInOrder1(): array + { + return $this->relation('itemsInOrder1'); + } + public function getItemsInOrder1Query(): ActiveQuery { return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems', static function ($q) { @@ -109,6 +255,11 @@ public function getItemsInOrder1Query(): ActiveQuery })->orderBy('name'); } + public function getItemsInOrder2(): array + { + return $this->relation('itemsInOrder2'); + } + public function getItemsInOrder2Query(): ActiveQuery { return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems', static function ($q) { @@ -116,11 +267,21 @@ public function getItemsInOrder2Query(): ActiveQuery })->orderBy('name'); } + public function getBooks(): array + { + return $this->relation('books'); + } + public function getBooksQuery(): ActiveQuery { return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems')->where(['category_id' => 1]); } + public function getBooksWithNullFK(): array + { + return $this->relation('booksWithNullFK'); + } + public function getBooksWithNullFKQuery(): ActiveQuery { return $this->hasMany( @@ -129,6 +290,11 @@ public function getBooksWithNullFKQuery(): ActiveQuery )->via('orderItemsWithNullFK')->where(['category_id' => 1]); } + public function getBooksViaTable(): array + { + return $this->relation('booksViaTable'); + } + public function getBooksViaTableQuery(): ActiveQuery { return $this->hasMany( @@ -137,6 +303,11 @@ public function getBooksViaTableQuery(): ActiveQuery )->viaTable('order_item', ['order_id' => 'id'])->where(['category_id' => 1]); } + public function getBooksWithNullFKViaTable(): array + { + return $this->relation('booksWithNullFKViaTable'); + } + public function getBooksWithNullFKViaTableQuery(): ActiveQuery { return $this->hasMany( @@ -145,6 +316,11 @@ public function getBooksWithNullFKViaTableQuery(): ActiveQuery )->viaTable('order_item_with_null_fk', ['order_id' => 'id'])->where(['category_id' => 1]); } + public function getBooks2(): array + { + return $this->relation('books2'); + } + public function getBooks2Query(): ActiveQuery { return $this->hasMany( @@ -153,6 +329,11 @@ public function getBooks2Query(): ActiveQuery )->onCondition(['category_id' => 1])->viaTable('order_item', ['order_id' => 'id']); } + public function getBooksExplicit(): array + { + return $this->relation('booksExplicit'); + } + public function getBooksExplicitQuery(): ActiveQuery { return $this->hasMany( @@ -161,6 +342,11 @@ public function getBooksExplicitQuery(): ActiveQuery )->onCondition(['category_id' => 1])->viaTable('order_item', ['order_id' => 'id']); } + public function getBooksExplicitA(): array + { + return $this->relation('booksExplicitA'); + } + public function getBooksExplicitAQuery(): ActiveQuery { return $this->hasMany( @@ -169,6 +355,11 @@ public function getBooksExplicitAQuery(): ActiveQuery )->alias('bo')->onCondition(['bo.category_id' => 1])->viaTable('order_item', ['order_id' => 'id']); } + public function getBookItems(): array + { + return $this->relation('bookItems'); + } + public function getBookItemsQuery(): ActiveQuery { return $this->hasMany( @@ -177,6 +368,11 @@ public function getBookItemsQuery(): ActiveQuery )->alias('books')->onCondition(['books.category_id' => 1])->viaTable('order_item', ['order_id' => 'id']); } + public function getMovieItems(): array + { + return $this->relation('movieItems'); + } + public function getMovieItemsQuery(): ActiveQuery { return $this->hasMany( @@ -185,11 +381,21 @@ public function getMovieItemsQuery(): ActiveQuery )->alias('movies')->onCondition(['movies.category_id' => 2])->viaTable('order_item', ['order_id' => 'id']); } + public function getLimitedItems(): array + { + return $this->relation('limitedItems'); + } + public function getLimitedItemsQuery(): ActiveQuery { return $this->hasMany(Item::class, ['id' => 'item_id'])->onCondition(['item.id' => [3, 5]])->via('orderItems'); } + public function getExpensiveItemsUsingViaWithCallable(): array + { + return $this->relation('expensiveItemsUsingViaWithCallable'); + } + public function getExpensiveItemsUsingViaWithCallableQuery(): ActiveQuery { return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems', function (ActiveQuery $q) { @@ -197,6 +403,11 @@ public function getExpensiveItemsUsingViaWithCallableQuery(): ActiveQuery }); } + public function getCheapItemsUsingViaWithCallable(): array + { + return $this->relation('cheapItemsUsingViaWithCallable'); + } + public function getCheapItemsUsingViaWithCallableQuery(): ActiveQuery { return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems', function (ActiveQuery $q) { @@ -204,11 +415,21 @@ public function getCheapItemsUsingViaWithCallableQuery(): ActiveQuery }); } + public function getOrderItemsFor8(): array + { + return $this->relation('orderItemsFor8'); + } + public function getOrderItemsFor8Query(): ActiveQuery { return $this->hasMany(OrderItemWithNullFK::class, ['order_id' => 'id'])->andOnCondition(['subtotal' => 8.0]); } + public function getItemsFor8(): array + { + return $this->relation('itemsFor8'); + } + public function getItemsFor8Query(): ActiveQuery { return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItemsFor8'); diff --git a/tests/Stubs/ActiveRecord/OrderItem.php b/tests/Stubs/ActiveRecord/OrderItem.php index 8af8b7cca..6ca66b8a3 100644 --- a/tests/Stubs/ActiveRecord/OrderItem.php +++ b/tests/Stubs/ActiveRecord/OrderItem.php @@ -5,6 +5,7 @@ namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; use Yiisoft\ActiveRecord\ActiveQuery; +use Yiisoft\ActiveRecord\ActiveQueryInterface; use Yiisoft\ActiveRecord\ActiveRecord; /** @@ -13,10 +14,15 @@ * @property int $order_id * @property int $item_id * @property int $quantity - * @property string $subtotal + * @property float $subtotal */ final class OrderItem extends ActiveRecord { + protected int $order_id; + protected int $item_id; + protected int $quantity; + protected float $subtotal; + public function getTableName(): string { return 'order_item'; @@ -26,6 +32,7 @@ public function fields(): array { $fields = parent::fields(); + // Wrong fields. Should be without values. $fields['order_id'] = $this->getAttribute('order_id'); $fields['item_id'] = $this->getAttribute('item_id'); $fields['price'] = $this->getAttribute('subtotal') / $this->getAttribute('quantity'); @@ -35,27 +42,104 @@ public function fields(): array return $fields; } + public function getOrderId(): int + { + return $this->order_id; + } + + public function getItemId(): int + { + return $this->item_id; + } + + public function getQuantity(): int + { + return $this->quantity; + } + + public function getSubtotal(): float + { + return $this->subtotal; + } + + public function setOrderId(int $orderId): void + { + $this->setAttribute('order_id', $orderId); + } + + public function setItemId(int $itemId): void + { + $this->setAttribute('item_id', $itemId); + } + + public function setQuantity(int $quantity): void + { + $this->quantity = $quantity; + } + + public function setSubtotal(float $subtotal): void + { + $this->subtotal = $subtotal; + } + + public function relationQuery(string $name): ActiveQueryInterface + { + return match ($name) { + 'order' => $this->getOrderQuery(), + 'item' => $this->getItemQuery(), + 'orderItemCompositeWithJoin' => $this->getOrderItemCompositeWithJoinQuery(), + 'orderItemCompositeNoJoin' => $this->getOrderItemCompositeNoJoinQuery(), + 'custom' => $this->getCustomQuery(), + default => parent::relationQuery($name), + }; + } + + public function getOrder(): Order|null + { + return $this->relation('order'); + } + public function getOrderQuery(): ActiveQuery { return $this->hasOne(Order::class, ['id' => 'order_id']); } + public function getItem(): Item|null + { + return $this->relation('item'); + } + public function getItemQuery(): ActiveQuery { return $this->hasOne(Item::class, ['id' => 'item_id']); } + public function getOrderItemCompositeWithJoin(): OrderItem|null + { + return $this->relation('orderItemCompositeWithJoin'); + } + public function getOrderItemCompositeWithJoinQuery(): ActiveQuery { /** relations used by testFindCompositeWithJoin() */ return $this->hasOne(self::class, ['item_id' => 'item_id', 'order_id' => 'order_id' ])->joinWith('item'); } + public function getOrderItemCompositeNoJoin(): OrderItem|null + { + return $this->relation('orderItemCompositeNoJoin'); + } + public function getOrderItemCompositeNoJoinQuery(): ActiveQuery { return $this->hasOne(self::class, ['item_id' => 'item_id', 'order_id' => 'order_id' ]); } + public function getCustom(): Order|null + { + return $this->relation('custom'); + } + public function getCustomQuery(): ActiveQuery { return new ActiveQuery(Order::class, $this->db()); diff --git a/tests/Stubs/ActiveRecord/OrderItemWithNullFK.php b/tests/Stubs/ActiveRecord/OrderItemWithNullFK.php index d848bc59a..24c07fc84 100644 --- a/tests/Stubs/ActiveRecord/OrderItemWithNullFK.php +++ b/tests/Stubs/ActiveRecord/OrderItemWithNullFK.php @@ -9,13 +9,18 @@ /** * Class OrderItem. * - * @property int $order_id - * @property int $item_id + * @property int|null $order_id + * @property int|null $item_id * @property int $quantity - * @property string $subtotal + * @property float $subtotal */ final class OrderItemWithNullFK extends ActiveRecord { + protected int|null $order_id; + protected int|null $item_id; + protected int $quantity; + protected float $subtotal; + public function getTableName(): string { return 'order_item_with_null_fk'; diff --git a/tests/Stubs/ActiveRecord/OrderWithNullFK.php b/tests/Stubs/ActiveRecord/OrderWithNullFK.php index 2f76b5324..acd10dd97 100644 --- a/tests/Stubs/ActiveRecord/OrderWithNullFK.php +++ b/tests/Stubs/ActiveRecord/OrderWithNullFK.php @@ -10,14 +10,39 @@ * Class Order. * * @property int $id - * @property int $customer_id + * @property int|null $customer_id * @property int $created_at - * @property string $total + * @property float $total */ final class OrderWithNullFK extends ActiveRecord { + protected int $id; + protected int|null $customer_id; + protected int $created_at; + protected float $total; + public function getTableName(): string { return 'order_with_null_fk'; } + + public function getId(): int + { + return $this->id; + } + + public function getCustomerId(): int|null + { + return $this->customer_id; + } + + public function getCreatedAt(): int + { + return $this->created_at; + } + + public function getTotal(): float + { + return $this->total; + } } diff --git a/tests/Stubs/ActiveRecord/Profile.php b/tests/Stubs/ActiveRecord/Profile.php index 0d5e06e14..1953f6bb9 100644 --- a/tests/Stubs/ActiveRecord/Profile.php +++ b/tests/Stubs/ActiveRecord/Profile.php @@ -16,6 +16,9 @@ final class Profile extends ActiveRecord { public const TABLE_NAME = 'profile'; + protected int $id; + protected string $description; + public function getTableName(): string { return self::TABLE_NAME; diff --git a/tests/Stubs/ActiveRecord/ProfileWithConstructor.php b/tests/Stubs/ActiveRecord/ProfileWithConstructor.php index c6b87e0fe..c3059b37b 100644 --- a/tests/Stubs/ActiveRecord/ProfileWithConstructor.php +++ b/tests/Stubs/ActiveRecord/ProfileWithConstructor.php @@ -16,6 +16,9 @@ */ final class ProfileWithConstructor extends ActiveRecord { + protected int $id; + protected string $description; + public function __construct(ConnectionInterface $db, private Aliases $aliases) { parent::__construct($db); diff --git a/tests/Stubs/ActiveRecord/TestTrigger.php b/tests/Stubs/ActiveRecord/TestTrigger.php index b60400ffd..d625afcf4 100644 --- a/tests/Stubs/ActiveRecord/TestTrigger.php +++ b/tests/Stubs/ActiveRecord/TestTrigger.php @@ -14,6 +14,9 @@ */ final class TestTrigger extends ActiveRecord { + public int $id; + public string $stringcol; + public function getTableName(): string { return 'test_trigger'; diff --git a/tests/Stubs/ActiveRecord/TestTriggerAlert.php b/tests/Stubs/ActiveRecord/TestTriggerAlert.php index f66538934..414a85ef5 100644 --- a/tests/Stubs/ActiveRecord/TestTriggerAlert.php +++ b/tests/Stubs/ActiveRecord/TestTriggerAlert.php @@ -14,6 +14,9 @@ */ final class TestTriggerAlert extends ActiveRecord { + public int $id; + public string $stringcol; + public function getTableName(): string { return 'test_trigger_alert'; diff --git a/tests/Stubs/ActiveRecord/Type.php b/tests/Stubs/ActiveRecord/Type.php index ec8c47849..d2cb1ccf4 100644 --- a/tests/Stubs/ActiveRecord/Type.php +++ b/tests/Stubs/ActiveRecord/Type.php @@ -5,26 +5,46 @@ namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; use Yiisoft\ActiveRecord\ActiveRecord; +use Yiisoft\Db\Expression\Expression; /** * Model representing type table. * * @property int $int_col - * @property int $int_col2 DEFAULT 1 - * @property int $smallint_col DEFAULT 1 + * @property int|null $int_col2 DEFAULT 1 + * @property int|null $tinyint_col DEFAULT 1 + * @property int|null $smallint_col DEFAULT 1 * @property string $char_col - * @property string $char_col2 DEFAULT 'something' - * @property string $char_col3 + * @property string|null $char_col2 DEFAULT 'something' + * @property string|null $char_col3 * @property float $float_col - * @property float $float_col2 DEFAULT '1.23' - * @property string $blob_col - * @property float $numeric_col DEFAULT '33.22' + * @property float|null $float_col2 DEFAULT '1.23' + * @property string|null $blob_col + * @property float|null $numeric_col DEFAULT '33.22' * @property string $time DEFAULT '2002-01-01 00:00:00' * @property bool $bool_col - * @property bool $bool_col2 DEFAULT 1 + * @property bool|null $bool_col2 DEFAULT 1 */ final class Type extends ActiveRecord { + public int $int_col; + public int|null $int_col2 = 1; + public int|null $tinyint_col = 1; + public int|null $smallint_col = 1; + public string $char_col; + public string|null $char_col2 = 'something'; + public string|null $char_col3; + public float $float_col; + public float|null $float_col2 = 1.23; + public mixed $blob_col; + public float|null $numeric_col = 33.22; + public string $time = '2002-01-01 00:00:00'; + public bool|int $bool_col; + public bool|int|null $bool_col2 = true; + public string|Expression $ts_default; + public $bit_col = b'10000010'; + public array $json_col; + public function getTableName(): string { return 'type'; diff --git a/tests/Stubs/MagicActiveRecord/Alpha.php b/tests/Stubs/MagicActiveRecord/Alpha.php new file mode 100644 index 000000000..07e3b0ac6 --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/Alpha.php @@ -0,0 +1,27 @@ +hasMany(Beta::class, ['alpha_string_identifier' => 'string_identifier']); + } +} diff --git a/tests/Stubs/MagicActiveRecord/Animal.php b/tests/Stubs/MagicActiveRecord/Animal.php new file mode 100644 index 000000000..a2a31d2bd --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/Animal.php @@ -0,0 +1,49 @@ +type = static::class; + } + + public function getDoes() + { + return $this->does; + } + + public function instantiate($row): ActiveRecordInterface + { + $class = $row['type']; + + return new $class($this->db()); + } + + public function setDoes(string $value): void + { + $this->does = $value; + } +} diff --git a/tests/Stubs/MagicActiveRecord/ArrayAndJsonTypes.php b/tests/Stubs/MagicActiveRecord/ArrayAndJsonTypes.php new file mode 100644 index 000000000..64b774c51 --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/ArrayAndJsonTypes.php @@ -0,0 +1,11 @@ +hasOne(Alpha::class, ['string_identifier' => 'alpha_string_identifier']); + } +} diff --git a/tests/Stubs/MagicActiveRecord/BitValues.php b/tests/Stubs/MagicActiveRecord/BitValues.php new file mode 100644 index 000000000..ab097b829 --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/BitValues.php @@ -0,0 +1,17 @@ +setDoes('meow'); + } + + public function getException(): void + { + throw new Exception('no'); + } + + /** + * This is to test if __isset catches the error. + * + * @throw DivisionByZeroError + */ + public function getThrowable(): float|int + { + return 5 / 0; + } + + public function setNonExistingProperty(string $value): void + { + } +} diff --git a/tests/Stubs/MagicActiveRecord/Category.php b/tests/Stubs/MagicActiveRecord/Category.php new file mode 100644 index 000000000..0ebf51c48 --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/Category.php @@ -0,0 +1,42 @@ +hasMany(Item::class, ['category_id' => 'id'])->onCondition(['item.id' => [1, 2, 3]]); + } + + public function getItemsQuery(): ActiveQuery + { + return $this->hasMany(Item::class, ['category_id' => 'id']); + } + + public function getOrderItemsQuery(): ActiveQuery + { + return $this->hasMany(OrderItem::class, ['item_id' => 'id'])->via('items'); + } + + public function getOrdersQuery(): ActiveQuery + { + return $this->hasMany(Order::class, ['id' => 'order_id'])->via('orderItems'); + } +} diff --git a/tests/Stubs/MagicActiveRecord/Customer.php b/tests/Stubs/MagicActiveRecord/Customer.php new file mode 100644 index 000000000..ecd9c575c --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/Customer.php @@ -0,0 +1,121 @@ +getAttribute('name'); + } + + public function getProfileQuery(): ActiveQuery + { + return $this->hasOne(Profile::class, ['id' => 'profile_id']); + } + + public function getOrdersPlainQuery(): ActiveQuery + { + return $this->hasMany(Order::class, ['customer_id' => 'id']); + } + + public function getOrdersQuery(): ActiveQuery + { + return $this->hasMany(Order::class, ['customer_id' => 'id'])->orderBy('[[id]]'); + } + + public function getOrdersNoOrderQuery(): ActiveQuery + { + return $this->hasMany(Order::class, ['customer_id' => 'id']); + } + + public function getExpensiveOrdersQuery(): ActiveQuery + { + return $this->hasMany(Order::class, ['customer_id' => 'id'])->andWhere('[[total]] > 50')->orderBy('id'); + } + + public function getItemQuery(): void + { + } + + public function getOrdersWithItemsQuery(): ActiveQuery + { + return $this->hasMany(Order::class, ['customer_id' => 'id'])->with('orderItems'); + } + + public function getExpensiveOrdersWithNullFKQuery(): ActiveQuery + { + return $this->hasMany( + OrderWithNullFK::class, + ['customer_id' => 'id'] + )->andWhere('[[total]] > 50')->orderBy('id'); + } + + public function getOrdersWithNullFKQuery(): ActiveQuery + { + return $this->hasMany(OrderWithNullFK::class, ['customer_id' => 'id'])->orderBy('id'); + } + + public function getOrders2Query(): ActiveQuery + { + return $this->hasMany(Order::class, ['customer_id' => 'id'])->inverseOf('customer2')->orderBy('id'); + } + + /** deeply nested table relation */ + public function getOrderItemsQuery(): ActiveQuery + { + $rel = $this->hasMany(Item::class, ['id' => 'item_id']); + + return $rel->viaTable('order_item', ['order_id' => 'id'], function ($q) { + /* @var $q ActiveQuery */ + $q->viaTable('order', ['customer_id' => 'id']); + })->orderBy('id'); + } + + public function setOrdersReadOnly(): void + { + } + + public function getOrderItems2Query(): ActiveQuery + { + return $this->hasMany(OrderItem::class, ['order_id' => 'id']) + ->via('ordersNoOrder'); + } + + public function getItems2Query(): ActiveQuery + { + return $this->hasMany(Item::class, ['id' => 'item_id']) + ->via('orderItems2'); + } +} diff --git a/tests/Stubs/MagicActiveRecord/CustomerClosureField.php b/tests/Stubs/MagicActiveRecord/CustomerClosureField.php new file mode 100644 index 000000000..d90e2981c --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/CustomerClosureField.php @@ -0,0 +1,33 @@ + $customer->status === 1 ? 'active' : 'inactive'; + + return $fields; + } +} diff --git a/tests/Stubs/MagicActiveRecord/CustomerForArrayable.php b/tests/Stubs/MagicActiveRecord/CustomerForArrayable.php new file mode 100644 index 000000000..e396f3f87 --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/CustomerForArrayable.php @@ -0,0 +1,57 @@ +item = $item; + } + + public function setItems(self ...$items) + { + $this->items = $items; + } + + public function toArray(array $fields = [], array $expand = [], bool $recursive = true): array + { + $data = parent::toArray($fields, $expand, $recursive); + + $data['status'] = $this->status == 1 ? 'active' : 'inactive'; + + return $data; + } +} diff --git a/tests/Stubs/MagicActiveRecord/CustomerQuery.php b/tests/Stubs/MagicActiveRecord/CustomerQuery.php new file mode 100644 index 000000000..cc4744023 --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/CustomerQuery.php @@ -0,0 +1,19 @@ +andWhere('[[status]]=1'); + + return $this; + } +} diff --git a/tests/Stubs/MagicActiveRecord/CustomerWithAlias.php b/tests/Stubs/MagicActiveRecord/CustomerWithAlias.php new file mode 100644 index 000000000..221e5a612 --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/CustomerWithAlias.php @@ -0,0 +1,32 @@ +hasOne(Profile::class, ['id' => 'profile_id']); + } +} diff --git a/tests/Stubs/ActiveRecord/CustomerWithProperties.php b/tests/Stubs/MagicActiveRecord/CustomerWithProperties.php similarity index 90% rename from tests/Stubs/ActiveRecord/CustomerWithProperties.php rename to tests/Stubs/MagicActiveRecord/CustomerWithProperties.php index f0dc90109..2567f5515 100644 --- a/tests/Stubs/ActiveRecord/CustomerWithProperties.php +++ b/tests/Stubs/MagicActiveRecord/CustomerWithProperties.php @@ -2,15 +2,15 @@ declare(strict_types=1); -namespace Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord; +namespace Yiisoft\ActiveRecord\Tests\Stubs\MagicActiveRecord; use Yiisoft\ActiveRecord\ActiveQuery; -use Yiisoft\ActiveRecord\ActiveRecord; +use Yiisoft\ActiveRecord\MagicActiveRecord; /** * Class Customer with defined properties. */ -class CustomerWithProperties extends ActiveRecord +class CustomerWithProperties extends MagicActiveRecord { protected int $id; protected string $email; diff --git a/tests/Stubs/MagicActiveRecord/DefaultPk.php b/tests/Stubs/MagicActiveRecord/DefaultPk.php new file mode 100644 index 000000000..c25bb652e --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/DefaultPk.php @@ -0,0 +1,15 @@ +hasMany( + Employee::class, + [ + 'department_id' => 'id', + ] + )->inverseOf('department'); + } +} diff --git a/tests/Stubs/MagicActiveRecord/Document.php b/tests/Stubs/MagicActiveRecord/Document.php new file mode 100644 index 000000000..d10690eda --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/Document.php @@ -0,0 +1,22 @@ +setDoes('bark'); + } +} diff --git a/tests/Stubs/MagicActiveRecord/Dossier.php b/tests/Stubs/MagicActiveRecord/Dossier.php new file mode 100644 index 000000000..5781c69be --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/Dossier.php @@ -0,0 +1,36 @@ +hasOne( + Employee::class, + [ + 'department_id' => 'department_id', + 'id' => 'employee_id', + ] + )->inverseOf('dossier'); + } +} diff --git a/tests/Stubs/MagicActiveRecord/Employee.php b/tests/Stubs/MagicActiveRecord/Employee.php new file mode 100644 index 000000000..0e421bfd5 --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/Employee.php @@ -0,0 +1,53 @@ +first_name . ' ' . $this->last_name; + } + + public function getDepartmentQuery(): ActiveQuery + { + return $this + ->hasOne(Department::class, [ + 'id' => 'department_id', + ]) + ->inverseOf('employees') + ; + } + + public function getDossierQuery(): ActiveQuery + { + return $this->hasOne( + Dossier::class, + [ + 'department_id' => 'department_id', + 'employee_id' => 'id', + ] + )->inverseOf('employee'); + } +} diff --git a/tests/Stubs/MagicActiveRecord/Item.php b/tests/Stubs/MagicActiveRecord/Item.php new file mode 100644 index 000000000..f4f8fd632 --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/Item.php @@ -0,0 +1,28 @@ +hasOne(Category::class, ['id' => 'category_id']); + } +} diff --git a/tests/Stubs/MagicActiveRecord/NoExist.php b/tests/Stubs/MagicActiveRecord/NoExist.php new file mode 100644 index 000000000..e8ac24737 --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/NoExist.php @@ -0,0 +1,15 @@ +virtualCustomerId = $virtualCustomerId; + } + + public function getVirtualCustomerQuery() + { + return $this->hasOne(Customer::class, ['id' => 'virtualCustomerId']); + } + + public function getCustomerQuery(): ActiveQuery + { + return $this->hasOne(Customer::class, ['id' => 'customer_id']); + } + + public function getCustomerJoinedWithProfileQuery(): ActiveQuery + { + return $this->hasOne(Customer::class, ['id' => 'customer_id'])->joinWith('profile'); + } + + public function getCustomerJoinedWithProfileIndexOrderedQuery(): ActiveQuery + { + return $this->hasMany( + Customer::class, + ['id' => 'customer_id'] + )->joinWith('profile')->orderBy(['profile.description' => SORT_ASC])->indexBy('name'); + } + + public function getCustomer2Query(): ActiveQuery + { + return $this->hasOne(Customer::class, ['id' => 'customer_id'])->inverseOf('orders2'); + } + + public function getOrderItemsQuery(): ActiveQuery + { + return $this->hasMany(OrderItem::class, ['order_id' => 'id']); + } + + public function getOrderItems2Query(): ActiveQuery + { + return $this->hasMany(OrderItem::class, ['order_id' => 'id'])->indexBy('item_id'); + } + + public function getOrderItems3Query(): ActiveQuery + { + return $this->hasMany( + OrderItem::class, + ['order_id' => 'id'] + )->indexBy(fn ($row) => $row['order_id'] . '_' . $row['item_id']); + } + + public function getOrderItemsWithNullFKQuery(): ActiveQuery + { + return $this->hasMany(OrderItemWithNullFK::class, ['order_id' => 'id']); + } + + public function getItemsQuery(): ActiveQuery + { + return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems', static function ($q) { + // additional query configuration + })->orderBy('item.id'); + } + + public function getItemsIndexedQuery(): ActiveQuery + { + return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems')->indexBy('id'); + } + + public function getItemsWithNullFKQuery(): ActiveQuery + { + return $this->hasMany( + Item::class, + ['id' => 'item_id'] + )->viaTable('order_item_with_null_fk', ['order_id' => 'id']); + } + + public function getItemsInOrder1Query(): ActiveQuery + { + return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems', static function ($q) { + $q->orderBy(['subtotal' => SORT_ASC]); + })->orderBy('name'); + } + + public function getItemsInOrder2Query(): ActiveQuery + { + return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems', static function ($q) { + $q->orderBy(['subtotal' => SORT_DESC]); + })->orderBy('name'); + } + + public function getBooksQuery(): ActiveQuery + { + return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems')->where(['category_id' => 1]); + } + + public function getBooksWithNullFKQuery(): ActiveQuery + { + return $this->hasMany( + Item::class, + ['id' => 'item_id'] + )->via('orderItemsWithNullFK')->where(['category_id' => 1]); + } + + public function getBooksViaTableQuery(): ActiveQuery + { + return $this->hasMany( + Item::class, + ['id' => 'item_id'] + )->viaTable('order_item', ['order_id' => 'id'])->where(['category_id' => 1]); + } + + public function getBooksWithNullFKViaTableQuery(): ActiveQuery + { + return $this->hasMany( + Item::class, + ['id' => 'item_id'] + )->viaTable('order_item_with_null_fk', ['order_id' => 'id'])->where(['category_id' => 1]); + } + + public function getBooks2Query(): ActiveQuery + { + return $this->hasMany( + Item::class, + ['id' => 'item_id'] + )->onCondition(['category_id' => 1])->viaTable('order_item', ['order_id' => 'id']); + } + + public function getBooksExplicitQuery(): ActiveQuery + { + return $this->hasMany( + Item::class, + ['id' => 'item_id'] + )->onCondition(['category_id' => 1])->viaTable('order_item', ['order_id' => 'id']); + } + + public function getBooksExplicitAQuery(): ActiveQuery + { + return $this->hasMany( + Item::class, + ['id' => 'item_id'] + )->alias('bo')->onCondition(['bo.category_id' => 1])->viaTable('order_item', ['order_id' => 'id']); + } + + public function getBookItemsQuery(): ActiveQuery + { + return $this->hasMany( + Item::class, + ['id' => 'item_id'] + )->alias('books')->onCondition(['books.category_id' => 1])->viaTable('order_item', ['order_id' => 'id']); + } + + public function getMovieItemsQuery(): ActiveQuery + { + return $this->hasMany( + Item::class, + ['id' => 'item_id'] + )->alias('movies')->onCondition(['movies.category_id' => 2])->viaTable('order_item', ['order_id' => 'id']); + } + + public function getLimitedItemsQuery(): ActiveQuery + { + return $this->hasMany(Item::class, ['id' => 'item_id'])->onCondition(['item.id' => [3, 5]])->via('orderItems'); + } + + public function getExpensiveItemsUsingViaWithCallableQuery(): ActiveQuery + { + return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems', function (ActiveQuery $q) { + $q->where(['>=', 'subtotal', 10]); + }); + } + + public function getCheapItemsUsingViaWithCallableQuery(): ActiveQuery + { + return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems', function (ActiveQuery $q) { + $q->where(['<', 'subtotal', 10]); + }); + } + + public function getOrderItemsFor8Query(): ActiveQuery + { + return $this->hasMany(OrderItemWithNullFK::class, ['order_id' => 'id'])->andOnCondition(['subtotal' => 8.0]); + } + + public function getItemsFor8Query(): ActiveQuery + { + return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItemsFor8'); + } +} diff --git a/tests/Stubs/MagicActiveRecord/OrderItem.php b/tests/Stubs/MagicActiveRecord/OrderItem.php new file mode 100644 index 000000000..23650caaa --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/OrderItem.php @@ -0,0 +1,63 @@ +getAttribute('order_id'); + $fields['item_id'] = $this->getAttribute('item_id'); + $fields['price'] = $this->getAttribute('subtotal') / $this->getAttribute('quantity'); + $fields['quantity'] = $this->getAttribute('quantity'); + $fields['subtotal'] = $this->getAttribute('subtotal'); + + return $fields; + } + + public function getOrderQuery(): ActiveQuery + { + return $this->hasOne(Order::class, ['id' => 'order_id']); + } + + public function getItemQuery(): ActiveQuery + { + return $this->hasOne(Item::class, ['id' => 'item_id']); + } + + public function getOrderItemCompositeWithJoinQuery(): ActiveQuery + { + /** relations used by testFindCompositeWithJoin() */ + return $this->hasOne(self::class, ['item_id' => 'item_id', 'order_id' => 'order_id' ])->joinWith('item'); + } + + public function getOrderItemCompositeNoJoinQuery(): ActiveQuery + { + return $this->hasOne(self::class, ['item_id' => 'item_id', 'order_id' => 'order_id' ]); + } + + public function getCustomQuery(): ActiveQuery + { + return new ActiveQuery(Order::class, $this->db()); + } +} diff --git a/tests/Stubs/MagicActiveRecord/OrderItemWithNullFK.php b/tests/Stubs/MagicActiveRecord/OrderItemWithNullFK.php new file mode 100644 index 000000000..7663631f2 --- /dev/null +++ b/tests/Stubs/MagicActiveRecord/OrderItemWithNullFK.php @@ -0,0 +1,23 @@ +