Browse Source

more tests for joinWith alias

also test on joining the same relation twice
tags/2.0.7
Carsten Brandt 9 years ago
parent
commit
3f8df39f45
  1. 1
      framework/db/ActiveQuery.php
  2. 4
      framework/db/Query.php
  3. 30
      tests/data/ar/Order.php
  4. 84
      tests/framework/db/ActiveRecordTest.php

1
framework/db/ActiveQuery.php

@ -641,6 +641,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
if (!empty($child->join)) {
foreach ($child->join as $join) {
$this->join[] = $join;
$this->populateAliases((array) $join[1]);
}
}
if (!empty($child->union)) {

4
framework/db/Query.php

@ -851,7 +851,7 @@ class Query extends Component implements QueryInterface
*/
public static function create($from)
{
return new self([
$query = new self([
'where' => $from->where,
'limit' => $from->limit,
'offset' => $from->offset,
@ -867,5 +867,7 @@ class Query extends Component implements QueryInterface
'union' => $from->union,
'params' => $from->params,
]);
$query->_aliases = $from->_aliases;
return $query;
}
}

30
tests/data/ar/Order.php

@ -118,7 +118,35 @@ class Order extends ActiveRecord
public function getBooksQuerysyntax()
{
return $this->hasMany(Item::className(), ['id' => 'item_id'])
->onCondition(['{{@books}}.category_id' => 1])
->onCondition(['{{@item}}.category_id' => 1])
->viaTable('order_item', ['order_id' => 'id']);
}
public function getBooksExplicitA()
{
return $this->hasMany(Item::className(), ['id' => 'item_id'])->alias('bo')
->onCondition(['bo.category_id' => 1])
->viaTable('order_item', ['order_id' => 'id']);
}
public function getBooksQuerysyntaxA()
{
return $this->hasMany(Item::className(), ['id' => 'item_id'])->alias('bo')
->onCondition(['{{@item}}.category_id' => 1])
->viaTable('order_item', ['order_id' => 'id']);
}
public function getBookItems()
{
return $this->hasMany(Item::className(), ['id' => 'item_id'])->alias('books')
->onCondition(['books.category_id' => 1])
->viaTable('order_item', ['order_id' => 'id']);
}
public function getMovieItems()
{
return $this->hasMany(Item::className(), ['id' => 'item_id'])->alias('movies')
->onCondition(['movies.category_id' => 2])
->viaTable('order_item', ['order_id' => 'id']);
}

84
tests/framework/db/ActiveRecordTest.php

@ -556,7 +556,7 @@ class ActiveRecordTest extends DatabaseTestCase
return [
['explicit'], // c
['querysyntax'], // {{@customer}}
['applyAlias'], // $query->applyAlias('customer', 'id')
// ['applyAlias'], // $query->applyAlias('customer', 'id') // _aliases are currently not being populated
// later getRelationAlias() could be added
];
}
@ -621,7 +621,7 @@ class ActiveRecordTest extends DatabaseTestCase
if ($aliasMethod === 'explicit') {
$orders = $query->where(['b.name' => 'Yii 1.1 Application Development Cookbook'])->orderBy('order.id')->all();
} elseif ($aliasMethod === 'querysyntax') {
$orders = $query->where(['{{@book}}.name' => 'Yii 1.1 Application Development Cookbook'])->orderBy('{{@order}}.id')->all();
$orders = $query->where(['{{@item}}.name' => 'Yii 1.1 Application Development Cookbook'])->orderBy('{{@order}}.id')->all();
} elseif ($aliasMethod === 'applyAlias') {
$orders = $query->where([$query->applyAlias('book', 'name') => 'Yii 1.1 Application Development Cookbook'])->orderBy($query->applyAlias('order', 'id'))->all();
}
@ -687,6 +687,22 @@ class ActiveRecordTest extends DatabaseTestCase
$this->assertEquals(1, count($orders[2]->$relationName));
}
// join with ON condition and alias in relation definition
if ($aliasMethod === 'explicit' || $aliasMethod === 'querysyntax') {
$relationName = 'books' . ucfirst($aliasMethod) . 'A';
$orders = Order::find()->joinWith(["$relationName"])->orderBy('order.id')->all();
$this->assertEquals(3, count($orders));
$this->assertEquals(1, $orders[0]->id);
$this->assertEquals(2, $orders[1]->id);
$this->assertEquals(3, $orders[2]->id);
$this->assertTrue($orders[0]->isRelationPopulated($relationName));
$this->assertTrue($orders[1]->isRelationPopulated($relationName));
$this->assertTrue($orders[2]->isRelationPopulated($relationName));
$this->assertEquals(2, count($orders[0]->$relationName));
$this->assertEquals(0, count($orders[1]->$relationName));
$this->assertEquals(1, count($orders[2]->$relationName));
}
// join with count and query
/** @var $query ActiveQuery */
$query = Order::find()->joinWith(['customer c']);
@ -708,7 +724,7 @@ class ActiveRecordTest extends DatabaseTestCase
if ($aliasMethod === 'explicit') {
$customer = $customerQuery->where(['o.id' => 1])->one();
} elseif ($aliasMethod === 'querysyntax') {
$customer = $customerQuery->where(['{{order}}.id' => 1])->one();
$customer = $customerQuery->where(['{{@order}}.id' => 1])->one();
} elseif ($aliasMethod === 'applyAlias') {
$customer = $customerQuery->where([$query->applyAlias('order', 'id') => 1])->one();
}
@ -726,7 +742,7 @@ class ActiveRecordTest extends DatabaseTestCase
} elseif ($aliasMethod === 'querysyntax') {
$q->where('{{@category}}.[[id]] = 2');
} elseif ($aliasMethod === 'applyAlias') {
$q->where([$query->applyAlias('category', 'id') => 2]);
$q->where([$q->applyAlias('category', 'id') => 2]);
}
},
])->orderBy('order.id')->all();
@ -739,6 +755,66 @@ class ActiveRecordTest extends DatabaseTestCase
}
public function testJoinWithSameTable()
{
// join with the same table but different aliases
// alias is defined in the relation definition
// without eager loading
$query = Order::find()
->joinWith('bookItems', false)// TODO true
->joinWith('movieItems', false)
->where(['movies.name' => 'Toy Story']);
$orders = $query->all();
$this->assertEquals(1, count($orders), $query->createCommand()->rawSql . print_r($orders, true));
$this->assertEquals(2, $orders[0]->id);
$this->assertFalse($orders[0]->isRelationPopulated('bookItems'));
$this->assertFalse($orders[0]->isRelationPopulated('movieItems'));
// with eager loading
$query = Order::find()
->joinWith('bookItems', true)
->joinWith('movieItems', true)
->where(['movies.name' => 'Toy Story']);
$orders = $query->all();
$this->assertEquals(1, count($orders), $query->createCommand()->rawSql . print_r($orders, true));
$this->assertEquals(2, $orders[0]->id);
$this->assertTrue($orders[0]->isRelationPopulated('bookItems'));
$this->assertTrue($orders[0]->isRelationPopulated('movieItems'));
$this->assertEquals(0, count($orders[0]->bookItems));
$this->assertEquals(3, count($orders[0]->movieItems));
// join with the same table but different aliases
// alias is defined in the call to joinWith()
// without eager loading
$query = Order::find()
->joinWith(['itemsIndexed books' => function($q) { $q->onCondition('books.category_id = 1'); }], false)
->joinWith(['itemsIndexed movies' => function($q) { $q->onCondition('movies.category_id = 2'); }], false)
->where(['movies.name' => 'Toy Story']);
$orders = $query->all();
$this->assertEquals(1, count($orders), $query->createCommand()->rawSql . print_r($orders, true));
$this->assertEquals(2, $orders[0]->id);
$this->assertFalse($orders[0]->isRelationPopulated('itemsIndexed'));
// with eager loading, only for one relation as it would be overwritten otherwise.
$query = Order::find()
->joinWith(['itemsIndexed books' => function($q) { $q->onCondition('books.category_id = 1'); }], false)
->joinWith(['itemsIndexed movies' => function($q) { $q->onCondition('movies.category_id = 2'); }], true)
->where(['movies.name' => 'Toy Story']);
$orders = $query->all();
$this->assertEquals(1, count($orders), $query->createCommand()->rawSql . print_r($orders, true));
$this->assertEquals(2, $orders[0]->id);
$this->assertTrue($orders[0]->isRelationPopulated('itemsIndexed'));
$this->assertEquals(3, count($orders[0]->itemsIndexed));
// with eager loading, and the other relation
$query = Order::find()
->joinWith(['itemsIndexed books' => function($q) { $q->onCondition('books.category_id = 1'); }], true)
->joinWith(['itemsIndexed movies' => function($q) { $q->onCondition('movies.category_id = 2'); }], false)
->where(['movies.name' => 'Toy Story']);
$orders = $query->all();
$this->assertEquals(1, count($orders), $query->createCommand()->rawSql . print_r($orders, true));
$this->assertEquals(2, $orders[0]->id);
$this->assertTrue($orders[0]->isRelationPopulated('itemsIndexed'));
$this->assertEquals(0, count($orders[0]->itemsIndexed));
}
public function testAlias()
{
$query = Order::find();

Loading…
Cancel
Save