Модель транзакций
Когда процесс выполняет несколько операций с базой данных, может быть важно, чтобы каждый шаг был выполнен успешно, чтобы сохранить целостность данных. Транзакции обеспечивают возможность гарантировать, что все операции с базой данных были успешно выполнены до того, как данные будут сохранены в базе данных.
Транзакции в Phalcon позволяют вам подтвердить все операции, если они были выполнены успешно, или откатить все операции, если что-то пошло не так.
Ручные транзакции
Если приложение использует только один соединение и транзакции не очень сложные, транзакцию можно создать, просто переведя текущее соединение в режим транзакции, а затем подтвердить или отменить операцию, независимо от того, была ли она успешной или нет:
use Phalcon\Mvc\Controller;
class RobotsController extends Controller
{
public function saveAction()
{
// Start a transaction
$this->db->begin();
$robot = new Robots();
$robot->name = "WALL·E";
$robot->created_at = date("Y-m-d");
// The model failed to save, so rollback the transaction
if ($robot->save() === false) {
$this->db->rollback();
return;
}
$robotPart = new RobotParts();
$robotPart->robots_id = $robot->id;
$robotPart->type = "head";
// The model failed to save, so rollback the transaction
if ($robotPart->save() === false) {
$this->db->rollback();
return;
}
// Commit the transaction
$this->db->commit();
}
}
Неявные транзакции
Существующие отношения могут использоваться для хранения записей и их связанных экземпляров, такой вид операции неявно создаёт транзакцию, чтобы гарантировать правильное хранение данных:
$robotPart = new RobotParts();
$robotPart->type = "head";
$robot = new Robots();
$robot->name = "WALL·E";
$robot->created_at = date("Y-m-d");
$robot->robotPart = $robotPart;
// Creates an implicit transaction to store both records
$robot->save();
Изолированные транзакции
Изолированные транзакции выполняются в новом соединении, гарантируя, что весь сгенерированный SQL, проверки виртуальных внешних ключей и бизнес-правила изолированы от основного соединения. Такой тип транзакции требует менеджера транзакций, который глобально управляет каждой созданной транзакцией, гарантируя, что они правильно отменяются/подтверждаются до завершения запроса:
use Phalcon\Mvc\Model\Transaction\Failed as TxFailed;
use Phalcon\Mvc\Model\Transaction\Manager as TxManager;
try {
// Create a transaction manager
$manager = new TxManager();
// Request a transaction
$transaction = $manager->get();
$robot = new Robots();
$robot->setTransaction($transaction);
$robot->name = "WALL·E";
$robot->created_at = date("Y-m-d");
if ($robot->save() === false) {
$transaction->rollback(
"Cannot save robot"
);
}
$robotPart = new RobotParts();
$robotPart->setTransaction($transaction);
$robotPart->robots_id = $robot->id;
$robotPart->type = "head";
if ($robotPart->save() === false) {
$transaction->rollback(
"Cannot save robot part"
);
}
// Everything's gone fine, let's commit the transaction
$transaction->commit();
} catch (TxFailed $e) {
echo "Failed, reason: ", $e->getMessage();
}
Транзакции могут использоваться для удаления многих записей согласованным способом:
use Phalcon\Mvc\Model\Transaction\Failed as TxFailed;
use Phalcon\Mvc\Model\Transaction\Manager as TxManager;
try {
// Create a transaction manager
$manager = new TxManager();
// Request a transaction
$transaction = $manager->get();
// Get the robots to be deleted
$robots = Robots::find(
"type = 'mechanical'"
);
foreach ($robots as $robot) {
$robot->setTransaction($transaction);
// Something's gone wrong, we should rollback the transaction
if ($robot->delete() === false) {
$messages = $robot->getMessages();
foreach ($messages as $message) {
$transaction->rollback(
$message->getMessage()
);
}
}
}
// Everything's gone fine, let's commit the transaction
$transaction->commit();
echo "Robots were deleted successfully!";
} catch (TxFailed $e) {
echo "Failed, reason: ", $e->getMessage();
}
Транзакции повторно используются независимо от того, где был получен объект транзакции. Новая транзакция генерируется только при выполнении commit() или rollback(). Вы можете использовать контейнер сервисов для создания глобального менеджера транзакций для всего приложения:
use Phalcon\Mvc\Model\Transaction\Manager as TransactionManager
$di->setShared(
"transactions",
function () {
return new TransactionManager();
}
);
Затем обратитесь к нему из контроллера или представления:
use Phalcon\Mvc\Controller;
class ProductsController extends Controller
{
public function saveAction()
{
// Obtain the TransactionsManager from the services container
$manager = $this->di->getTransactions();
// Or
$manager = $this->transactions;
// Request a transaction
$transaction = $manager->get();
// ...
}
}
Пока активна транзакция, менеджер транзакций всегда будет возвращать одну и ту же транзакцию по всему приложению.
© 2011–2017 Phalcon Framework Team
Licensed under the Creative Commons Attribution License 3.0.
https://docs.phalconphp.com/en/latest/reference/model-transactions.html