В моем проекте у меня есть таблица entities
, в которой должны существовать все сущности (для поддержки сложных внешних ключей), поэтому мне нужно вставить дополнительную строку в специальную таблицу (в этот список сущностей), прежде чем вставлять строку в таблицу моей модели, и я хотел спросите, как лучше всего это сделать.
Итак, для следующего кода мне нужно вставить две строки: в таблицу entity
, затем взять идентификатор только что вставленной строки, сохранить его в текущей модели и вставить в таблицу accounts
:
$account = new Account();
$account->name = 'John';
$account->save(); // performs two inserts while creating model
Как я понял, я могу использовать метод beforeCreate() для вставки строки в таблицу entity
и получения идентификатора для вновь созданной строки, что-то вроде этого:
class Account
{
public function beforeSave()
{
$entity = new \Entity();
$entity->type = get_class($this);
$entity->save();
$this->id = $entity->id;
}
}
Но таким образом, если каким-либо образом строка счета не будет вставлена, строка в таблице entity
будет существовать.
Затем я решил использовать транзакции, как показано в документах здесь http://docs.phalconphp.com/en/latest/reference/models.html#transactions
Но я не понимаю, если у меня есть небольшие транзакции для каждого метода model::create(), как это будет работать, когда мне понадобятся транзакции для сложных операций?
e.g.
// controller action context
use Phalcon\Mvc\Model\Transaction\Manager as TxManager,
Phalcon\Mvc\Model\Transaction\Failed as TxFailed;
try {
//Create a transaction manager
$manager = new TxManager();
// Request a transaction
$transaction = $manager->get();
$account = new Account();
$account->setTransaction($transaction);
$account->name = "WALL·E";
$account->created_at = date("Y-m-d");
if ($account->save() == false) { // sub-transaction inside account::create() method
$transaction->rollback("Cannot save account");
}
$accountPart = new AccountPart();
$accountPart->setTransaction($transaction);
$accountPart->type = "head";
if ($accountPart->save() == false) { // sub-transaction inside accountPart::create() method
$transaction->rollback("Cannot save account part");
}
//Everything goes fine, let's commit the transaction
$transaction->commit();
} catch(TxFailed $e) {
echo "Failed, reason: ", $e->getMessage();
}
Трудно представить, как это будет работать в большом проекте. Вложенные транзакции не очень хороши для производительности базы данных.
Также я подумал о 3D-методе реализации, я добавил его код ниже, но он выглядит как хак, и я также не хочу его использовать:
public function create($data = null)
{
// Create abstract entity instance
$entity = new \Entity();
$entity->type = get_class($this);
// Save abstract entity
if (!$entity->save()) {
return false;
}
// Save current entity
$this->id = $entity->id;
$result = parent::create($data);
// Remove abstract entity if current row was not saved
if (!$result) {
$entity->delete();
}
return $result;
}
Каков наилучший и простой способ поддержки таких сложных объектов?