diff --git a/extensions/yii/elasticsearch/ActiveQuery.php b/extensions/yii/elasticsearch/ActiveQuery.php index 2a282d3..d67327c 100644 --- a/extensions/yii/elasticsearch/ActiveQuery.php +++ b/extensions/yii/elasticsearch/ActiveQuery.php @@ -92,7 +92,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface } /** @var ActiveRecord $modelClass */ $modelClass = $this->modelClass; - $pk = $modelClass::primaryKey(); + $pk = $modelClass::primaryKey()[0]; if ($this->asArray && $this->indexBy) { foreach ($result['hits']['hits'] as &$row) { if ($pk === '_id') { @@ -136,7 +136,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface /** @var ActiveRecord $modelClass */ $modelClass = $this->modelClass; $model = $result['_source']; - $pk = $modelClass::primaryKey(); + $pk = $modelClass::primaryKey()[0]; if ($pk === '_id') { $model['_id'] = $result['_id']; } @@ -165,7 +165,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface if ($this->asArray) { /** @var ActiveRecord $modelClass */ $modelClass = $this->modelClass; - $pk = $modelClass::primaryKey(); + $pk = $modelClass::primaryKey()[0]; foreach($models as $key => $model) { if ($pk === '_id') { $model['_source']['_id'] = $model['_id']; diff --git a/extensions/yii/elasticsearch/ActiveRecord.php b/extensions/yii/elasticsearch/ActiveRecord.php index 29d62f3..df50039 100644 --- a/extensions/yii/elasticsearch/ActiveRecord.php +++ b/extensions/yii/elasticsearch/ActiveRecord.php @@ -171,7 +171,7 @@ class ActiveRecord extends BaseActiveRecord */ public function setPrimaryKey($value) { - $pk = static::primaryKey(); + $pk = static::primaryKey()[0]; if ($this->getIsNewRecord() || $pk != '_id') { $this->$pk = $value; } else { @@ -184,7 +184,7 @@ class ActiveRecord extends BaseActiveRecord */ public function getPrimaryKey($asArray = false) { - $pk = static::primaryKey(); + $pk = static::primaryKey()[0]; if ($asArray) { return [$pk => $this->$pk]; } else { @@ -197,7 +197,7 @@ class ActiveRecord extends BaseActiveRecord */ public function getOldPrimaryKey($asArray = false) { - $pk = static::primaryKey(); + $pk = static::primaryKey()[0]; if ($this->getIsNewRecord()) { $id = null; } elseif ($pk == '_id') { @@ -213,21 +213,37 @@ class ActiveRecord extends BaseActiveRecord } /** - * This method defines the primary. + * This method defines the attribute that uniquely identifies a record. * - * The primaryKey for elasticsearch documents is always `primaryKey`. It can not be changed. + * The primaryKey for elasticsearch documents is the `_id` field by default. This field is not part of the + * ActiveRecord attributes so you should never add `_id` to the list of [[attributes()|attributes]]. * - * @return string the primary key of this record. + * You may overide this method to define the primary key name when you have defined + * [path mapping](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-id-field.html) + * for the `_id` field so that it is part of the `_source` and thus part of the [[attributes()|attributes]]. + * + * Note that elasticsearch only supports _one_ attribute to be the primary key. However to match the signature + * of the [[\yii\db\ActiveRecordInterface|ActiveRecordInterface]] this methods returns an array instead of a + * single string. + * + * @return string[] array of primary key attributes. Only the first element of the array will be used. */ public static function primaryKey() { - return '_id'; + return ['_id']; } /** * Returns the list of all attribute names of the model. + * * This method must be overridden by child classes to define available attributes. - * @return array list of attribute names. + * + * Attributes are names of fields of the corresponding elasticsearch document. + * The primaryKey for elasticsearch documents is the `_id` field by default which is not part of the attributes. + * You may define [path mapping](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-id-field.html) + * for the `_id` field so that it is part of the `_source` fields and thus becomes part of the attributes. + * + * @return string[] list of attribute names. */ public function attributes() { @@ -260,7 +276,7 @@ class ActiveRecord extends BaseActiveRecord public static function create($row) { $record = parent::create($row['_source']); - $pk = static::primaryKey(); + $pk = static::primaryKey()[0]; $record->$pk = $row['_id']; $record->_score = isset($row['_score']) ? $row['_score'] : null; $record->_version = isset($row['_version']) ? $row['_version'] : null; // TODO version should always be available... @@ -336,8 +352,11 @@ class ActiveRecord extends BaseActiveRecord if (!isset($response['ok'])) { return false; } - $pk = static::primaryKey(); - $values[$pk] = $this->$pk = $response['_id']; + $pk = static::primaryKey()[0]; + $this->$pk = $response['_id']; + if ($pk != '_id') { + $values[$pk] = $response['_id']; + } $this->_version = $response['_version']; $this->_score = null; $this->setOldAttributes($values); @@ -362,9 +381,9 @@ class ActiveRecord extends BaseActiveRecord */ public static function updateAll($attributes, $condition = []) { - $pkName = static::primaryKey(); + $pkName = static::primaryKey()[0]; if (count($condition) == 1 && isset($condition[$pkName])) { - $primaryKeys = (array) $condition[$pkName]; + $primaryKeys = is_array($condition[$pkName]) ? $condition[$pkName] : [$condition[$pkName]]; } else { $primaryKeys = static::find()->where($condition)->column($pkName); // TODO check whether this works with default pk _id } @@ -372,7 +391,7 @@ class ActiveRecord extends BaseActiveRecord return 0; } $bulk = ''; - foreach((array) $primaryKeys as $pk) { + foreach($primaryKeys as $pk) { $action = Json::encode([ "update" => [ "_id" => $pk, @@ -420,9 +439,9 @@ class ActiveRecord extends BaseActiveRecord */ public static function updateAllCounters($counters, $condition = []) { - $pkName = static::primaryKey(); + $pkName = static::primaryKey()[0]; if (count($condition) == 1 && isset($condition[$pkName])) { - $primaryKeys = (array) $condition[$pkName]; + $primaryKeys = is_array($condition[$pkName]) ? $condition[$pkName] : [$condition[$pkName]]; } else { $primaryKeys = static::find()->where($condition)->column($pkName); // TODO check whether this works with default pk _id } @@ -430,7 +449,7 @@ class ActiveRecord extends BaseActiveRecord return 0; } $bulk = ''; - foreach((array) $primaryKeys as $pk) { + foreach($primaryKeys as $pk) { $action = Json::encode([ "update" => [ "_id" => $pk, @@ -478,9 +497,9 @@ class ActiveRecord extends BaseActiveRecord */ public static function deleteAll($condition = []) { - $pkName = static::primaryKey(); + $pkName = static::primaryKey()[0]; if (count($condition) == 1 && isset($condition[$pkName])) { - $primaryKeys = (array) $condition[$pkName]; + $primaryKeys = is_array($condition[$pkName]) ? $condition[$pkName] : [$condition[$pkName]]; } else { $primaryKeys = static::find()->where($condition)->column($pkName); // TODO check whether this works with default pk _id } @@ -488,7 +507,7 @@ class ActiveRecord extends BaseActiveRecord return 0; } $bulk = ''; - foreach((array) $primaryKeys as $pk) { + foreach($primaryKeys as $pk) { $bulk .= Json::encode([ "delete" => [ "_id" => $pk, diff --git a/extensions/yii/gii/generators/crud/Generator.php b/extensions/yii/gii/generators/crud/Generator.php index 7e0e671..bbd2ab5 100644 --- a/extensions/yii/gii/generators/crud/Generator.php +++ b/extensions/yii/gii/generators/crud/Generator.php @@ -176,7 +176,7 @@ class Generator extends \yii\gii\Generator /** @var \yii\db\ActiveRecord $class */ $class = $this->modelClass; $pk = $class::primaryKey(); - return is_array($pk) ? $pk[0] : $pk; + return $pk[0]; } /** @@ -363,7 +363,7 @@ class Generator extends \yii\gii\Generator { /** @var ActiveRecord $class */ $class = $this->modelClass; - $pks = (array) $class::primaryKey(); + $pks = $class::primaryKey(); if (count($pks) === 1) { return "'id' => \$model->{$pks[0]}"; } else { @@ -379,7 +379,7 @@ class Generator extends \yii\gii\Generator { /** @var ActiveRecord $class */ $class = $this->modelClass; - $pks = (array) $class::primaryKey(); + $pks = $class::primaryKey(); if (count($pks) === 1) { return '$id'; } else { @@ -391,7 +391,7 @@ class Generator extends \yii\gii\Generator { /** @var ActiveRecord $class */ $class = $this->modelClass; - $pks = (array) $class::primaryKey(); + $pks = $class::primaryKey(); if (($table = $this->getTableSchema()) === false) { $params = []; foreach ($pks as $pk) { diff --git a/extensions/yii/gii/generators/crud/templates/controller.php b/extensions/yii/gii/generators/crud/templates/controller.php index 7430b78..bb5d3f4 100644 --- a/extensions/yii/gii/generators/crud/templates/controller.php +++ b/extensions/yii/gii/generators/crud/templates/controller.php @@ -19,7 +19,7 @@ if ($modelClass === $searchModelClass) { /** @var ActiveRecordInterface $class */ $class = $generator->modelClass; -$pks = (array) $class::primaryKey(); +$pks = $class::primaryKey(); $urlParams = $generator->generateUrlParams(); $actionParams = $generator->generateActionParams(); $actionParamComments = $generator->generateActionParamComments(); diff --git a/framework/yii/data/ActiveDataProvider.php b/framework/yii/data/ActiveDataProvider.php index e1175a8..2292286 100644 --- a/framework/yii/data/ActiveDataProvider.php +++ b/framework/yii/data/ActiveDataProvider.php @@ -128,7 +128,7 @@ class ActiveDataProvider extends BaseDataProvider } elseif ($this->query instanceof ActiveQueryInterface) { /** @var \yii\db\ActiveRecord $class */ $class = $this->query->modelClass; - $pks = (array) $class::primaryKey(); + $pks = $class::primaryKey(); if (count($pks) === 1) { $pk = $pks[0]; foreach ($models as $model) { diff --git a/framework/yii/db/BaseActiveRecord.php b/framework/yii/db/BaseActiveRecord.php index 133c9b6..4219507 100644 --- a/framework/yii/db/BaseActiveRecord.php +++ b/framework/yii/db/BaseActiveRecord.php @@ -1273,7 +1273,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface */ public static function isPrimaryKey($keys) { - $pks = (array) static::primaryKey(); + $pks = static::primaryKey(); if (count($keys) === count($pks)) { return count(array_intersect($keys, $pks)) === count($pks); } else { diff --git a/framework/yii/validators/UniqueValidator.php b/framework/yii/validators/UniqueValidator.php index 55c96cf..51474b0 100644 --- a/framework/yii/validators/UniqueValidator.php +++ b/framework/yii/validators/UniqueValidator.php @@ -101,7 +101,7 @@ class UniqueValidator extends Validator $n = count($objects); if ($n === 1) { $keys = array_keys($params); - $pks = (array) $targetClass::primaryKey(); + $pks = $targetClass::primaryKey(); sort($keys); sort($pks); if ($keys === $pks) { diff --git a/tests/unit/data/ar/elasticsearch/Customer.php b/tests/unit/data/ar/elasticsearch/Customer.php index 1ff1cef..22d2c09 100644 --- a/tests/unit/data/ar/elasticsearch/Customer.php +++ b/tests/unit/data/ar/elasticsearch/Customer.php @@ -22,7 +22,7 @@ class Customer extends ActiveRecord public static function primaryKey() { - return 'id'; + return ['id']; } public function attributes() diff --git a/tests/unit/data/ar/elasticsearch/Item.php b/tests/unit/data/ar/elasticsearch/Item.php index 2474f60..033c38d 100644 --- a/tests/unit/data/ar/elasticsearch/Item.php +++ b/tests/unit/data/ar/elasticsearch/Item.php @@ -14,7 +14,7 @@ class Item extends ActiveRecord { public static function primaryKey() { - return 'id'; + return ['id']; } public function attributes() diff --git a/tests/unit/data/ar/elasticsearch/Order.php b/tests/unit/data/ar/elasticsearch/Order.php index 41d05f7..e7607cd 100644 --- a/tests/unit/data/ar/elasticsearch/Order.php +++ b/tests/unit/data/ar/elasticsearch/Order.php @@ -15,7 +15,7 @@ class Order extends ActiveRecord { public static function primaryKey() { - return 'id'; + return ['id']; } public function attributes() diff --git a/tests/unit/extensions/elasticsearch/ActiveRecordTest.php b/tests/unit/extensions/elasticsearch/ActiveRecordTest.php index 89431aa..2d31792 100644 --- a/tests/unit/extensions/elasticsearch/ActiveRecordTest.php +++ b/tests/unit/extensions/elasticsearch/ActiveRecordTest.php @@ -251,7 +251,7 @@ class ActiveRecordTest extends ElasticSearchTestCase public function testInsertNoPk() { - $this->assertEquals('id', Customer::primaryKey()); + $this->assertEquals(['id'], Customer::primaryKey()); $pkName = 'id'; $customer = new Customer;