0 follower

Class Yiisoft\ActiveRecord\ActiveRecord

InheritanceYiisoft\ActiveRecord\ActiveRecord » Yiisoft\ActiveRecord\AbstractActiveRecord
ImplementsYiisoft\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 Methods

Hide inherited methods

Method Description Defined By
assignOldValue() Yiisoft\ActiveRecord\AbstractActiveRecord
assignOldValues() Yiisoft\ActiveRecord\AbstractActiveRecord
column() Yiisoft\ActiveRecord\ActiveRecord
createQuery() Yiisoft\ActiveRecord\AbstractActiveRecord
db() Yiisoft\ActiveRecord\AbstractActiveRecord
delete() Yiisoft\ActiveRecord\AbstractActiveRecord
deleteAll() Yiisoft\ActiveRecord\AbstractActiveRecord
equals() Yiisoft\ActiveRecord\AbstractActiveRecord
get() Yiisoft\ActiveRecord\AbstractActiveRecord
hasMany() Yiisoft\ActiveRecord\AbstractActiveRecord
hasOne() Yiisoft\ActiveRecord\AbstractActiveRecord
hasProperty() Yiisoft\ActiveRecord\AbstractActiveRecord
insert() Yiisoft\ActiveRecord\AbstractActiveRecord
isChanged() Yiisoft\ActiveRecord\AbstractActiveRecord
isNew() Yiisoft\ActiveRecord\AbstractActiveRecord
isPrimaryKey() Yiisoft\ActiveRecord\AbstractActiveRecord
isPropertyChanged() Yiisoft\ActiveRecord\AbstractActiveRecord
isPropertyChangedNonStrict() Yiisoft\ActiveRecord\AbstractActiveRecord
isRelationPopulated() Yiisoft\ActiveRecord\AbstractActiveRecord
link() Yiisoft\ActiveRecord\AbstractActiveRecord
loadDefaultValues() Yiisoft\ActiveRecord\ActiveRecord
markAsExisting() Yiisoft\ActiveRecord\AbstractActiveRecord
markAsNew() Yiisoft\ActiveRecord\AbstractActiveRecord
markPropertyChanged() Yiisoft\ActiveRecord\AbstractActiveRecord
newValues() Yiisoft\ActiveRecord\AbstractActiveRecord
oldValue() Yiisoft\ActiveRecord\AbstractActiveRecord
oldValues() Yiisoft\ActiveRecord\AbstractActiveRecord
populateProperties() Yiisoft\ActiveRecord\AbstractActiveRecord
populateRecord() Yiisoft\ActiveRecord\ActiveRecord
populateRelation() Yiisoft\ActiveRecord\AbstractActiveRecord
primaryKey() Yiisoft\ActiveRecord\ActiveRecord
primaryKeyOldValue() Yiisoft\ActiveRecord\AbstractActiveRecord
primaryKeyOldValues() Yiisoft\ActiveRecord\AbstractActiveRecord
primaryKeyValue() Yiisoft\ActiveRecord\AbstractActiveRecord
primaryKeyValues() Yiisoft\ActiveRecord\AbstractActiveRecord
propertyNames() Yiisoft\ActiveRecord\ActiveRecord
propertyValues() Yiisoft\ActiveRecord\AbstractActiveRecord
query() Yiisoft\ActiveRecord\AbstractActiveRecord
refresh() Repopulates this active record with the latest data. Yiisoft\ActiveRecord\AbstractActiveRecord
relatedRecords() Yiisoft\ActiveRecord\AbstractActiveRecord
relation() Yiisoft\ActiveRecord\AbstractActiveRecord
relationQuery() Yiisoft\ActiveRecord\AbstractActiveRecord
resetRelation() Yiisoft\ActiveRecord\AbstractActiveRecord
save() Yiisoft\ActiveRecord\AbstractActiveRecord
set() Yiisoft\ActiveRecord\AbstractActiveRecord
tableName() Yiisoft\ActiveRecord\AbstractActiveRecord
tableSchema() Yiisoft\ActiveRecord\ActiveRecord
unlink() Yiisoft\ActiveRecord\AbstractActiveRecord
unlinkAll() Yiisoft\ActiveRecord\AbstractActiveRecord
update() Yiisoft\ActiveRecord\AbstractActiveRecord
updateAll() Yiisoft\ActiveRecord\AbstractActiveRecord
updateAllCounters() Yiisoft\ActiveRecord\AbstractActiveRecord
updateCounters() Yiisoft\ActiveRecord\AbstractActiveRecord
upsert() Yiisoft\ActiveRecord\AbstractActiveRecord

Method Details

Hide inherited methods

