more tests for joinWith alias

also test on joining the same relation twice
This commit is contained in:
Carsten Brandt
2016-02-12 01:16:11 +01:00
parent 94571e2c23
commit 3f8df39f45
4 changed files with 113 additions and 6 deletions

View File

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

View File

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

View File

@@ -118,7 +118,35 @@ class Order extends ActiveRecord
public function getBooksQuerysyntax() public function getBooksQuerysyntax()
{ {
return $this->hasMany(Item::className(), ['id' => 'item_id']) 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']); ->viaTable('order_item', ['order_id' => 'id']);
} }

View File

@@ -556,7 +556,7 @@ class ActiveRecordTest extends DatabaseTestCase
return [ return [
['explicit'], // c ['explicit'], // c
['querysyntax'], // {{@customer}} ['querysyntax'], // {{@customer}}
['applyAlias'], // $query->applyAlias('customer', 'id') // ['applyAlias'], // $query->applyAlias('customer', 'id') // _aliases are currently not being populated
// later getRelationAlias() could be added // later getRelationAlias() could be added
]; ];
} }
@@ -621,7 +621,7 @@ class ActiveRecordTest extends DatabaseTestCase
if ($aliasMethod === 'explicit') { if ($aliasMethod === 'explicit') {
$orders = $query->where(['b.name' => 'Yii 1.1 Application Development Cookbook'])->orderBy('order.id')->all(); $orders = $query->where(['b.name' => 'Yii 1.1 Application Development Cookbook'])->orderBy('order.id')->all();
} elseif ($aliasMethod === 'querysyntax') { } 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') { } elseif ($aliasMethod === 'applyAlias') {
$orders = $query->where([$query->applyAlias('book', 'name') => 'Yii 1.1 Application Development Cookbook'])->orderBy($query->applyAlias('order', 'id'))->all(); $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)); $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 // join with count and query
/** @var $query ActiveQuery */ /** @var $query ActiveQuery */
$query = Order::find()->joinWith(['customer c']); $query = Order::find()->joinWith(['customer c']);
@@ -708,7 +724,7 @@ class ActiveRecordTest extends DatabaseTestCase
if ($aliasMethod === 'explicit') { if ($aliasMethod === 'explicit') {
$customer = $customerQuery->where(['o.id' => 1])->one(); $customer = $customerQuery->where(['o.id' => 1])->one();
} elseif ($aliasMethod === 'querysyntax') { } elseif ($aliasMethod === 'querysyntax') {
$customer = $customerQuery->where(['{{order}}.id' => 1])->one(); $customer = $customerQuery->where(['{{@order}}.id' => 1])->one();
} elseif ($aliasMethod === 'applyAlias') { } elseif ($aliasMethod === 'applyAlias') {
$customer = $customerQuery->where([$query->applyAlias('order', 'id') => 1])->one(); $customer = $customerQuery->where([$query->applyAlias('order', 'id') => 1])->one();
} }
@@ -726,7 +742,7 @@ class ActiveRecordTest extends DatabaseTestCase
} elseif ($aliasMethod === 'querysyntax') { } elseif ($aliasMethod === 'querysyntax') {
$q->where('{{@category}}.[[id]] = 2'); $q->where('{{@category}}.[[id]] = 2');
} elseif ($aliasMethod === 'applyAlias') { } elseif ($aliasMethod === 'applyAlias') {
$q->where([$query->applyAlias('category', 'id') => 2]); $q->where([$q->applyAlias('category', 'id') => 2]);
} }
}, },
])->orderBy('order.id')->all(); ])->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() public function testAlias()
{ {
$query = Order::find(); $query = Order::find();