php事务管理器,php – 在控制器中做事务管理不好的做法?

我说交易不属于模型层的原因基本是这样的:

模型可以调用其他模型中的方法。

如果一个模型尝试启动事务,但是它不知道它的调用者是否已经开始一个事务,那么模型必须有条件地启动事务,如@Bubba’s answer中的代码示例所示。模型的方法必须接受一个标志,使得呼叫者可以告诉它是否允许开始自己的事务。否则,该模型必须具有查询其呼叫者“处于交易”状态的能力。

public function setPrivacy($privacy, $caller){

if (! $caller->isInTransaction() ) $this->beginTransaction();

$this->privacy = $privacy;

// ...action code..

if (! $caller->isInTransaction() ) $this->commit();

}

如果调用者不是对象怎么办?在PHP中,它可以是静态方法或简单的非面向对象的代码。这变得非常混乱,并在模型中导致了很多重复的代码。

这也是Control Coupling的一个例子,这被认为是坏的,因为调用者必须知道被叫对象的内部工作。例如,您的Model的某些方法可能具有$事务参数,但其他方法可能没有该参数。调用者如何知道参数的重要性?

// I need to override method's attempt to commit

$video->setPrivacy($privacy, false);

// But I have no idea if this method might attempt to commit

$video->setFormat($format);

我看到的另一个解决方案(甚至在某些框架如Propel中实现)是在DBAL知道它已经在一个事务中时,使beginTransaction()和commit()没有操作。但是,如果您的模型尝试提交并发现它没有真正提交,这可能会导致异常。或者尝试回滚并忽略该请求。之前我写过这些异常。

我建议的妥协是,模型不了解交易。该模型不知道其对setPrivacy()的请求是否应该立即提交,或者它是更大图片的一部分,涉及多个模型的更复杂的一系列更改,只有在所有这些更改成功时才应该提交。这就是交易点。

那么,如果模型不知道他们是否可以开始和提交自己的交易,那么谁呢? GRASP包括一个用于用例的非UI类的Controller pattern,它被分配负责创建和控制所有的部分以完成该用例。控制器知道事务,因为这是所有信息都可以访问的地方,完整的用例是否复杂,并且需要在一个事务中(或者可能在几个事务中)在模型中进行多个更改。

我以前写过的例子,就是在MVC控制器的beforeAction()方法中启动一个事务,并在afterAction()方法中提交它,这是一个简化。控制器应该随意启动和提交尽可能多的交易,以便完成当前的操作。或者有时控制器可以避免显式的事务控制,并允许模型自动提交每个变化。

但关键的是,有关什么变革的信息是必需的,这是模型不知道的 – 它们必须被告知(以$事务参数的形式),或者从调用者中查询它,无论如何,将不得不将问题转交给控制人的行动。

您还可以创建一个Service Layer的类,每个类都知道如何执行这种复杂的用例,以及是否将所有更改包含在单个事务中。这样你就避免了很多重复的代码。但是,PHP应用程序包含不同的服务层并不常见;控制器的操作通常与服务层重合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值