Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 42 additions & 24 deletions src/AbstractActiveRecord.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use function array_flip;
use function array_intersect;
use function array_intersect_key;
use function array_is_list;
use function array_key_exists;
use function array_keys;
use function array_merge;
Expand Down Expand Up @@ -67,8 +68,8 @@ abstract protected function propertyValuesInternal(): array;
/**
* Inserts Active Record values into DB without considering transaction.
*
* @param array|null $propertyNames List of property names that need to be saved. Defaults to `null`, meaning all
* changed property values will be saved. Only changed values will be saved.
* @param array|null $properties List of property names or name-values pairs that need to be saved.
* Defaults to `null`, meaning all changed property values will be saved.
*
* @throws Exception
* @throws InvalidArgumentException
Expand All @@ -77,7 +78,7 @@ abstract protected function propertyValuesInternal(): array;
*
* @return bool Whether the record inserted successfully.
*/
abstract protected function insertInternal(array|null $propertyNames = null): bool;
abstract protected function insertInternal(array|null $properties = null): bool;

/**
* Sets the value of the named property.
Expand Down Expand Up @@ -347,9 +348,9 @@ public function hasOne(string|ActiveRecordInterface|Closure $class, array $link)
return $this->createRelationQuery($class, $link, false);
}

public function insert(array|null $propertyNames = null): bool
public function insert(array|null $properties = null): bool
{
return $this->insertInternal($propertyNames);
return $this->insertInternal($properties);
}

/**
Expand Down Expand Up @@ -619,13 +620,13 @@ protected function retrieveRelation(string $name): ActiveRecordInterface|array|n
return $this->related[$name] = $query->relatedRecords();
}

public function save(array|null $propertyNames = null): bool
public function save(array|null $properties = null): bool
{
if ($this->isNewRecord()) {
return $this->insert($propertyNames);
return $this->insert($properties);
}

$this->update($propertyNames);
$this->update($properties);

return true;
}
Expand Down Expand Up @@ -1093,6 +1094,38 @@ protected function deleteInternal(): int
return $result;
}

/**
* 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 newValues() changed property values} will be returned.
*
* @param array|null $properties 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|null $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);
}

/**
* Repopulates this active record with the latest data from a newly fetched instance.
*
Expand Down Expand Up @@ -1136,22 +1169,7 @@ protected function updateInternal(array|null $properties = null): int
throw new InvalidCallException('The record is new and cannot be updated.');
}

if ($properties === null) {
$names = $this->propertyNames();
} else {
$names = [];

foreach ($properties as $name => $value) {
if (is_int($name)) {
$names[] = $value;
} else {
$this->set($name, $value);
$names[] = $name;
}
}
}

$values = $this->newValues($names);
$values = $this->newPropertyValues($properties);

if (empty($values)) {
return 0;
Expand Down
9 changes: 7 additions & 2 deletions src/ActiveRecord.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Yiisoft\Db\Constant\ColumnType;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidCallException;
use Yiisoft\Db\Exception\InvalidConfigException;
use Yiisoft\Db\Schema\TableSchemaInterface;

Expand Down Expand Up @@ -153,9 +154,13 @@ protected function propertyValuesInternal(): array
return get_object_vars($this);
}

protected function insertInternal(array|null $propertyNames = null): bool
protected function insertInternal(array|null $properties = null): bool
{
$values = $this->newValues($propertyNames);
if (!$this->isNewRecord()) {
throw new InvalidCallException('The record is not new and cannot be inserted.');
}

$values = $this->newPropertyValues($properties);
$primaryKeys = $this->db()->createCommand()->insertWithReturningPks($this->tableName(), $values);

if ($primaryKeys === false) {
Expand Down
44 changes: 32 additions & 12 deletions src/ActiveRecordInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Yiisoft\Db\Constant\ColumnType;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidArgumentException;
use Yiisoft\Db\Exception\InvalidCallException;
use Yiisoft\Db\Exception\InvalidConfigException;

interface ActiveRecordInterface
Expand Down Expand Up @@ -195,6 +196,8 @@ public function hasProperty(string $name): bool;

/**
* Inserts a row into the associated database table using the property values of this record.
* You may specify the properties to be inserted as list of name or name-value pairs.
* If name-value pair specified, the corresponding property values will be modified.
*
* Only the {@see newValues() changed property values} will be inserted into a database.
*
Expand All @@ -210,15 +213,22 @@ public function hasProperty(string $name): bool;
* $customer->insert();
* ```
*
* @param array|null $propertyNames List of property names that need to be saved. Defaults to `null`, meaning all
* changed property values will be saved.
* To insert a customer record with specific properties:
*
* ```php
* $customer->insert(['name' => $name, 'email' => $email]);
* ```
*
* @param array|null $properties List of property names or name-values pairs that need to be saved.
* Defaults to `null`, meaning all changed property values will be saved.
*
* @throws InvalidCallException If the record {@see isNewRecord() is not new}.
* @throws InvalidConfigException
* @throws Throwable In case insert failed.
*
* @return bool Whether the record is inserted successfully.
*/
public function insert(array|null $propertyNames = null): bool;
public function insert(array|null $properties = null): bool;

