From 16e1aff41b29ff935cf469d06168b552ffabeb46 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Mon, 3 Feb 2014 14:01:29 +0100 Subject: [PATCH 1/2] renamed ActiveRecord::create() to populateRecord() - refactored elasticsearch AR to make type and index available in instantiate(), issue #1313 fixes #2281 --- extensions/elasticsearch/ActiveQuery.php | 3 +- extensions/elasticsearch/ActiveRecord.php | 40 ++++++++++++++++------- extensions/elasticsearch/CHANGELOG.md | 2 ++ extensions/mongodb/ActiveQuery.php | 3 +- extensions/mongodb/file/ActiveQuery.php | 3 +- extensions/redis/ActiveQuery.php | 3 +- extensions/redis/CHANGELOG.md | 1 + extensions/sphinx/ActiveQuery.php | 3 +- extensions/sphinx/ActiveRecord.php | 11 ++----- extensions/sphinx/CHANGELOG.md | 1 + framework/CHANGELOG.md | 1 + framework/db/ActiveQuery.php | 3 +- framework/db/ActiveQueryTrait.php | 7 ++-- framework/db/ActiveRecord.php | 5 ++- framework/db/BaseActiveRecord.php | 19 +++++------ 15 files changed, 65 insertions(+), 40 deletions(-) diff --git a/extensions/elasticsearch/ActiveQuery.php b/extensions/elasticsearch/ActiveQuery.php index 89661e9f2e..d2f7e74466 100644 --- a/extensions/elasticsearch/ActiveQuery.php +++ b/extensions/elasticsearch/ActiveQuery.php @@ -152,7 +152,8 @@ class ActiveQuery extends Query implements ActiveQueryInterface } else { /** @var ActiveRecord $class */ $class = $this->modelClass; - $model = $class::create($result); + $model = $class::instantiate($result); + $class::populateRecord($model, $result); } if (!empty($this->with)) { $models = [$model]; diff --git a/extensions/elasticsearch/ActiveRecord.php b/extensions/elasticsearch/ActiveRecord.php index b343c59d70..1965d3d6c2 100644 --- a/extensions/elasticsearch/ActiveRecord.php +++ b/extensions/elasticsearch/ActiveRecord.php @@ -94,7 +94,8 @@ class ActiveRecord extends BaseActiveRecord $command = static::getDb()->createCommand(); $result = $command->get(static::index(), static::type(), $primaryKey, $options); if ($result['exists']) { - $model = static::create($result); + $model = static::instantiate($result); + static::populateRecord($model, $result); $model->afterFind(); return $model; } @@ -123,7 +124,8 @@ class ActiveRecord extends BaseActiveRecord $models = []; foreach($result['docs'] as $doc) { if ($doc['exists']) { - $model = static::create($doc); + $model = static::instantiate($doc); + static::populateRecord($model, $doc); $model->afterFind(); $models[] = $model; } @@ -264,22 +266,38 @@ class ActiveRecord extends BaseActiveRecord } /** - * Creates an active record object using a row of data. - * This method is called by [[ActiveQuery]] to populate the query results - * into Active Records. It is not meant to be used to create new records. - * @param array $row attribute values (name => value) - * @return ActiveRecord the newly created active record. + * @inheritdoc */ - public static function create($row) + public static function populateRecord($record, $row) { - $record = parent::create($row['_source']); + parent::populateRecord($record, $row['_source']); $pk = static::primaryKey()[0]; if ($pk === '_id') { - $record->$pk = $row['_id']; + $record->_id = $row['_id']; } $record->_score = isset($row['_score']) ? $row['_score'] : null; $record->_version = isset($row['_version']) ? $row['_version'] : null; // TODO version should always be available... - return $record; + } + + /** + * Creates an active record instance. + * + * This method is called together with [[populateRecord()]] by [[ActiveQuery]]. + * + * You may override this method if the instance being created + * depends on the row data to be populated into the record. + * For example, by creating a record based on the value of a column, + * you may implement the so-called single-table inheritance mapping. + * @param array $row row data to be populated into the record. + * This array consists of the following keys: + * - `_source`: refers to the attributes of the record. + * - `_type`: the type this record is stored in. + * - `_index`: the index this record is stored in. + * @return static the newly created active record + */ + public static function instantiate($row) + { + return new static; } /** diff --git a/extensions/elasticsearch/CHANGELOG.md b/extensions/elasticsearch/CHANGELOG.md index aad9d614fd..483b05642b 100644 --- a/extensions/elasticsearch/CHANGELOG.md +++ b/extensions/elasticsearch/CHANGELOG.md @@ -5,9 +5,11 @@ Yii Framework 2 elasticsearch extension Change Log ---------------------------- - Bug #1993: afterFind event in AR is now called after relations have been populated (cebe, creocoder) +- Enh #1313: made index and type available in `ActiveRecord::instantiate()` to allow creating records based on elasticsearch type when doing cross index/type search (cebe) - Enh #1382: Added a debug toolbar panel for elasticsearch (cebe) - Enh #1765: Added support for primary key path mapping, pk can now be part of the attributes when mapping is defined (cebe) - Chg #1765: Changed handling of ActiveRecord primary keys, removed getId(), use getPrimaryKey() instead (cebe) +- Chg #2281: Renamed `ActiveRecord::create()` to `populateRecord()` and changed signature. This method will not call instantiate() anymore (cebe) 2.0.0 alpha, December 1, 2013 ----------------------------- diff --git a/extensions/mongodb/ActiveQuery.php b/extensions/mongodb/ActiveQuery.php index 7b07085e35..cf7db82acb 100644 --- a/extensions/mongodb/ActiveQuery.php +++ b/extensions/mongodb/ActiveQuery.php @@ -81,7 +81,8 @@ class ActiveQuery extends Query implements ActiveQueryInterface } else { /** @var ActiveRecord $class */ $class = $this->modelClass; - $model = $class::create($row); + $model = $class::instantiate($row); + $class::populateRecord($model, $row); } if (!empty($this->with)) { $models = [$model]; diff --git a/extensions/mongodb/file/ActiveQuery.php b/extensions/mongodb/file/ActiveQuery.php index 8eab080b2f..f89d20170d 100644 --- a/extensions/mongodb/file/ActiveQuery.php +++ b/extensions/mongodb/file/ActiveQuery.php @@ -81,7 +81,8 @@ class ActiveQuery extends Query implements ActiveQueryInterface } else { /** @var ActiveRecord $class */ $class = $this->modelClass; - $model = $class::create($row); + $model = $class::instantiate($row); + $class::populateRecord($model, $row); } if (!empty($this->with)) { $models = [$model]; diff --git a/extensions/redis/ActiveQuery.php b/extensions/redis/ActiveQuery.php index d79a144449..6ce8a4bf42 100644 --- a/extensions/redis/ActiveQuery.php +++ b/extensions/redis/ActiveQuery.php @@ -112,7 +112,8 @@ class ActiveQuery extends \yii\base\Component implements ActiveQueryInterface } else { /** @var ActiveRecord $class */ $class = $this->modelClass; - $model = $class::create($row); + $model = $class::instantiate($row); + $class::populateRecord($model, $row); } if (!empty($this->with)) { $models = [$model]; diff --git a/extensions/redis/CHANGELOG.md b/extensions/redis/CHANGELOG.md index 9a39115a03..f6741f0f6e 100644 --- a/extensions/redis/CHANGELOG.md +++ b/extensions/redis/CHANGELOG.md @@ -6,6 +6,7 @@ Yii Framework 2 redis extension Change Log - Bug #1993: afterFind event in AR is now called after relations have been populated (cebe, creocoder) - Enh #1773: keyPrefix property of Session and Cache is not restricted to alnum characters anymore (cebe) +- Chg #2281: Renamed `ActiveRecord::create()` to `populateRecord()` and changed signature. This method will not call instantiate() anymore (cebe) 2.0.0 alpha, December 1, 2013 ----------------------------- diff --git a/extensions/sphinx/ActiveQuery.php b/extensions/sphinx/ActiveQuery.php index 2821c9802c..a846f6a164 100644 --- a/extensions/sphinx/ActiveQuery.php +++ b/extensions/sphinx/ActiveQuery.php @@ -139,7 +139,8 @@ class ActiveQuery extends Query implements ActiveQueryInterface } else { /** @var $class ActiveRecord */ $class = $this->modelClass; - $model = $class::create($row); + $model = $class::instantiate($row); + $class::populateRecord($model, $row); } if (!empty($this->with)) { $models = [$model]; diff --git a/extensions/sphinx/ActiveRecord.php b/extensions/sphinx/ActiveRecord.php index 8037c54453..4c1092c82a 100644 --- a/extensions/sphinx/ActiveRecord.php +++ b/extensions/sphinx/ActiveRecord.php @@ -619,15 +619,11 @@ abstract class ActiveRecord extends BaseActiveRecord } /** - * Creates an active record object using a row of data. - * This method is called by [[ActiveQuery]] to populate the query results - * into Active Records. It is not meant to be used to create new records. - * @param array $row attribute values (name => value) - * @return ActiveRecord the newly created active record. + * @inheritdoc */ - public static function create($row) + public static function populateRecord($record, $row) { - $record = static::instantiate($row); + // TODO refactor to call parent $columns = static::getIndexSchema()->columns; foreach ($row as $name => $value) { if (isset($columns[$name])) { @@ -641,7 +637,6 @@ abstract class ActiveRecord extends BaseActiveRecord } } $record->setOldAttributes($record->getAttributes()); - return $record; } /** diff --git a/extensions/sphinx/CHANGELOG.md b/extensions/sphinx/CHANGELOG.md index 63d05b83af..2f7f0fdb5f 100644 --- a/extensions/sphinx/CHANGELOG.md +++ b/extensions/sphinx/CHANGELOG.md @@ -7,6 +7,7 @@ Yii Framework 2 sphinx extension Change Log - Bug #1993: afterFind event in AR is now called after relations have been populated (cebe, creocoder) - Bug #2160: SphinxQL does not support OFFSET (qiangxue, romeo7) - Enh #1398: Refactor ActiveRecord to use BaseActiveRecord class of the framework (klimov-paul) +- Chg #2281: Renamed `ActiveRecord::create()` to `populateRecord()` and changed signature. This method will not call instantiate() anymore (cebe) 2.0.0 alpha, December 1, 2013 ----------------------------- diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index bcd96c9c13..fd074aa628 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -142,6 +142,7 @@ Yii Framework 2 Change Log - Chg #2175: QueryBuilder will now append UNION statements at the end of the primary SQL (qiangxue) - Chg #2210: Mysql driver will now treat `tinyint(1)` as integer instead of boolean (qiangxue) - Chg #2248: Renamed `yii\base\Model::DEFAULT_SCENARIO` to `yii\base\Model::SCENARIO_DEFAULT` (samdark) +- Chg #2281: Renamed `ActiveRecord::create()` to `populateRecord()` and changed signature. This method will not call instantiate() anymore (cebe) - Chg: Renamed `yii\jui\Widget::clientEventsMap` to `clientEventMap` (qiangxue) - Chg: Renamed `ActiveRecord::getPopulatedRelations()` to `getRelatedRecords()` (qiangxue) - Chg: Renamed `attributeName` and `className` to `targetAttribute` and `targetClass` for `UniqueValidator` and `ExistValidator` (qiangxue) diff --git a/framework/db/ActiveQuery.php b/framework/db/ActiveQuery.php index df78e87994..0a26b40a98 100644 --- a/framework/db/ActiveQuery.php +++ b/framework/db/ActiveQuery.php @@ -144,7 +144,8 @@ class ActiveQuery extends Query implements ActiveQueryInterface } else { /** @var ActiveRecord $class */ $class = $this->modelClass; - $model = $class::create($row); + $model = $class::instantiate($row); + $class::populateRecord($model, $row); } if (!empty($this->with)) { $models = [$model]; diff --git a/framework/db/ActiveQueryTrait.php b/framework/db/ActiveQueryTrait.php index 4444f3426e..c82bd33a20 100644 --- a/framework/db/ActiveQueryTrait.php +++ b/framework/db/ActiveQueryTrait.php @@ -128,11 +128,14 @@ trait ActiveQueryTrait $class = $this->modelClass; if ($this->indexBy === null) { foreach ($rows as $row) { - $models[] = $class::create($row); + $model = $class::instantiate($row); + $class::populateRecord($model, $row); + $models[] = $model; } } else { foreach ($rows as $row) { - $model = $class::create($row); + $model = $class::instantiate($row); + $class::populateRecord($model, $row); if (is_string($this->indexBy)) { $key = $model->{$this->indexBy}; } else { diff --git a/framework/db/ActiveRecord.php b/framework/db/ActiveRecord.php index e3a9a323bf..eec6c0cf1c 100644 --- a/framework/db/ActiveRecord.php +++ b/framework/db/ActiveRecord.php @@ -277,9 +277,9 @@ class ActiveRecord extends BaseActiveRecord /** * @inheritdoc */ - public static function create($row) + public static function populateRecord($record, $row) { - $record = static::instantiate($row); + // TODO refactor to call parent $attributes = array_flip($record->attributes()); $columns = static::getTableSchema()->columns; foreach ($row as $name => $value) { @@ -293,7 +293,6 @@ class ActiveRecord extends BaseActiveRecord } } $record->setOldAttributes($record->getAttributes()); - return $record; } /** diff --git a/framework/db/BaseActiveRecord.php b/framework/db/BaseActiveRecord.php index 54d94453e4..8deaac17e1 100644 --- a/framework/db/BaseActiveRecord.php +++ b/framework/db/BaseActiveRecord.php @@ -984,23 +984,21 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface } /** - * Creates an active record object using a row of data from the database/storage. + * Populates an active record object using a row of data from the database/storage. * - * This method is *not* meant to be used to create new records. - * - * It is an internal method meant to be called to create active record objects after + * This is an internal method meant to be called to create active record objects after * fetching data from the database. It is mainly used by [[ActiveQuery]] to populate - * the query results into Active Records. + * the query results into active records. * * When calling this method manually you should call [[afterFind()]] on the created * record to trigger the [[EVENT_AFTER_FIND|afterFind Event]]. * + * @param BaseActiveRecord $record the record to be populated. In most cases this will be an instance + * created by [[instantiate()]] beforehand. * @param array $row attribute values (name => value) - * @return static the newly created active record. */ - public static function create($row) + public static function populateRecord($record, $row) { - $record = static::instantiate($row); $columns = array_flip($record->attributes()); foreach ($row as $name => $value) { if (isset($columns[$name])) { @@ -1010,12 +1008,13 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface } } $record->_oldAttributes = $record->_attributes; - return $record; } /** * Creates an active record instance. - * This method is called by [[create()]]. + * + * This method is called together with [[populateRecord()]] by [[ActiveQuery]]. + * * You may override this method if the instance being created * depends on the row data to be populated into the record. * For example, by creating a record based on the value of a column, From 4a9f47beddd1a917195e4326103db00e1e621d72 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Mon, 3 Feb 2014 14:12:03 +0100 Subject: [PATCH 2/2] refactored sphinx and db AR to call parent implementation of populateRecord() --- extensions/sphinx/ActiveRecord.php | 13 +++---------- framework/db/ActiveRecord.php | 11 ++--------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/extensions/sphinx/ActiveRecord.php b/extensions/sphinx/ActiveRecord.php index 4c1092c82a..35764a0108 100644 --- a/extensions/sphinx/ActiveRecord.php +++ b/extensions/sphinx/ActiveRecord.php @@ -623,20 +623,13 @@ abstract class ActiveRecord extends BaseActiveRecord */ public static function populateRecord($record, $row) { - // TODO refactor to call parent $columns = static::getIndexSchema()->columns; foreach ($row as $name => $value) { - if (isset($columns[$name])) { - $column = $columns[$name]; - if ($column->isMva) { - $value = explode(',', $value); - } - $record->setAttribute($name, $value); - } else { - $record->$name = $value; + if (isset($columns[$name]) && $columns[$name]->isMva) { + $row[$name] = explode(',', $value); } } - $record->setOldAttributes($record->getAttributes()); + parent::populateRecord($record, $row); } /** diff --git a/framework/db/ActiveRecord.php b/framework/db/ActiveRecord.php index eec6c0cf1c..ad36b27945 100644 --- a/framework/db/ActiveRecord.php +++ b/framework/db/ActiveRecord.php @@ -279,20 +279,13 @@ class ActiveRecord extends BaseActiveRecord */ public static function populateRecord($record, $row) { - // TODO refactor to call parent - $attributes = array_flip($record->attributes()); $columns = static::getTableSchema()->columns; foreach ($row as $name => $value) { if (isset($columns[$name])) { - $value = $columns[$name]->typecast($value); - } - if (isset($attributes[$name])) { - $record->setAttribute($name, $value); - } else { - $record->$name = $value; + $row[$name] = $columns[$name]->typecast($value); } } - $record->setOldAttributes($record->getAttributes()); + parent::populateRecord($record, $row); } /**