哪种方法可以更好地保存模型属性?

时间:2014-12-12 20:53:44

标签: php oop cakephp

我有一个模型订单(模型在CakePhp中的外观),它具有属性 status 。当 Order 完成处理步骤时,此属性已更改。目前状态更改以这种方式工作:

我有相关的模型 OrderStatus ,其中我有一组可能的状态,例如

<?php
OrderStatus::STARTED
...
OrderStatus::PAID
...
OrderStatus::PROCESSED
订单模型中的

我有一个方法来更改状态

<?php
/**
 * Save new status value for Order.
 *  
 * @param  int $id Order id
 * @param  int $status   New status value
 * @param  int $current  [Optional] Current status value
 * @return boolean
 */
public function changeStatus($id, $status, $current = null) {
    // some code
}

当我需要在Controller或其他模型中的某处更改它时,我只需将其称为:

<?php
$Order->changeStatus($id, OrderStatus::PAID);

到目前为止,这个解决方案一切正常,但现在我想到这种方法是多么正确。如果明天我决定对特定的状态更改做一些额外的操作,那么我必须添加一些额外的逻辑并扩展changeStatus方法。另外我不喜欢的是我必须在需要更改订单状态的地方使用 OrderStatus 常量,因此它会在整个代码中传播。

添加单独的方法来设置每个新状态,在这些方法中使用 OrderStatus constans并将所有相关逻辑放在那里,并更改 Order <之外的状态更正确/ em>模型的方式如下:

<?php
$Order->makePaid($id);
// and 
$Order->makeProcessed($id);

从OOP原则和最佳实践角度来看哪一个更好,或者可能还有另一个更好的解决方案。

3 个答案:

答案 0 :(得分:1)

我建议Order对象应该表示单个订单(单个id),其中的方法与可以在订单上完成的操作相关。这应该是您的应用程序试图解决的问题。因此,如果需要支付订单,为什么不使用pay()方法;其副作用可以是设置正确的当前状态。同样适用于启动和流程。

class Order {

    private $id;
    private $currentStatus;

    //other methods...

    public function pay(Money $payment) {
        //handle payment etc.
        $this->currentStatus = OrderStatus::PAID;
    }

    public function start() {
        //do business logic related to starting an order.
        $this->currentStatus = OrderStatus::STARTED;
    }

    public function process() {
        //process an order
        $this->currentStatus = OrderStatus::PROCESSED;
    }

}

答案 1 :(得分:1)

首先,你和大多数的“MVC”(注意它是引用因为它们实际上不是MVC,而是更像是试图模仿模式而不是它们)框架称为“模型”是一个实体将业务逻辑融为一体。在大多数情况下,他们也使用Active Record模式,以便能够以更抽象的方式表示DB中的链接。

关于你的问题,首先,从“控制器”的角度来看是错误的(引用再次因为它不完全是一个控制器,因为它做了更多)与实体本身。更好的是,有一个“服务”层抽象出你想要做的事情,由“控制器”调用,而“服务”本身知道如何处理这些请求。我想说的是控制器只传递事件。

在你的情况下,应该有类似OrdersService的东西来保持订单的逻辑。例如:制作一个新的,支付此类订单等。控制器创建OrdersService的实例并调用$ordersService->createOrder($requiredData)$ordersService->processOrder($id)。然后另一方面OrdersService调用Order“模型”来分别处理这些事件。你在不同类中的逻辑分离越多越好。通常很多人都试图遵循框架的逻辑,最终会产生大量的上帝类,里面有太多的逻辑。

如果您想开始使用更好的OOP做法,请考虑阅读SOLID PrinciplesSeparation Of Concerns

答案 2 :(得分:1)

在“清洁代码”中,罗伯特·C·马丁建议说争论越少越好。最好为给定的动作创建专用方法,而不是具有大量参数的泛型方法。这样你的代码就会更具表现力。

在您的示例中,如果为每个更改状态的操作创建专用方法,则状态更改本身将成为订单对象的实现细节,并且不会在对象外部公开。它是一个很大的优势,因为你可以改变它,顺序依赖类不需要任何改变。