/**
* Checks if any property returned by {@see propertyNames()} method has changed.
Expand Down Expand Up @@ -358,9 +368,13 @@ public function relationQuery(string $name): ActiveQueryInterface;
public function resetRelation(string $name): void;

/**
* Saves the current record.
* Saves the changes to this active record into the associated database table.
* You may specify the properties to be updated as list of name or name-value pairs.
* If name-value pair specified, the corresponding property values will be modified.
*
* This method will call {@see insert()} when {@see isNewRecord()|isNewRecord} is true, or {@see update()} when
* Only the {@see newValues() changed property values} will be saved into a database.
*
* This method will call {@see insert()} when {@see isNewRecord()} is true, or {@see update()} when
* {@see isNewRecord()|isNewRecord} is false.
*
* For example, to save a customer record:
Expand All @@ -372,12 +386,18 @@ public function resetRelation(string $name): void;
* $customer->save();
* ```
*
* @param array|null $propertyNames List of property names that need to be saved. Defaults to `null`,
* meaning all changed property values will be saved.
* To save a customer record with specific properties:
*
* ```php
* $customer->save(['name' => $name, 'email' => $email]);
* ```
*
* @param array|null $properties List of property names or name-values pairs that need to be saved.
* Defaults to `null`, meaning all changed property values will be saved.
*
* @return bool Whether the saving succeeded (that's no validation errors occurred).
*/
public function save(array|null $propertyNames = null): bool;
public function save(array|null $properties = null): bool;

/**
* Sets the named property value.
Expand All @@ -400,7 +420,7 @@ public function set(string $propertyName, mixed $value): void;
* For example, to update a customer record:
*
* ```php
* $customer = new Customer();
* $customer = (new ActiveQuery(Customer::class))->findByPk(1);
* $customer->name = $name;
* $customer->email = $email;
* $customer->update();
Expand All @@ -409,9 +429,8 @@ public function set(string $propertyName, mixed $value): void;
* To update a customer record with specific properties:
*
* ```php
* $customer = new Customer();
* $customer->update(['name' => $name, 'email' => $email]);
* ```
* $customer->update(['name' => $name, 'email' => $email]);
* ```
*
* Note that it's possible the update doesn't affect any row in the table.
* In this case, this method will return 0.
Expand All @@ -428,6 +447,7 @@ public function set(string $propertyName, mixed $value): void;
* @param array|null $properties List of property names or name-values pairs that need to be saved.
* Defaults to `null`, meaning all changed property values will be saved.
*
* @throws InvalidCallException If the record {@see isNewRecord() is new}.
* @throws OptimisticLockException If the instance implements {@see OptimisticLockInterface} and the data being
* updated is outdated.
* @throws Throwable In case update failed.
Expand Down
Loading
Loading