| public array primaryKey ( ) |
public function primaryKey(): array
{
return $this->tableSchema()->getPrimaryKey();
}
| Inheritance | Yiisoft\ActiveRecord\ActiveRecord » Yiisoft\ActiveRecord\AbstractActiveRecord |
|---|---|
| Implements | Yiisoft\ActiveRecord\ActiveRecordInterface |
Active Record class which implements {@see 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 {@see \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 {@see \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, {@see \Yiisoft\ActiveRecord\the guide article on ActiveRecord}
| public void assignOldValue ( string $propertyName, mixed $value ) | ||
| $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 void assignOldValues ( array|null $propertyValues = null ) | ||
| $propertyValues | array|null | |
public function assignOldValues(?array $propertyValues = null): void
{
$this->oldValues = $propertyValues;
}
| public \Yiisoft\Db\Schema\Column\ColumnInterface column ( string $propertyName ) | ||
| $propertyName | string | |
public function column(string $propertyName): ColumnInterface
{
return $this->tableSchema()->getColumn($propertyName)
?? $this->db()->getColumnFactory()->fromType(ColumnType::STRING, ['name' => $propertyName]);
}
| public Yiisoft\ActiveRecord\ActiveQueryInterface createQuery ( Yiisoft\ActiveRecord\ActiveRecordInterface|string|null $modelClass = null ) | ||
| $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.
| protected Yiisoft\ActiveRecord\ActiveQueryInterface createRelationQuery ( Yiisoft\ActiveRecord\ActiveRecordInterface|string $modelClass, array $link, boolean $multiple ) | ||
| $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 \Yiisoft\Db\Connection\ConnectionInterface db ( ) |
public function db(): ConnectionInterface
{
return ConnectionProvider::get();
}
| public integer deleteAll ( array $condition = [], array $params = [] ) | ||
| $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 delete()}
| protected integer deleteInternal ( ) | ||
| 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 boolean equals ( Yiisoft\ActiveRecord\ActiveRecordInterface $record ) | ||
| $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 mixed get ( string $propertyName ) | ||
| $propertyName | string | |
public function get(string $propertyName): mixed
{
return $this->propertyValuesInternal()[$propertyName] ?? null;
}
| protected boolean hasDependentRelations ( string $propertyName ) | ||
| $propertyName | string | |
protected function hasDependentRelations(string $propertyName): bool
{
return isset($this->relationsDependencies[$propertyName]);
}
| public Yiisoft\ActiveRecord\ActiveQueryInterface hasMany ( Yiisoft\ActiveRecord\ActiveRecordInterface|string $modelClass, array $link ) | ||
| $modelClass | Yiisoft\ActiveRecord\ActiveRecordInterface|string | |
| $link | array | |
public function hasMany(ActiveRecordInterface|string $modelClass, array $link): ActiveQueryInterface
{
return $this->createRelationQuery($modelClass, $link, true);
}
| public Yiisoft\ActiveRecord\ActiveQueryInterface hasOne ( Yiisoft\ActiveRecord\ActiveRecordInterface|string $modelClass, array $link ) | ||
| $modelClass | Yiisoft\ActiveRecord\ActiveRecordInterface|string | |
| $link | array | |
public function hasOne(ActiveRecordInterface|string $modelClass, array $link): ActiveQueryInterface
{
return $this->createRelationQuery($modelClass, $link, false);
}
| public boolean hasProperty ( string $name ) | ||
| $name | string | |
public function hasProperty(string $name): bool
{
return in_array($name, $this->propertyNames(), true);
}
| public void insert ( array|null $properties = null ) | ||
| $properties | array|null | |
public function insert(?array $properties = null): void
{
$this->insertInternal($properties);
}
| protected void insertInternal ( array|null $properties = null ) | ||
| $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 boolean isChanged ( ) |
public function isChanged(): bool
{
return !empty($this->newValues());
}
| public boolean isPrimaryKey ( array $keys ) | ||
| $keys | array | |
public function isPrimaryKey(array $keys): bool
{
$pks = $this->primaryKey();
return count($keys) === count($pks)
&& count(array_intersect($keys, $pks)) === count($pks);
}
| public boolean isPropertyChanged ( string $name ) | ||
| $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 boolean isPropertyChangedNonStrict ( string $name ) | ||
| $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 boolean isRelationPopulated ( string $name ) | ||
| $name | string | |
public function isRelationPopulated(string $name): bool
{
return array_key_exists($name, $this->related);
}
| public void link ( string $relationName, Yiisoft\ActiveRecord\ActiveRecordInterface $linkModel, array $extraColumns = [] ) | ||
| $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 Yiisoft\ActiveRecord\ActiveRecord loadDefaultValues ( boolean $skipIfSet = true ) | ||
| $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 void markAsExisting ( ) |
public function markAsExisting(): void
{
$this->oldValues = $this->propertyValuesInternal();
}
| public void markPropertyChanged ( string $name ) | ||
| $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 {@see \Yiisoft\ActiveRecord\newValues() changed property values} will be returned.
| protected array newPropertyValues ( array|null $properties = null ) | ||
| $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 array newValues ( array|null $propertyNames = null ) | ||
| $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 mixed oldValue ( string $propertyName ) | ||
| $propertyName | string | |
public function oldValue(string $propertyName): mixed
{
return $this->oldValues[$propertyName] ?? null;
}
| public void populateProperties ( array $values ) | ||
| $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 void populateProperty ( string $name, mixed $value ) | ||
| $name | string | |
| $value | mixed | |
protected function populateProperty(string $name, mixed $value): void
{
$this->$name = $value;
}
| public Yiisoft\ActiveRecord\ActiveRecord populateRecord ( array|object $row ) | ||
| $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 void populateRelation ( string $name, array|Yiisoft\ActiveRecord\ActiveRecordInterface|null $records ) | ||
| $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 array primaryKey ( ) |
public function primaryKey(): array
{
return $this->tableSchema()->getPrimaryKey();
}
| public float|integer|string|null primaryKeyOldValue ( ) |
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 array primaryKeyOldValues ( ) |
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 float|integer|string|null primaryKeyValue ( ) |
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 array primaryKeyValues ( ) |
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 array propertyNames ( ) |
public function propertyNames(): array
{
return $this->tableSchema()->getColumnNames();
}
| public array propertyValues ( array|null $names = null, array $except = [] ) | ||
| $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 array propertyValuesInternal ( ) |
protected function propertyValuesInternal(): array
{
return get_object_vars($this);
}
| public static Yiisoft\ActiveRecord\ActiveQueryInterface query ( Yiisoft\ActiveRecord\ActiveRecordInterface|string|null $modelClass = null ) | ||
| $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 boolean refresh ( ) | ||
| 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.
| protected boolean refreshInternal ( Yiisoft\ActiveRecord\ActiveRecordInterface|array|null $record = null ) | ||
| $record | Yiisoft\ActiveRecord\ActiveRecordInterface|array|null |
The record to take property values from. |
| return | boolean |
Whether refresh was successful. {@see \Yiisoft\ActiveRecord\refresh()} |
|---|---|---|
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 Yiisoft\ActiveRecord\ActiveRecordInterface|array|null relation ( string $name ) | ||
| $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 Yiisoft\ActiveRecord\ActiveQueryInterface relationQuery ( string $name ) | ||
| $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 void resetDependentRelations ( string $propertyName ) | ||
| $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 void resetRelation ( string $name ) | ||
| $name | string | |
public function resetRelation(string $name): void
{
foreach ($this->relationsDependencies as &$relationNames) {
unset($relationNames[$name]);
}
unset($this->related[$name]);
}
| protected Yiisoft\ActiveRecord\ActiveRecordInterface|array|null retrieveRelation ( string $name ) | ||
| $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 void save ( array|null $properties = null ) | ||
| $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 void set ( string $propertyName, mixed $value ) | ||
| $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 string tableName ( ) |
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 \Yiisoft\Db\Schema\TableSchemaInterface tableSchema ( ) |
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 void unlink ( string $relationName, Yiisoft\ActiveRecord\ActiveRecordInterface $linkedModel, boolean $delete = false ) | ||
| $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 void unlinkAll ( string $relationName, boolean $delete = false ) | ||
| $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 integer update ( array|null $properties = null ) | ||
| $properties | array|null | |
public function update(?array $properties = null): int
{
return $this->updateInternal($properties);
}
| public integer updateAll ( array $propertyValues, array|string $condition = [], array|\Yiisoft\Db\Expression\ExpressionInterface|string|null $from = null, array $params = [] ) | ||
| $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 integer updateAllCounters ( array $counters, array|string $condition = '', array|\Yiisoft\Db\Expression\ExpressionInterface|string|null $from = null, array $params = [] ) | ||
| $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 void updateCounters ( array $counters ) | ||
| $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 update()}
| protected integer updateInternal ( array|null $properties = null ) | ||
| $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 void upsert ( array|null $insertProperties = null, array|boolean $updateProperties = true ) | ||
| $insertProperties | array|null | |
| $updateProperties | array|boolean | |
public function upsert(?array $insertProperties = null, array|bool $updateProperties = true): void
{
$this->upsertInternal($insertProperties, $updateProperties);
}
| protected void upsertInternal ( array|null $insertProperties = null, array|boolean $updateProperties = true ) | ||
| $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.