Commit 42d8748e by Qiang Xue

Fixes #1579: throw exception when the given AR relation name does not match in a…

Fixes #1579: throw exception when the given AR relation name does not match in a case sensitive manner. Renamed `ActiveRecord::getPopulatedRelations()` to `getRelatedRecords()`
parent c1aef527
......@@ -29,7 +29,7 @@ use yii\helpers\StringHelper;
* @property mixed $oldPrimaryKey The old primary key value. An array (column name => column value) is
* returned if the primary key is composite. A string is returned otherwise (null will be returned if the key
* value is null). This property is read-only.
* @property array $populatedRelations An array of relation data indexed by relation names. This property is
* @property array $relatedRecords An array of the populated related records indexed by relation names. This property is
* read-only.
* @property mixed $primaryKey The primary key value. An array (column name => column value) is returned if
* the primary key is composite. A string is returned otherwise (null will be returned if the key value is null).
......
......@@ -21,11 +21,13 @@ Yii Framework 2 Change Log
- Enh #1469: ActiveRecord::find() now works with default conditions (default scope) applied by createQuery (cebe)
- Enh #1523: Query conditions now allow to use the NOT operator (cebe)
- Enh #1552: It is now possible to use multiple bootstrap NavBar in a single page (Alex-Code)
- Enh #1579: throw exception when the given AR relation name does not match in a case sensitive manner (qiangxue)
- Enh: Added `favicon.ico` and `robots.txt` to defauly application templates (samdark)
- Enh: Added `Widget::autoIdPrefix` to support prefixing automatically generated widget IDs (qiangxue)
- Enh: Support for file aliases in console command 'message' (omnilight)
- Enh: Sort and Paginiation can now create absolute URLs (cebe)
- Chg: Renamed `yii\jui\Widget::clientEventsMap` to `clientEventMap` (qiangxue)
- Chg: Renamed `ActiveRecord::getPopulatedRelations()` to `getRelatedRecords()` (qiangxue)
- Chg: Added `yii\widgets\InputWidget::options` (qiangxue)
- New #1438: [MongoDB integration](https://github.com/yiisoft/yii2-mongodb) ActiveRecord and Query (klimov-paul)
- New #1393: [Codeception testing framework integration](https://github.com/yiisoft/yii2-codeception) (Ragazzo)
......
......@@ -30,7 +30,7 @@ use yii\helpers\Inflector;
* @property mixed $oldPrimaryKey The old primary key value. An array (column name => column value) is
* returned if the primary key is composite. A string is returned otherwise (null will be returned if the key
* value is null). This property is read-only.
* @property array $populatedRelations An array of relation data indexed by relation names. This property is
* @property array $relatedRecords An array of the populated related records indexed by relation names. This property is
* read-only.
* @property mixed $primaryKey The primary key value. An array (column name => column value) is returned if
* the primary key is composite. A string is returned otherwise (null will be returned if the key value is null).
......@@ -232,6 +232,13 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
}
$value = parent::__get($name);
if ($value instanceof ActiveRelationInterface) {
if (method_exists($this, 'get' . $name)) {
$method = new \ReflectionMethod($this, 'get' . $name);
$realName = lcfirst(substr($method->getName(), 3));
if ($realName !== $name) {
throw new InvalidParamException('Relation names are case sensitive. ' . get_class($this) . " has a relation named \"$realName\" instead of \"$name\".");
}
}
return $this->_related[$name] = $value->multiple ? $value->all() : $value->one();
} else {
return $value;
......@@ -390,10 +397,10 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
}
/**
* Returns all populated relations.
* @return array an array of relation data indexed by relation names.
* Returns all populated related records.
* @return array an array of related records indexed by relation names.
*/
public function getPopulatedRelations()
public function getRelatedRecords()
{
return $this->_related;
}
......@@ -999,15 +1006,25 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
{
$getter = 'get' . $name;
try {
// the relation could be defined in a behavior
$relation = $this->$getter();
if ($relation instanceof ActiveRelationInterface) {
return $relation;
} else {
throw new InvalidParamException(get_class($this) . ' has no relation named "' . $name . '".');
}
} catch (UnknownMethodException $e) {
throw new InvalidParamException(get_class($this) . ' has no relation named "' . $name . '".', 0, $e);
}
if (!$relation instanceof ActiveRelationInterface) {
throw new InvalidParamException(get_class($this) . ' has no relation named "' . $name . '".');
}
if (method_exists($this, $getter)) {
// relation name is case sensitive, trying to validate it when the relation is defined within this class
$method = new \ReflectionMethod($this, $getter);
$realName = lcfirst(substr($method->getName(), 3));
if ($realName !== $name) {
throw new InvalidParamException('Relation names are case sensitive. ' . get_class($this) . " has a relation named \"$realName\" instead of \"$name\".");
}
}
return $relation;
}
/**
......
......@@ -69,7 +69,7 @@ class ActiveRelationTest extends MongoDbTestCase
$this->assertTrue($order->isRelationPopulated('customer'));
$this->assertTrue($customer instanceof Customer);
$this->assertEquals((string)$customer->_id, (string)$order->customer_id);
$this->assertEquals(1, count($order->populatedRelations));
$this->assertEquals(1, count($order->relatedRecords));
}
public function testFindEager()
......
......@@ -29,7 +29,7 @@ class ActiveRelationTest extends SphinxTestCase
$index = $article->index;
$this->assertTrue($article->isRelationPopulated('index'));
$this->assertTrue($index instanceof ArticleIndex);
$this->assertEquals(1, count($article->populatedRelations));
$this->assertEquals(1, count($article->relatedRecords));
$this->assertEquals($article->id, $index->id);
}
......
......@@ -32,7 +32,7 @@ class ExternalActiveRelationTest extends SphinxTestCase
$source = $article->source;
$this->assertTrue($article->isRelationPopulated('source'));
$this->assertTrue($source instanceof ArticleDb);
$this->assertEquals(1, count($article->populatedRelations));
$this->assertEquals(1, count($article->relatedRecords));
// has many :
/*$this->assertFalse($article->isRelationPopulated('tags'));
......
......@@ -392,14 +392,14 @@ trait ActiveRecordTestTrait
$orders = $customer->orders;
$this->assertTrue($customer->isRelationPopulated('orders'));
$this->assertEquals(2, count($orders));
$this->assertEquals(1, count($customer->populatedRelations));
$this->assertEquals(1, count($customer->relatedRecords));
/** @var Customer $customer */
$customer = $this->callCustomerFind(2);
$this->assertFalse($customer->isRelationPopulated('orders'));
$orders = $customer->getOrders()->where(['id' => 3])->all();
$this->assertFalse($customer->isRelationPopulated('orders'));
$this->assertEquals(0, count($customer->populatedRelations));
$this->assertEquals(0, count($customer->relatedRecords));
$this->assertEquals(1, count($orders));
$this->assertEquals(3, $orders[0]->id);
......@@ -421,7 +421,7 @@ trait ActiveRecordTestTrait
$customer = $this->callCustomerFind()->where(['id' => 1])->with('orders')->one();
$this->assertTrue($customer->isRelationPopulated('orders'));
$this->assertEquals(1, count($customer->orders));
$this->assertEquals(1, count($customer->populatedRelations));
$this->assertEquals(1, count($customer->relatedRecords));
}
public function testFindLazyVia()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment