【问题标题】:Phalcon: transactions and complex modelsPhalcon:交易和复杂模型
【发布时间】:2013-01-29 08:14:47
【问题描述】:

在我的项目中,我有 entities 表,所有实体都应该存在(以支持复杂的外键),所以我需要在特殊表中插入额外的行(在这个实体列表中),然后再将一行插入我的模型表,我想问一下最好的方法是什么。

因此,对于以下代码,我需要插入两行:在entity 表中,然后为刚刚插入的行选取 id,将其保存在当前模型中并插入accounts 表中:

$account = new Account();
$account->name = 'John';
$account->save(); // performs two inserts while creating model

据我所知,我可以使用 beforeCreate() 方法在entity 表中插入行并为新创建的行获取 id,就像这样:

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() 方法都有小事务,当我需要复杂操作的事务时它会如何工作?

例如

// 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 的实现方法,我在下面添加了它的代码,但它看起来像一个 hack,我也不想使用它:

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

支持此类复杂实体的最佳且简单的方法是什么?

【问题讨论】:

    标签: model phalcon


    【解决方案1】:

    实现事务的最简单方法是使用 0.9.0:

    class Account
    {
        public function beforeCreate()
        {
            $entity = new \Entity();
            $entity->type = get_class($this);
            $this->entity = $entity;
        }
    
        public function initialize()
        {
            $this->belongsTo(array('entity_id', 'Entity', 'id'));
        }
    
    }
    

    另一方面,事务管理器创建一个隔离连接,允许您查询在当前事务快照中修改的记录,以及查看未隔离的记录。

    这里有新文档中对不同交易场景的解释:http://docs.phalconphp.com/en/0.9.0/reference/models.html#transactions

    【讨论】:

    • 嗯...如果 $account->save() 失败,是否有机会回滚插入“实体”行?
    • 如果无法保存帐户,则不会创建实体行,对吗?第二个问题:是否可以将隐式事务与手动事务(在控制器操作层)和隔离事务一起使用?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-20
    相关资源
    最近更新 更多