mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-14 22:30:27 +08:00
finished draft implementation of new AR.
This commit is contained in:
@ -66,14 +66,15 @@ class ActiveQuery extends BaseQuery
|
||||
{
|
||||
$command = $this->createCommand();
|
||||
$rows = $command->queryAll();
|
||||
if ($rows === array()) {
|
||||
if ($rows !== array()) {
|
||||
$models = $this->createModels($rows);
|
||||
if (!empty($this->with)) {
|
||||
$this->fetchRelatedModels($models, $this->with);
|
||||
}
|
||||
return $models;
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
$models = $this->createModels($rows);
|
||||
if (!empty($this->with)) {
|
||||
$this->fetchRelatedModels($models, $this->with);
|
||||
}
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,11 +87,7 @@ class ActiveQuery extends BaseQuery
|
||||
{
|
||||
$command = $this->createCommand();
|
||||
$row = $command->queryRow();
|
||||
if ($row === false) {
|
||||
return false;
|
||||
} elseif ($this->asArray) {
|
||||
return $row;
|
||||
} else {
|
||||
if ($row !== false && !$this->asArray) {
|
||||
/** @var $class ActiveRecord */
|
||||
$class = $this->modelClass;
|
||||
$model = $class::create($row);
|
||||
@ -100,6 +97,8 @@ class ActiveQuery extends BaseQuery
|
||||
$model = $models[0];
|
||||
}
|
||||
return $model;
|
||||
} else {
|
||||
return $row === false ? null : $row;
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,17 +125,13 @@ class ActiveQuery extends BaseQuery
|
||||
|
||||
/**
|
||||
* Creates a DB command that can be used to execute this query.
|
||||
* @param Connection $db the database connection used to generate the SQL statement.
|
||||
* If this parameter is not given, the `db` application component will be used.
|
||||
* @return Command the created DB command instance.
|
||||
*/
|
||||
public function createCommand($db = null)
|
||||
public function createCommand()
|
||||
{
|
||||
/** @var $modelClass ActiveRecord */
|
||||
$modelClass = $this->modelClass;
|
||||
if ($db === null) {
|
||||
$db = $modelClass::getDbConnection();
|
||||
}
|
||||
$db = $modelClass::getDbConnection();
|
||||
if ($this->sql === null) {
|
||||
if ($this->from === null) {
|
||||
$tableName = $modelClass::tableName();
|
||||
|
@ -878,7 +878,7 @@ abstract class ActiveRecord extends Model
|
||||
public static function create($row)
|
||||
{
|
||||
$record = static::instantiate($row);
|
||||
$columns = static::model()->getTableSchema()->columns;
|
||||
$columns = static::getTableSchema()->columns;
|
||||
foreach ($row as $name => $value) {
|
||||
if (isset($columns[$name])) {
|
||||
$record->_attributes[$name] = $value;
|
||||
|
@ -59,12 +59,21 @@ class ActiveRelation extends ActiveQuery
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function createCommand($db = null)
|
||||
public function createCommand()
|
||||
{
|
||||
if ($this->primaryModel !== null) {
|
||||
$this->filterByPrimaryModels(array($this->primaryModel));
|
||||
if ($this->via !== null) {
|
||||
/** @var $viaQuery ActiveRelation */
|
||||
$viaName = $this->via;
|
||||
$viaQuery = $this->$viaName();
|
||||
$primaryModels = array($this->primaryModel);
|
||||
$viaModels = $viaQuery->findWith($viaName, $primaryModels);
|
||||
$this->filterByModels($viaModels);
|
||||
} else {
|
||||
$this->filterByModels(array($this->primaryModel));
|
||||
}
|
||||
}
|
||||
return parent::createCommand($db);
|
||||
return parent::createCommand();
|
||||
}
|
||||
|
||||
public function findWith($name, &$primaryModels)
|
||||
@ -74,44 +83,81 @@ class ActiveRelation extends ActiveQuery
|
||||
}
|
||||
|
||||
if ($this->via !== null) {
|
||||
/** @var $viaQuery ActiveRelation */
|
||||
$viaName = $this->via;
|
||||
$viaQuery = $this->$viaName();
|
||||
$viaModels = $viaQuery->findWith($viaName, $primaryModels);
|
||||
$this->filterByModels($viaModels);
|
||||
} else {
|
||||
$this->filterByModels($primaryModels);
|
||||
}
|
||||
|
||||
$this->filterByPrimaryModels($primaryModels);
|
||||
|
||||
if (count($primaryModels) === 1 && !$this->multiple) {
|
||||
$model = $this->one();
|
||||
foreach ($primaryModels as $i => $primaryModel) {
|
||||
$primaryModels[$i][$name] = $this->one();
|
||||
$primaryModels[$i][$name] = $model;
|
||||
}
|
||||
return array($model);
|
||||
} else {
|
||||
$models = $this->all();
|
||||
$this->bindModels($name, $primaryModels, $models);
|
||||
if (isset($viaModels, $viaQuery)) {
|
||||
$buckets = $this->buildBuckets($models, $this->link, $viaModels, $viaQuery->link);
|
||||
} else {
|
||||
$buckets = $this->buildBuckets($models, $this->link);
|
||||
}
|
||||
|
||||
foreach ($primaryModels as $i => $primaryModel) {
|
||||
if (isset($viaQuery)) {
|
||||
$key = $this->getModelKey($primaryModel, array_values($viaQuery->link));
|
||||
} else {
|
||||
$key = $this->getModelKey($primaryModel, array_values($this->link));
|
||||
}
|
||||
if (isset($buckets[$key])) {
|
||||
$primaryModels[$i][$name] = $buckets[$key];
|
||||
} else {
|
||||
$primaryModels[$i][$name] = $this->multiple ? array() : null;
|
||||
}
|
||||
}
|
||||
return $models;
|
||||
}
|
||||
}
|
||||
|
||||
protected function bindModels($name, &$primaryModels, $models)
|
||||
protected function buildBuckets($models, $link, $viaModels = null, $viaLink = null)
|
||||
{
|
||||
$buckets = array();
|
||||
foreach ($models as $i => $model) {
|
||||
$key = $this->getModelKey($model, array_keys($this->link));
|
||||
$key = $this->getModelKey($model, array_keys($link));
|
||||
if ($this->index !== null) {
|
||||
$buckets[$key][$i] = $model;
|
||||
} else {
|
||||
$buckets[$key][] = $model;
|
||||
}
|
||||
}
|
||||
|
||||
if ($viaModels !== null) {
|
||||
$viaBuckets = array();
|
||||
foreach ($viaModels as $viaModel) {
|
||||
$key1 = $this->getModelKey($viaModel, array_keys($viaLink));
|
||||
$key2 = $this->getModelKey($viaModel, array_values($link));
|
||||
if (isset($buckets[$key2])) {
|
||||
foreach ($buckets[$key2] as $i => $bucket) {
|
||||
if ($this->index !== null) {
|
||||
$viaBuckets[$key1][$i] = $bucket;
|
||||
} else {
|
||||
$viaBuckets[$key1][] = $bucket;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$buckets = $viaBuckets;
|
||||
}
|
||||
|
||||
if (!$this->multiple) {
|
||||
foreach ($buckets as $i => $bucket) {
|
||||
$buckets[$i] = reset($bucket);
|
||||
}
|
||||
}
|
||||
foreach ($primaryModels as $i => $primaryModel) {
|
||||
$key = $this->getModelKey($primaryModel, array_values($this->link));
|
||||
if (isset($buckets[$key])) {
|
||||
$primaryModels[$i][$name] = $buckets[$key];
|
||||
} else {
|
||||
$primaryModels[$i][$name] = $this->multiple ? array() : null;
|
||||
}
|
||||
}
|
||||
return $buckets;
|
||||
}
|
||||
|
||||
protected function getModelKey($model, $attributes)
|
||||
@ -128,13 +174,13 @@ class ActiveRelation extends ActiveQuery
|
||||
}
|
||||
}
|
||||
|
||||
protected function filterByPrimaryModels($primaryModels)
|
||||
protected function filterByModels($models)
|
||||
{
|
||||
$attributes = array_keys($this->link);
|
||||
$values = array();
|
||||
if (isset($links[1])) {
|
||||
// composite keys
|
||||
foreach ($primaryModels as $model) {
|
||||
foreach ($models as $model) {
|
||||
$v = array();
|
||||
foreach ($this->link as $attribute => $link) {
|
||||
$v[$attribute] = is_array($model) ? $model[$link] : $model->$link;
|
||||
@ -144,7 +190,7 @@ class ActiveRelation extends ActiveQuery
|
||||
} else {
|
||||
// single key
|
||||
$attribute = $this->link[$links[0]];
|
||||
foreach ($primaryModels as $model) {
|
||||
foreach ($models as $model) {
|
||||
$values[] = is_array($model) ? $model[$attribute] : $model->$attribute;
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,9 @@
|
||||
namespace yii\test;
|
||||
|
||||
require_once('PHPUnit/Runner/Version.php');
|
||||
spl_autoload_unregister(array('YiiBase','autoload'));
|
||||
require_once('PHPUnit/Autoload.php');
|
||||
spl_autoload_register(array('YiiBase','autoload')); // put yii's autoloader at the end
|
||||
|
||||
/**
|
||||
* TestCase is the base class for all test case classes.
|
||||
|
@ -22,7 +22,7 @@ class Customer extends ActiveRecord
|
||||
* @param ActiveQuery $query
|
||||
* @return ActiveQuery
|
||||
*/
|
||||
public function active($query)
|
||||
public static function active($query)
|
||||
{
|
||||
return $query->andWhere(array('status' => self::STATUS_ACTIVE));
|
||||
}
|
||||
|
@ -22,8 +22,9 @@ class Order extends ActiveRecord
|
||||
public function items()
|
||||
{
|
||||
return $this->hasMany('Item', array('id' => 'item_id'))
|
||||
->via('orderItems')
|
||||
->orderBy('id');
|
||||
->via('orderItems', function($q) {
|
||||
// additional query configuration
|
||||
})->orderBy('id');
|
||||
}
|
||||
|
||||
public function books()
|
||||
|
@ -7,7 +7,7 @@ class Foo extends \yii\base\Object
|
||||
public $prop;
|
||||
}
|
||||
|
||||
class Bar extends \yii\base\Component implements \yii\base\Initable
|
||||
class Bar extends \yii\base\Component
|
||||
{
|
||||
public $prop1;
|
||||
public $prop2;
|
||||
@ -41,30 +41,6 @@ class ObjectTest extends \yiiunit\TestCase
|
||||
$this->object = null;
|
||||
}
|
||||
|
||||
public function testNewInstance()
|
||||
{
|
||||
$foo = Foo::newInstance(array(
|
||||
'prop' => array(
|
||||
'test' => 'test',
|
||||
),
|
||||
));
|
||||
|
||||
$this->assertEquals('test', $foo->prop['test']);
|
||||
|
||||
$bar = Bar::newInstance(array(), 10, 20);
|
||||
$this->assertEquals(30, $bar->prop1);
|
||||
$this->assertEquals(null, $bar->prop2);
|
||||
$this->assertEquals(3, $bar->prop3);
|
||||
|
||||
$bar = Bar::newInstance(array(
|
||||
'prop2' => 'x',
|
||||
'prop3' => 400,
|
||||
), 100, 200);
|
||||
$this->assertEquals(300, $bar->prop1);
|
||||
$this->assertEquals('x', $bar->prop2);
|
||||
$this->assertEquals(3, $bar->prop3);
|
||||
}
|
||||
|
||||
public function testHasProperty()
|
||||
{
|
||||
$this->assertTrue($this->object->hasProperty('Text'), "Component hasn't property Text");
|
||||
@ -88,19 +64,19 @@ class ObjectTest extends \yiiunit\TestCase
|
||||
|
||||
public function testGetProperty()
|
||||
{
|
||||
$this->assertTrue('default'===$this->object->Text);
|
||||
$this->setExpectedException('yii\base\Exception');
|
||||
$value2=$this->object->Caption;
|
||||
$this->assertTrue('default' === $this->object->Text);
|
||||
$this->setExpectedException('yii\base\BadPropertyException');
|
||||
$value2 = $this->object->Caption;
|
||||
}
|
||||
|
||||
public function testSetProperty()
|
||||
{
|
||||
$value='new value';
|
||||
$this->object->Text=$value;
|
||||
$text=$this->object->Text;
|
||||
$this->assertTrue($value===$this->object->Text);
|
||||
$this->setExpectedException('yii\base\Exception');
|
||||
$this->object->NewMember=$value;
|
||||
$value = 'new value';
|
||||
$this->object->Text = $value;
|
||||
$text = $this->object->Text;
|
||||
$this->assertTrue($value === $this->object->Text);
|
||||
$this->setExpectedException('yii\base\BadPropertyException');
|
||||
$this->object->NewMember = $value;
|
||||
}
|
||||
|
||||
public function testIsset()
|
||||
@ -112,7 +88,7 @@ class ObjectTest extends \yiiunit\TestCase
|
||||
$this->assertFalse(isset($this->object->Text));
|
||||
$this->assertFalse(!empty($this->object->Text));
|
||||
|
||||
$this->object->Text='';
|
||||
$this->object->Text = '';
|
||||
$this->assertTrue(isset($this->object->Text));
|
||||
$this->assertTrue(empty($this->object->Text));
|
||||
}
|
||||
@ -131,20 +107,19 @@ class NewObject extends \yii\base\Component
|
||||
|
||||
public function setText($value)
|
||||
{
|
||||
$this->_text=$value;
|
||||
$this->_text = $value;
|
||||
}
|
||||
|
||||
public function getObject()
|
||||
{
|
||||
if(!$this->_object)
|
||||
{
|
||||
$this->_object=new self;
|
||||
$this->_object->_text='object text';
|
||||
if (!$this->_object) {
|
||||
$this->_object = new self;
|
||||
$this->_object->_text = 'object text';
|
||||
}
|
||||
return $this->_object;
|
||||
}
|
||||
|
||||
public function exprEvaluator($p1,$comp)
|
||||
public function exprEvaluator($p1, $comp)
|
||||
{
|
||||
return "Hello $p1";
|
||||
}
|
||||
|
Reference in New Issue
Block a user