-
-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
175 additions
and
136 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Yiisoft\ActiveRecord\Trait; | ||
|
||
use Throwable; | ||
use Yiisoft\ActiveRecord\ActiveRecordInterface; | ||
use Yiisoft\ActiveRecord\TransactionalInterface; | ||
|
||
use function in_array; | ||
|
||
/** | ||
* Trait to implement transactional operations and {@see TransactionalInterface} for ActiveRecord. | ||
* | ||
* @see ActiveRecordInterface::insert() | ||
* @see ActiveRecordInterface::update() | ||
* @see ActiveRecordInterface::delete() | ||
*/ | ||
trait TransactionalTrait | ||
{ | ||
public function delete(): int | ||
{ | ||
if (!$this->isTransactional(TransactionalInterface::OP_DELETE)) { | ||
return $this->deleteInternal(); | ||
} | ||
|
||
$transaction = $this->db->beginTransaction(); | ||
|
||
try { | ||
$result = $this->deleteInternal(); | ||
$transaction->commit(); | ||
|
||
return $result; | ||
} catch (Throwable $e) { | ||
$transaction->rollBack(); | ||
throw $e; | ||
} | ||
} | ||
|
||
public function insert(array $attributes = null): bool | ||
{ | ||
if (!$this->isTransactional(TransactionalInterface::OP_INSERT)) { | ||
return $this->insertInternal($attributes); | ||
} | ||
|
||
$transaction = $this->db->beginTransaction(); | ||
|
||
try { | ||
$result = $this->insertInternal($attributes); | ||
if ($result === false) { | ||
$transaction->rollBack(); | ||
} else { | ||
$transaction->commit(); | ||
} | ||
|
||
return $result; | ||
} catch (Throwable $e) { | ||
$transaction->rollBack(); | ||
throw $e; | ||
} | ||
} | ||
|
||
public function isTransactional(int $operation): bool | ||
{ | ||
return in_array($operation, $this->transactions(), true); | ||
} | ||
|
||
public function transactions(): array | ||
{ | ||
return [ | ||
TransactionalInterface::OP_INSERT, | ||
TransactionalInterface::OP_UPDATE, | ||
TransactionalInterface::OP_DELETE, | ||
]; | ||
} | ||
|
||
public function update(array $attributeNames = null): int | ||
{ | ||
if (!$this->isTransactional(TransactionalInterface::OP_UPDATE)) { | ||
return $this->updateInternal($attributeNames); | ||
} | ||
|
||
$transaction = $this->db->beginTransaction(); | ||
|
||
try { | ||
$result = $this->updateInternal($attributeNames); | ||
if ($result === 0) { | ||
$transaction->rollBack(); | ||
} else { | ||
$transaction->commit(); | ||
} | ||
|
||
return $result; | ||
} catch (Throwable $e) { | ||
$transaction->rollBack(); | ||
throw $e; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Yiisoft\ActiveRecord; | ||
|
||
interface TransactionalInterface | ||
{ | ||
/** | ||
* The insert operation. This is mainly used when overriding {@see transactions()} to specify which operations are | ||
* transactional. | ||
*/ | ||
public const OP_INSERT = 0x01; | ||
|
||
/** | ||
* The update operation. This is mainly used when overriding {@see transactions()} to specify which operations are | ||
* transactional. | ||
*/ | ||
public const OP_UPDATE = 0x02; | ||
|
||
/** | ||
* The delete operation. This is mainly used when overriding {@see transactions()} to specify which operations are | ||
* transactional. | ||
*/ | ||
public const OP_DELETE = 0x04; | ||
|
||
/** | ||
* Returns a value indicating whether the specified operation is transactional. | ||
* | ||
* @param int $operation The operation to check. Possible values are {@see OP_INSERT}, {@see OP_UPDATE} and | ||
* {@see OP_DELETE}. | ||
* | ||
* @return bool Whether the specified operation is transactional. | ||
*/ | ||
public function isTransactional(int $operation): bool; | ||
|
||
/** | ||
* Declares which DB operations should be performed within a transaction in different scenarios. | ||
* | ||
* The supported DB operations are: {@see OP_INSERT}, {@see OP_UPDATE} and {@see OP_DELETE}, which correspond to the | ||
* {@see insert()}, {@see update()} and {@see delete()} methods, respectively. | ||
* | ||
* By default, these methods are NOT enclosed in a DB transaction. | ||
* | ||
* In some scenarios, to ensure data consistency, you may want to enclose some or all of them in transactions. You | ||
* can do so by overriding this method and returning the operations that need to be transactional. For example, | ||
* | ||
* ```php | ||
* return [ | ||
* 'admin' => self::OP_INSERT, | ||
* 'api' => self::OP_INSERT | self::OP_UPDATE | self::OP_DELETE, | ||
* // the above is equivalent to the following: | ||
* // 'api' => self::OP_ALL, | ||
* | ||
* ]; | ||
* ``` | ||
* | ||
* The above declaration specifies that in the "admin" scenario, the insert operation ({@see insert()}) should be | ||
* done in a transaction; and in the "api" scenario, all the operations should be done in a transaction. | ||
* | ||
* @return array The declarations of transactional operations. The array keys are scenarios names, and the array | ||
* values are the corresponding transaction operations. | ||
*/ | ||
public function transactions(): array; | ||
} |