assignOldValue() public method
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 . '".');
    }
}

            
assignOldValues() public method
public assignOldValues( array|null $propertyValues null ): void
$propertyValues array|null

                public function assignOldValues(?array $propertyValues = null): void
{
    $this->oldValues = $propertyValues;
}

            
column() public method

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]);
}

            
createQuery() public method
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);
}

            
createRelationQuery() protected method
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);
}

            
db() public method
public db( ): \Yiisoft\Db\Connection\ConnectionInterface

                public function db(): ConnectionInterface
{
    return ConnectionProvider::get();
}

            
delete() public method
public delete( ): integer

                public function delete(): int
{
    return $this->deleteInternal();
}

            
deleteAll() public method
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();
}

            
deleteInternal() protected method
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;
}

            
equals() public method
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();
}

            
get() public method
public get( string $propertyName ): mixed
$propertyName string

                public function get(string $propertyName): mixed
{
    return $this->propertyValuesInternal()[$propertyName] ?? null;
}

            
hasDependentRelations() protected method
protected hasDependentRelations( string $propertyName ): boolean
$propertyName string

                protected function hasDependentRelations(string $propertyName): bool
{
    return isset($this->relationsDependencies[$propertyName]);
}

            
hasMany() public method
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);
}

            
hasOne() public method
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);
}

            
hasProperty() public method
public hasProperty( string $name ): boolean
$name string

                public function hasProperty(string $name): bool
{
    return in_array($name, $this->propertyNames(), true);
}

            
insert() public method
public insert( array|null $properties null ): void
$properties array|null

                public function insert(?array $properties = null): void
{
    $this->insertInternal($properties);
}

            
insertInternal() protected method

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);
}

            
isChanged() public method
public isChanged( ): boolean

                public function isChanged(): bool
{
    return !empty($this->newValues());
}

            
isNew() public method
public isNew( ): boolean

                public function isNew(): bool
{
    return $this->oldValues === null;
}

            
isPrimaryKey() public method
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);
}

            
isPropertyChanged() public method
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];
}

            
isPropertyChangedNonStrict() public method
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];
}

            
isRelationPopulated() public method
public isRelationPopulated( string $name ): boolean
$name string

                public function isRelationPopulated(string $name): bool
{
    return array_key_exists($name, $this->related);
}

            
link() public method
public link( string $relationName, Yiisoft\ActiveRecord\ActiveRecordInterface $linkModel, array $extraColumns = [] ): void
$relationName string
$linkModel Yiisoft\ActiveRecord\ActiveRecordInterface
$extraColumns array

loadDefaultValues() public method

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;
}

            
markAsExisting() public method
public markAsExisting( ): void

                public function markAsExisting(): void
{
    $this->oldValues = $this->propertyValuesInternal();
}

            
markAsNew() public method
public markAsNew( ): void

                public function markAsNew(): void
{
    $this->oldValues = null;
}

            
markPropertyChanged() public method
public markPropertyChanged( string $name ): void
$name string

                public function markPropertyChanged(string $name): void
{
    if ($this->oldValues !== null && $name !== '') {
        unset($this->oldValues[$name]);
    }
}

            
newPropertyValues() protected method

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 null, meaning all changed property values will be returned.

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);
}

            
newValues() public method
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;
}

            
oldValue() public method
public oldValue( string $propertyName ): mixed
$propertyName string

                public function oldValue(string $propertyName): mixed
{
    return $this->oldValues[$propertyName] ?? null;
}

            
oldValues() public method
public oldValues( ): array

                public function oldValues(): array
{
    return $this->oldValues ?? [];
}

            
populateProperties() public method
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);
    }
}

            
populateProperty() protected method

protected populateProperty( string $name, mixed $value ): void
$name string
$value mixed

                protected function populateProperty(string $name, mixed $value): void
{
    $this->$name = $value;
}

            
populateRecord() public method

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);
}

            
populateRelation() public method
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;
}

            
primaryKey() public method

public primaryKey( ): array

                public function primaryKey(): array
{
    return $this->tableSchema()->getPrimaryKey();
}

            
primaryKeyOldValue() public method
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.',
        ),
    };
}

            
primaryKeyOldValues() public method
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;
}

            
primaryKeyValue() public method
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.',
        ),
    };
}

            
primaryKeyValues() public method
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;
}

            
propertyNames() public method

public propertyNames( ): array

                public function propertyNames(): array
{
    return $this->tableSchema()->getColumnNames();
}

            
propertyValues() public method
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));
}

            
propertyValuesInternal() protected method

protected propertyValuesInternal( ): array

                protected function propertyValuesInternal(): array
{
    return get_object_vars($this);
}

            
query() public static method
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);
}

            
refresh() public method

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 true, the latest data will be populated to this active record. Otherwise, this record will remain unchanged.

                public function refresh(): bool
{
    $record = $this->createQuery()->findByPk($this->primaryKeyOldValues());
    return $this->refreshInternal($record);
}

            
refreshInternal() protected method

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;
}

            
relatedRecords() public method
public relatedRecords( ): array

                public function relatedRecords(): array
{
    return $this->related;
}

            
relation() public method
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);
}

            
relationQuery() public method
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 . '".');
}

            
resetDependentRelations() protected method

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]);
}

            
resetRelation() public method
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]);
}

            
retrieveRelation() protected method
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();
}

            
save() public method
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);
}

            
set() public method
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);
}

            
tableName() public method
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 . '}}';
}

            
tableSchema() public method

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;
}

            
unlink() public method
public unlink( string $relationName, Yiisoft\ActiveRecord\ActiveRecordInterface $linkedModel, boolean $delete false ): void
$relationName string
$linkedModel Yiisoft\ActiveRecord\ActiveRecordInterface
$delete boolean

unlinkAll() public method
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]);
}

            
update() public method
public update( array|null $properties null ): integer
$properties array|null

                public function update(?array $properties = null): int
{
    return $this->updateInternal($properties);
}

            
updateAll() public method
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();
}

            
updateAllCounters() public method
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();
}

            
updateCounters() public method
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;
    }
}

            
updateInternal() protected method
protected updateInternal( array|null $properties null ): integer
$properties array|null

Property names or name-values pairs to update, null means all properties.

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;
}

            
upsert() public method
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);
}

            
upsertInternal() protected method

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);
}