| public primaryKey( ): array |
public function primaryKey(): array
{
return $this->tableSchema()->getPrimaryKey();
}
| Inheritance | Yiisoft\ActiveRecord\ActiveRecord » Yiisoft\ActiveRecord\AbstractActiveRecord |
|---|---|
| Implements | Yiisoft\ActiveRecord\ActiveRecordInterface |
Active Record class which implements Yiisoft\ActiveRecord\ActiveRecordInterface interface with the minimum set of methods.
Active Record implements the Active Record design pattern.
The premise behind Active Record is that an individual Yiisoft\ActiveRecord\ActiveRecord object is associated with a specific row in a database table. The object's properties are mapped to the columns of the corresponding table.
Referencing an Active Record property is equivalent to accessing the corresponding table column for that record.
As an example, say that the Customer ActiveRecord class is associated with the customer table.
This would mean that the class's name property is automatically mapped to the name column in customer table.
Thanks to Active Record, assuming the variable $customer is an object of type Customer, to get the value of the
name column for the table row, you can use the expression $customer->name.
In this example, Active Record is providing an object-oriented interface for accessing data stored in the database. But Active Record provides much more functionality than this.
To declare an ActiveRecord class, you need to extend Yiisoft\ActiveRecord\ActiveRecord and implement the tableName method:
class Customer extends ActiveRecord
{
public static function tableName(): string
{
return 'customer';
}
}
The tableName method only has to return the name of the database table associated with the class.
Class instances are obtained in one of two ways:
Using the new operator to create a new, empty object.
Using a method to fetch an existing record (or records) from the database.
Below is an example showing some typical usage of ActiveRecord:
$user = new User();
$user->name = 'Qiang';
$user->save(); // a new row is inserted into user table
// the following will retrieve the user 'CeBe' from the database
$user = User::query()->where(['name' => 'CeBe'])->one();
// this will get related records from orders table when relation is defined
$orders = $user->orders;
For more details and usage information on ActiveRecord, \Yiisoft\ActiveRecord\the guide article on ActiveRecord
| public assignOldValue( string $propertyName, mixed $value ): void | ||
| $propertyName | string | |
| $value | mixed | |
public function assignOldValue(string $propertyName, mixed $value): void
{
if (isset($this->oldValues[$propertyName]) || $this->hasProperty($propertyName)) {
$this->oldValues[$propertyName] = $value;
} else {
throw new InvalidArgumentException(static::class . ' has no property named "' . $propertyName . '".');
}
}
| public assignOldValues( array|null $propertyValues = null ): void | ||
| $propertyValues | array|null | |
public function assignOldValues(?array $propertyValues = null): void
{
$this->oldValues = $propertyValues;
}
| public column( string $propertyName ): \Yiisoft\Db\Schema\Column\ColumnInterface | ||
| $propertyName | string | |
public function column(string $propertyName): ColumnInterface
{
return $this->tableSchema()->getColumn($propertyName)
?? $this->db()->getColumnFactory()->fromType(ColumnType::STRING, ['name' => $propertyName]);
}
| public createQuery( Yiisoft\ActiveRecord\ActiveRecordInterface|string|null $modelClass = null ): Yiisoft\ActiveRecord\ActiveQueryInterface | ||
| $modelClass | Yiisoft\ActiveRecord\ActiveRecordInterface|string|null | |
public function createQuery(ActiveRecordInterface|string|null $modelClass = null): ActiveQueryInterface
{
return static::query($modelClass ?? $this);
}
Defined in: Yiisoft\ActiveRecord\AbstractActiveRecord::createRelationQuery()
Creates a query instance for has-one or has-many relation.
See also:
| protected createRelationQuery( Yiisoft\ActiveRecord\ActiveRecordInterface|string $modelClass, array $link, boolean $multiple ): Yiisoft\ActiveRecord\ActiveQueryInterface | ||
| $modelClass | Yiisoft\ActiveRecord\ActiveRecordInterface|string |
The class name of the related record. |
| $link | array |
The primary-foreign key constraint. |
| $multiple | boolean |
Whether this query represents a relation to more than one record. |
| return | Yiisoft\ActiveRecord\ActiveQueryInterface |
The relational query object. |
|---|---|---|
protected function createRelationQuery(
ActiveRecordInterface|string $modelClass,
array $link,
bool $multiple,
): ActiveQueryInterface {
return $this->createQuery($modelClass)->primaryModel($this)->link($link)->multiple($multiple);
}
Defined in: Yiisoft\ActiveRecord\AbstractActiveRecord::db()
| public db( ): \Yiisoft\Db\Connection\ConnectionInterface |
public function db(): ConnectionInterface
{
return ConnectionProvider::get();
}
| public deleteAll( array $condition = [], array $params = [] ): integer | ||
| $condition | array | |
| $params | array | |
public function deleteAll(array $condition = [], array $params = []): int
{
$command = $this->db()->createCommand();
$command->delete($this->tableName(), $condition, $params);
return $command->execute();
}
Defined in: Yiisoft\ActiveRecord\AbstractActiveRecord::deleteInternal()
See also Yiisoft\ActiveRecord\AbstractActiveRecord::delete().
| protected deleteInternal( ): integer | ||
| return | integer |
The number of rows deleted. |
|---|---|---|
| throws | \Yiisoft\Db\Exception\Exception | |
| throws | Throwable | |
protected function deleteInternal(): int
{
/**
* We don't check the return value of deleteAll() because it is possible the record is already deleted in
* the database and thus the method will return 0
*/
$condition = $this->primaryKeyOldValues();
if ($this instanceof OptimisticLockInterface) {
$lock = $this->optimisticLockPropertyName();
$condition[$lock] = $this->get($lock);
$result = $this->deleteAll($condition);
if ($result === 0) {
throw new OptimisticLockException(
'The object being deleted is outdated.',
);
}
} else {
$result = $this->deleteAll($condition);
}
$this->assignOldValues();
return $result;
}
| public equals( Yiisoft\ActiveRecord\ActiveRecordInterface $record ): boolean | ||
| $record | Yiisoft\ActiveRecord\ActiveRecordInterface | |
public function equals(ActiveRecordInterface $record): bool
{
if ($this->isNew() || $record->isNew()) {
return false;
}
return $this->tableName() === $record->tableName() && $this->primaryKeyValues() === $record->primaryKeyValues();
}
Defined in: Yiisoft\ActiveRecord\AbstractActiveRecord::get()
| public get( string $propertyName ): mixed | ||
| $propertyName | string | |
public function get(string $propertyName): mixed
{
return $this->propertyValuesInternal()[$propertyName] ?? null;
}
| protected hasDependentRelations( string $propertyName ): boolean | ||
| $propertyName | string | |
protected function hasDependentRelations(string $propertyName): bool
{
return isset($this->relationsDependencies[$propertyName]);
}
| public hasMany( Yiisoft\ActiveRecord\ActiveRecordInterface|string $modelClass, array $link ): Yiisoft\ActiveRecord\ActiveQueryInterface | ||
| $modelClass | Yiisoft\ActiveRecord\ActiveRecordInterface|string | |
| $link | array | |
public function hasMany(ActiveRecordInterface|string $modelClass, array $link): ActiveQueryInterface
{
return $this->createRelationQuery($modelClass, $link, true);
}
| public hasOne( Yiisoft\ActiveRecord\ActiveRecordInterface|string $modelClass, array $link ): Yiisoft\ActiveRecord\ActiveQueryInterface | ||
| $modelClass | Yiisoft\ActiveRecord\ActiveRecordInterface|string | |
| $link | array | |
public function hasOne(ActiveRecordInterface|string $modelClass, array $link): ActiveQueryInterface
{
return $this->createRelationQuery($modelClass, $link, false);
}
| public hasProperty( string $name ): boolean | ||
| $name | string | |
public function hasProperty(string $name): bool
{
return in_array($name, $this->propertyNames(), true);
}
| public insert( array|null $properties = null ): void | ||
| $properties | array|null | |
public function insert(?array $properties = null): void
{
$this->insertInternal($properties);
}
| protected insertInternal( array|null $properties = null ): void | ||
| $properties | array|null | |
protected function insertInternal(?array $properties = null): void
{
if (!$this->isNew()) {
throw new InvalidCallException('The record is not new and cannot be inserted.');
}
$values = $this->newPropertyValues($properties);
$primaryKeys = $this->db()->createCommand()->insertReturningPks($this->tableName(), $values);
$this->populateRawValues($primaryKeys, $values);
}
| public isChanged( ): boolean |
public function isChanged(): bool
{
return !empty($this->newValues());
}
| public isPrimaryKey( array $keys ): boolean | ||
| $keys | array | |
public function isPrimaryKey(array $keys): bool
{
$pks = $this->primaryKey();
return count($keys) === count($pks)
&& count(array_intersect($keys, $pks)) === count($pks);
}
| public isPropertyChanged( string $name ): boolean | ||
| $name | string | |
public function isPropertyChanged(string $name): bool
{
$values = $this->propertyValuesInternal();
if (empty($this->oldValues) || !array_key_exists($name, $this->oldValues)) {
return array_key_exists($name, $values);
}
return !array_key_exists($name, $values) || $values[$name] !== $this->oldValues[$name];
}
| public isPropertyChangedNonStrict( string $name ): boolean | ||
| $name | string | |
public function isPropertyChangedNonStrict(string $name): bool
{
$values = $this->propertyValuesInternal();
if (empty($this->oldValues) || !array_key_exists($name, $this->oldValues)) {
return array_key_exists($name, $values);
}
return !array_key_exists($name, $values) || $values[$name] != $this->oldValues[$name];
}
| public isRelationPopulated( string $name ): boolean | ||
| $name | string | |
public function isRelationPopulated(string $name): bool
{
return array_key_exists($name, $this->related);
}
| public link( string $relationName, Yiisoft\ActiveRecord\ActiveRecordInterface $linkModel, array $extraColumns = [] ): void | ||
| $relationName | string | |
| $linkModel | Yiisoft\ActiveRecord\ActiveRecordInterface | |
| $extraColumns | array | |
public function link(string $relationName, ActiveRecordInterface $linkModel, array $extraColumns = []): void
{
$viaModel = null;
$viaTable = null;
$relation = $this->relationQuery($relationName);
$via = $relation->getVia();
if ($via !== null) {
if ($this->isNew() || $linkModel->isNew()) {
throw new InvalidCallException(
'Unable to link models: the models being linked cannot be newly created.',
);
}
if (is_array($via)) {
[$viaName, $viaRelation] = $via;
$viaModel = $viaRelation->getModel();
// unset $viaName so that it can be reloaded to reflect the change.
unset($this->related[$viaName]);
} else {
$viaRelation = $via;
$from = $via->getFrom();
$viaTable = reset($from);
}
$columns = [];
$viaLink = $viaRelation->getLink();
foreach ($viaLink as $a => $b) {
$columns[$a] = $this->get($b);
}
$link = $relation->getLink();
foreach ($link as $a => $b) {
$columns[$b] = $linkModel->get($a);
}
foreach ($extraColumns as $k => $v) {
$columns[$k] = $v;
}
if ($viaModel !== null) {
foreach ($columns as $column => $value) {
$viaModel->set($column, $value);
}
$viaModel->insert();
} elseif (is_string($viaTable)) {
$this->db()->createCommand()->insert($viaTable, $columns)->execute();
}
} else {
$link = $relation->getLink();
$p1 = $linkModel->isPrimaryKey(array_keys($link));
$p2 = $this->isPrimaryKey(array_values($link));
if ($p1 && $p2) {
if ($this->isNew() && $linkModel->isNew()) {
throw new InvalidCallException('Unable to link models: at most one model can be newly created.');
}
if ($this->isNew()) {
$this->bindModels(array_flip($link), $this, $linkModel);
} else {
$this->bindModels($link, $linkModel, $this);
}
} elseif ($p1) {
$this->bindModels(array_flip($link), $this, $linkModel);
} elseif ($p2) {
$this->bindModels($link, $linkModel, $this);
} else {
throw new InvalidCallException(
'Unable to link models: the link defining the relation does not involve any primary key.',
);
}
}
// Update lazily loaded related objects.
if (!$relation->isMultiple()) {
$this->related[$relationName] = $linkModel;
} elseif (isset($this->related[$relationName])) {
/**
* Related records are already an array.
* @psalm-var array<string, ActiveRecordInterface[]|array[]> $this->related[$relationName]
*/
$indexBy = $relation->getIndexBy();
if ($indexBy !== null) {
/**
* We assume that the index is always string, int or null.
* @var int|string|null $index
*/
$index = $indexBy instanceof Closure
? $indexBy($linkModel)
: $linkModel->get($indexBy);
if ($index !== null) {
$this->related[$relationName][$index] = $linkModel;
}
} else {
$this->related[$relationName][] = $linkModel;
}
}
}
| public loadDefaultValues( boolean $skipIfSet = true ): Yiisoft\ActiveRecord\ActiveRecord | ||
| $skipIfSet | boolean | |
public function loadDefaultValues(bool $skipIfSet = true): static
{
foreach ($this->tableSchema()->getColumns() as $name => $column) {
if ($column->getDefaultValue() !== null && (!$skipIfSet || $this->get($name) === null)) {
$this->set($name, $column->getDefaultValue());
}
}
return $this;
}
| public markAsExisting( ): void |
public function markAsExisting(): void
{
$this->oldValues = $this->propertyValuesInternal();
}
| public markPropertyChanged( string $name ): void | ||
| $name | string | |
public function markPropertyChanged(string $name): void
{
if ($this->oldValues !== null && $name !== '') {
unset($this->oldValues[$name]);
}
}
Defined in: Yiisoft\ActiveRecord\AbstractActiveRecord::newPropertyValues()
Returns the property values that have been modified.
You may specify the properties to be returned as list of name or name-value pairs. If name-value pair specified, the corresponding property values will be modified.
Only the \Yiisoft\ActiveRecord\AbstractActiveRecord::newValues() changed property values will be returned.
| protected newPropertyValues( array|null $properties = null ): array | ||
| $properties | array|null |
List of property names or name-values pairs that need to be returned.
Defaults to |
| return | array |
The changed property values (name-value pairs). |
|---|---|---|
protected function newPropertyValues(?array $properties = null): array
{
if (empty($properties) || array_is_list($properties)) {
return $this->newValues($properties);
}
$names = [];
foreach ($properties as $name => $value) {
if (is_int($name)) {
$names[] = $value;
} else {
$this->set($name, $value);
$names[] = $name;
}
}
return $this->newValues($names);
}
| public newValues( array|null $propertyNames = null ): array | ||
| $propertyNames | array|null | |
public function newValues(?array $propertyNames = null): array
{
$values = $this->propertyValues($propertyNames);
if ($this->oldValues === null) {
return $values;
}
$result = array_diff_key($values, $this->oldValues);
foreach (array_diff_key($values, $result) as $name => $value) {
if ($value !== $this->oldValues[$name]) {
$result[$name] = $value;
}
}
return $result;
}
| public oldValue( string $propertyName ): mixed | ||
| $propertyName | string | |
public function oldValue(string $propertyName): mixed
{
return $this->oldValues[$propertyName] ?? null;
}
| public populateProperties( array $values ): void | ||
| $values | array | |
public function populateProperties(array $values): void
{
$values = array_intersect_key($values, array_flip($this->propertyNames()));
foreach ($values as $name => $value) {
$this->populateProperty($name, $value);
}
}
| protected populateProperty( string $name, mixed $value ): void | ||
| $name | string | |
| $value | mixed | |
protected function populateProperty(string $name, mixed $value): void
{
$this->$name = $value;
}
| public populateRecord( array|object $row ): Yiisoft\ActiveRecord\ActiveRecord | ||
| $row | array|object | |
public function populateRecord(array|object $row): static
{
$row = ArArrayHelper::toArray($row);
$row = Typecaster::cast($row, $this);
/** @var $this */
return parent::populateRecord($row);
}
| public populateRelation( string $name, array|Yiisoft\ActiveRecord\ActiveRecordInterface|null $records ): void | ||
| $name | string | |
| $records | array|Yiisoft\ActiveRecord\ActiveRecordInterface|null | |
public function populateRelation(string $name, array|ActiveRecordInterface|null $records): void
{
foreach ($this->relationsDependencies as &$relationNames) {
unset($relationNames[$name]);
}
$this->related[$name] = $records;
}
| public primaryKey( ): array |
public function primaryKey(): array
{
return $this->tableSchema()->getPrimaryKey();
}
| public primaryKeyOldValue( ): float|integer|string|null |
public function primaryKeyOldValue(): float|int|string|null
{
$keys = $this->primaryKey();
/**
* @var float|int|string|null We assume primary key old value always is float, int, string or null.
*/
return match (count($keys)) {
1 => $this->oldValues[$keys[0]] ?? null,
0 => throw new LogicException(
static::class . ' does not have a primary key. You should either define a primary key for '
. $this->tableName() . ' table or override the primaryKey() method.',
),
default => throw new LogicException(
static::class . ' has multiple primary keys. Use primaryKeyOldValues() method instead.',
),
};
}
| public primaryKeyOldValues( ): array |
public function primaryKeyOldValues(): array
{
$keys = $this->primaryKey();
if (empty($keys)) {
throw new LogicException(
static::class . ' does not have a primary key. You should either define a primary key for '
. $this->tableName() . ' table or override the primaryKey() method.',
);
}
$values = [];
foreach ($keys as $name) {
/**
* @var bool|float|int|string|null We assume primary key old values always are scalar or null.
*/
$values[$name] = $this->oldValues[$name] ?? null;
}
return $values;
}
| public primaryKeyValue( ): float|integer|string|null |
public function primaryKeyValue(): float|int|string|null
{
$keys = $this->primaryKey();
/**
* @var float|int|string|null We assume primary key value always is float, int, string or null.
*/
return match (count($keys)) {
1 => $this->get($keys[0]),
0 => throw new LogicException(
static::class . ' does not have a primary key. You should either define a primary key for '
. $this->tableName() . ' table or override the primaryKey() method.',
),
default => throw new LogicException(
static::class . ' has multiple primary keys. Use primaryKeyValues() method instead.',
),
};
}
| public primaryKeyValues( ): array |
public function primaryKeyValues(): array
{
$keys = $this->primaryKey();
if (empty($keys)) {
throw new LogicException(
static::class . ' does not have a primary key. You should either define a primary key for '
. $this->tableName() . ' table or override the primaryKey() method.',
);
}
$values = [];
foreach ($keys as $name) {
/**
* @var bool|float|int|string|null We assume primary key old values always are scalar or null.
*/
$values[$name] = $this->get($name);
}
return $values;
}
| public propertyNames( ): array |
public function propertyNames(): array
{
return $this->tableSchema()->getColumnNames();
}
| public propertyValues( array|null $names = null, array $except = [] ): array | ||
| $names | array|null | |
| $except | array | |
public function propertyValues(?array $names = null, array $except = []): array
{
$names ??= $this->propertyNames();
if (!empty($except)) {
$names = array_diff($names, $except);
}
return array_intersect_key($this->propertyValuesInternal(), array_flip($names));
}
| protected propertyValuesInternal( ): array |
protected function propertyValuesInternal(): array
{
return get_object_vars($this);
}
| public static query( Yiisoft\ActiveRecord\ActiveRecordInterface|string|null $modelClass = null ): Yiisoft\ActiveRecord\ActiveQueryInterface | ||
| $modelClass | Yiisoft\ActiveRecord\ActiveRecordInterface|string|null | |
public static function query(ActiveRecordInterface|string|null $modelClass = null): ActiveQueryInterface
{
return new ActiveQuery($modelClass ?? static::class);
}
Defined in: Yiisoft\ActiveRecord\AbstractActiveRecord::refresh()
Repopulates this active record with the latest data.
| public refresh( ): boolean | ||
| return | boolean |
Whether the row still exists in the database. If |
|---|---|---|
public function refresh(): bool
{
$record = $this->createQuery()->findByPk($this->primaryKeyOldValues());
return $this->refreshInternal($record);
}
Defined in: Yiisoft\ActiveRecord\AbstractActiveRecord::refreshInternal()
Repopulates this active record with the latest data from a newly fetched instance.
See also Yiisoft\ActiveRecord\AbstractActiveRecord::refresh().
| protected refreshInternal( Yiisoft\ActiveRecord\ActiveRecordInterface|array|null $record = null ): boolean | ||
| $record | Yiisoft\ActiveRecord\ActiveRecordInterface|array|null |
The record to take property values from. |
| return | boolean |
Whether refresh was successful. |
|---|---|---|
protected function refreshInternal(array|ActiveRecordInterface|null $record = null): bool
{
if ($record === null || is_array($record)) {
return false;
}
foreach ($this->propertyNames() as $name) {
$this->populateProperty($name, $record->get($name));
}
$this->oldValues = $record->oldValues();
$this->related = [];
$this->relationsDependencies = [];
return true;
}
| public relation( string $name ): Yiisoft\ActiveRecord\ActiveRecordInterface|array|null | ||
| $name | string | |
public function relation(string $name): ActiveRecordInterface|array|null
{
if (array_key_exists($name, $this->related)) {
return $this->related[$name];
}
return $this->retrieveRelation($name);
}
| public relationQuery( string $name ): Yiisoft\ActiveRecord\ActiveQueryInterface | ||
| $name | string | |
public function relationQuery(string $name): ActiveQueryInterface
{
throw new InvalidArgumentException(static::class . ' has no relation named "' . $name . '".');
}
Defined in: Yiisoft\ActiveRecord\AbstractActiveRecord::resetDependentRelations()
Resets dependent related models checking if their links contain specific property.
| protected resetDependentRelations( string $propertyName ): void | ||
| $propertyName | string |
The changed property name. |
protected function resetDependentRelations(string $propertyName): void
{
foreach ($this->relationsDependencies[$propertyName] as $relation) {
unset($this->related[$relation]);
}
unset($this->relationsDependencies[$propertyName]);
}
| public resetRelation( string $name ): void | ||
| $name | string | |
public function resetRelation(string $name): void
{
foreach ($this->relationsDependencies as &$relationNames) {
unset($relationNames[$name]);
}
unset($this->related[$name]);
}
| protected retrieveRelation( string $name ): Yiisoft\ActiveRecord\ActiveRecordInterface|array|null | ||
| $name | string | |
protected function retrieveRelation(string $name): ActiveRecordInterface|array|null
{
/** @var ActiveQueryInterface $query */
$query = $this->relationQuery($name);
$this->setRelationDependencies($name, $query);
return $this->related[$name] = $query->relatedRecords();
}
| public save( array|null $properties = null ): void | ||
| $properties | array|null | |
public function save(?array $properties = null): void
{
if ($this->isNew()) {
$this->insert($properties);
return;
}
$this->update($properties);
}
Defined in: Yiisoft\ActiveRecord\AbstractActiveRecord::set()
| public set( string $propertyName, mixed $value ): void | ||
| $propertyName | string | |
| $value | mixed | |
public function set(string $propertyName, mixed $value): void
{
if (
isset($this->relationsDependencies[$propertyName])
&& ($value === null || $this->get($propertyName) !== $value)
) {
$this->resetDependentRelations($propertyName);
}
$this->populateProperty($propertyName, $value);
}
| public tableName( ): string |
public function tableName(): string
{
$name = (new ReflectionClass($this))->getShortName();
/** @var string $name */
$name = preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $name);
$name = strtolower(ltrim($name, '_'));
return '{{%' . $name . '}}';
}
| public tableSchema( ): \Yiisoft\Db\Schema\TableSchemaInterface |
public function tableSchema(): TableSchemaInterface
{
$tableSchema = $this->db()->getSchema()->getTableSchema($this->tableName());
if ($tableSchema === null) {
throw new InvalidConfigException('The table does not exist: ' . $this->tableName());
}
return $tableSchema;
}
| public unlink( string $relationName, Yiisoft\ActiveRecord\ActiveRecordInterface $linkedModel, boolean $delete = false ): void | ||
| $relationName | string | |
| $linkedModel | Yiisoft\ActiveRecord\ActiveRecordInterface | |
| $delete | boolean | |
public function unlink(string $relationName, ActiveRecordInterface $linkedModel, bool $delete = false): void
{
$viaModel = null;
$viaTable = null;
$relation = $this->relationQuery($relationName);
$viaRelation = $relation->getVia();
if ($viaRelation !== null) {
if (is_array($viaRelation)) {
[$viaName, $viaRelation] = $viaRelation;
$viaModel = $viaRelation->getModel();
unset($this->related[$viaName]);
}
$columns = [];
$nulls = [];
if ($viaRelation instanceof ActiveQueryInterface) {
$from = $viaRelation->getFrom();
$viaTable = reset($from);
foreach ($viaRelation->getLink() as $a => $b) {
$columns[$a] = $this->get($b);
}
$link = $relation->getLink();
foreach ($link as $a => $b) {
$columns[$b] = $linkedModel->get($a);
}
$nulls = array_fill_keys(array_keys($columns), null);
if ($viaRelation->getOn() !== null) {
$columns = ['and', $columns, $viaRelation->getOn()];
}
}
if ($viaModel !== null) {
if ($delete) {
$viaModel->deleteAll($columns);
} else {
$viaModel->updateAll($nulls, $columns);
}
} elseif (is_string($viaTable)) {
$command = $this->db()->createCommand();
if ($delete) {
$command->delete($viaTable, $columns)->execute();
} else {
$command->update($viaTable, $nulls, $columns)->execute();
}
}
} else {
if ($this->isPrimaryKey($relation->getLink())) {
if ($delete) {
$linkedModel->delete();
} else {
foreach ($relation->getLink() as $a => $b) {
$linkedModel->set($a, null);
}
$linkedModel->save();
}
} elseif ($linkedModel->isPrimaryKey(array_keys($relation->getLink()))) {
foreach ($relation->getLink() as $a => $b) {
$values = $this->get($b);
// relation via array valued property
if (is_array($values)) {
if (($key = array_search($linkedModel->get($a), $values)) !== false) {
unset($values[$key]);
$this->set($b, array_values($values));
}
} else {
$this->set($b, null);
}
}
$delete ? $this->delete() : $this->save();
} else {
throw new InvalidCallException('Unable to unlink models: the link does not involve any primary key.');
}
}
if (!$relation->isMultiple()) {
unset($this->related[$relationName]);
} elseif (isset($this->related[$relationName]) && is_array($this->related[$relationName])) {
/** @psalm-var array<array-key, ActiveRecordInterface> $related */
$related = $this->related[$relationName];
foreach ($related as $a => $b) {
if ($linkedModel->primaryKeyValues() === $b->primaryKeyValues()) {
unset($this->related[$relationName][$a]);
}
}
}
}
| public unlinkAll( string $relationName, boolean $delete = false ): void | ||
| $relationName | string | |
| $delete | boolean | |
public function unlinkAll(string $relationName, bool $delete = false): void
{
$viaModel = null;
$viaTable = null;
$relation = $this->relationQuery($relationName);
$viaRelation = $relation->getVia();
if ($viaRelation !== null) {
if (is_array($viaRelation)) {
[$viaName, $viaRelation] = $viaRelation;
$viaModel = $viaRelation->getModel();
unset($this->related[$viaName]);
} else {
$from = $viaRelation->getFrom();
$viaTable = reset($from);
}
$condition = [];
$nulls = [];
if ($viaRelation instanceof ActiveQueryInterface) {
foreach ($viaRelation->getLink() as $a => $b) {
$nulls[$a] = null;
$condition[$a] = $this->get($b);
}
if (!empty($viaRelation->getWhere())) {
$condition = ['and', $condition, $viaRelation->getWhere()];
}
if (!empty($viaRelation->getOn())) {
$condition = ['and', $condition, $viaRelation->getOn()];
}
}
if ($viaModel !== null) {
if ($delete) {
$viaModel->deleteAll($condition);
} else {
$viaModel->updateAll($nulls, $condition);
}
} elseif (is_string($viaTable)) {
$command = $this->db()->createCommand();
if ($delete) {
$command->delete($viaTable, $condition)->execute();
} else {
$command->update($viaTable, $nulls, $condition)->execute();
}
}
} else {
$relatedModel = $relation->getModel();
$link = $relation->getLink();
if (!$delete && count($link) === 1 && is_array($this->get($b = reset($link)))) {
/** relation via array valued property */
$this->set($b, []);
$this->save();
} else {
$nulls = [];
$condition = [];
foreach ($relation->getLink() as $a => $b) {
$nulls[$a] = null;
$condition[$a] = $this->get($b);
}
if (!empty($relation->getWhere())) {
$condition = ['and', $condition, $relation->getWhere()];
}
if (!empty($relation->getOn())) {
$condition = ['and', $condition, $relation->getOn()];
}
if ($delete) {
$relatedModel->deleteAll($condition);
} else {
$relatedModel->updateAll($nulls, $condition);
}
}
}
unset($this->related[$relationName]);
}
| public update( array|null $properties = null ): integer | ||
| $properties | array|null | |
public function update(?array $properties = null): int
{
return $this->updateInternal($properties);
}
| public updateAll( array $propertyValues, array|string $condition = [], array|\Yiisoft\Db\Expression\ExpressionInterface|string|null $from = null, array $params = [] ): integer | ||
| $propertyValues | array | |
| $condition | array|string | |
| $from | array|\Yiisoft\Db\Expression\ExpressionInterface|string|null | |
| $params | array | |
public function updateAll(array $propertyValues, array|string $condition = [], array|ExpressionInterface|string|null $from = null, array $params = []): int
{
$command = $this->db()->createCommand();
$command->update($this->tableName(), $propertyValues, $condition, $from, $params);
return $command->execute();
}
| public updateAllCounters( array $counters, array|string $condition = '', array|\Yiisoft\Db\Expression\ExpressionInterface|string|null $from = null, array $params = [] ): integer | ||
| $counters | array | |
| $condition | array|string | |
| $from | array|\Yiisoft\Db\Expression\ExpressionInterface|string|null | |
| $params | array | |
public function updateAllCounters(
array $counters,
array|string $condition = '',
array|ExpressionInterface|string|null $from = null,
array $params = [],
): int {
$n = 0;
foreach ($counters as $name => $value) {
$counters[$name] = new Expression("[[$name]]+:bp$n", [":bp$n" => $value]);
$n++;
}
return $this->db()
->createCommand()
->update($this->tableName(), $counters, $condition, $from, $params)
->execute();
}
| public updateCounters( array $counters ): void | ||
| $counters | array | |
public function updateCounters(array $counters): void
{
if ($this->isNew()) {
throw new LogicException('Updating counters is not possible for new records.');
}
$this->updateAllCounters($counters, $this->primaryKeyOldValues());
foreach ($counters as $name => $value) {
/**
* @psalm-suppress MixedOperand We assume that the counter value is always an integer.
*/
$value += $this->get($name) ?? 0;
$this->populateProperty($name, $value);
$this->oldValues[$name] = $value;
}
}
Defined in: Yiisoft\ActiveRecord\AbstractActiveRecord::updateInternal()
See also Yiisoft\ActiveRecord\AbstractActiveRecord::update().
| protected updateInternal( array|null $properties = null ): integer | ||
| $properties | array|null |
Property names or name-values pairs to update, |
| return | integer |
The number of rows affected. |
|---|---|---|
| throws | \Yiisoft\Db\Exception\Exception | |
| throws | \Yiisoft\Db\Exception\NotSupportedException | |
protected function updateInternal(?array $properties = null): int
{
if ($this->isNew()) {
throw new InvalidCallException('The record is new and cannot be updated.');
}
$values = $this->newPropertyValues($properties);
if (empty($values)) {
return 0;
}
$condition = $this->primaryKeyOldValues();
if ($this instanceof OptimisticLockInterface) {
$lock = $this->optimisticLockPropertyName();
/**
* @var int $lockValue We assume that optimistic lock property value is always an integer.
*/
$lockValue = $this->get($lock);
$condition[$lock] = $lockValue;
$values[$lock] = ++$lockValue;
$rows = $this->updateAll($values, $condition);
if ($rows === 0) {
throw new OptimisticLockException(
'The object being updated is outdated.',
);
}
$this->populateProperty($lock, $lockValue);
} else {
$rows = $this->updateAll($values, $condition);
}
$this->oldValues = array_merge($this->oldValues ?? [], $values);
return $rows;
}
| public upsert( array|null $insertProperties = null, array|boolean $updateProperties = true ): void | ||
| $insertProperties | array|null | |
| $updateProperties | array|boolean | |
public function upsert(?array $insertProperties = null, array|bool $updateProperties = true): void
{
$this->upsertInternal($insertProperties, $updateProperties);
}
| protected upsertInternal( array|null $insertProperties = null, array|boolean $updateProperties = true ): void | ||
| $insertProperties | array|null | |
| $updateProperties | array|boolean | |
protected function upsertInternal(?array $insertProperties = null, array|bool $updateProperties = true): void
{
if (!$this->isNew()) {
throw new InvalidCallException('The record is not new and cannot be inserted.');
}
$insertValues = $this->newPropertyValues($insertProperties);
$returnProperties = $insertProperties !== null
? array_merge($this->primaryKey(), array_keys($insertValues))
: null;
if (is_array($updateProperties)) {
/**
* @var string[] $updateNames Values of `$updateProperties` parameter which are integer keys
* represent property names
*/
$updateNames = array_filter($updateProperties, is_int(...), ARRAY_FILTER_USE_KEY);
if (!empty($updateNames)) {
$updateProperties = array_merge(
array_diff_key($updateProperties, $updateNames),
$this->newPropertyValues($updateNames),
);
}
/** @psalm-var array<string, mixed> $updateProperties */
if ($returnProperties !== null) {
$returnProperties = array_merge($returnProperties, array_keys($updateProperties));
}
}
$returnedValues = $this->db()->createCommand()
->upsertReturning($this->tableName(), $insertValues, $updateProperties, $returnProperties);
$this->populateRawValues($returnedValues);
}
Signup or Login in order to comment.