MVC模式中如何區分應用程序邏輯(Controller層)和業務邏輯(Model層)?


現在的大部分框架都是 MVC 模式,但 MVC 三個部分怎么配合,這里做了一點總結:
基本原則:業務邏輯代碼應該寫在 M 里面,而應用程序邏輯應該寫在 C 里面。V 只是單純的展示數據。
舉個簡單例子吧:用戶往購物車添加一個商品
用戶點擊商品的“添加到購物車”按鈕,引起一次請求。服務器開始處理該請求,過程:
1、檢查當前用戶是否有權限(比如是否已經登錄、用戶帳戶狀態、是否可以購物等)
2、檢查要添加的商品ID是否有效、
3、檢查要添加的商品庫存是否足夠
4、將商品加入購物車,並保存購物車狀態
5、反饋信息
在上述流程中:
1: 是應用程序邏輯(一般由框架實現):因為和“添加商品到購物車”這個業務沒有直接關系
2: 業務邏輯:不能購買不存在的商品,這是業務進行的基本條件
3: 業務邏輯:商品庫存決定了是否可以購買此商品,這是業務進行的基本條件
4: 業務邏輯
5: 應用程序邏輯
用代碼表示的,可能像下面這樣:
// Cart控制器
class Controller_Cart
{
    function actionAddGoods()
    {
        $goods_id = (int)$_GET['goods_id'];
        Cart::instance()->add($goods_id)->save();
        
        echo '添加成功';
    }
}


// Cart 模型
class Cart
{
    /**
     * 購物車中的所有項目
     */
    public $items = array();
   
    /**
     * 單子模式,返回購物車對象的唯一實例
     */
    static function instance()
    {
        ...
    }
   
    function add($goods_id, $quantity = 1)
    {
        $goods = Goods::find($goods_id)->get();
        // 檢查 id 和庫存數
        if ($goods->id && $quantity > $goods->remaining)
        {
            // 添加商品到購物車
            $this->items[] = array($goods, $quantity);
        }
        else
        {
            throw new CartExecption('無效的商品 ID');
        }
        return $this;
    }
}

這個代碼不完整,但是演示了最重要的部分,就是應用程序邏輯和業務邏輯的分離。
如果這個流程走下去,用戶要結算了,那么代碼如下:
class Controller_Cart
{
    function actionCheckOut()
    {
        Cart::instance()->checkout();
        
        echo '成功';
    }
}
class Cart
{
    function checkout()
    {
        // 開啟一個數據庫事務
        ....
        
        try
        {
            // 創建一個新的訂單對象
            // $this->owner 是當前購物車的所有者(用戶)
            $order = new Order($this->owner);
            
            // 將購物車中的所有商品添加到訂單中
            foreach ($this->items as $item)
            {
                list($goods, $quantity) = $item;
                $order->add($goods, $quantity);
            }
            // 保存訂單
            $order->save();
            
            // 清空購物車
            $this->items = array();
        }
        catch (Exception $ex)
        {
            // 出錯了,回滾事務
            ....
               
            // 再重新拋出異常
            throw $ex;
        }
        
        // 返回新建的訂單
        return $order;
    }
}


class Order extends Model
{
    public $items;
   
    function add($goods, $quantity)
    {
        $this->items[] = array($goods, $quantity);
        return $this;
    }
   
    function save()
    {
        foreach ($this->items as $item)
        {
            list($goods, $quantity) = $item;
            // 保存訂單時,減少訂單中每一個商品的庫存數
            $goods->decrRemaining($quantity);
        }
        
        // 調用父類的保存
        parent::save();
        
        return $this;
    }
}

結算的代碼很容易理解:
1、調用購物車的 checkout() 方法
2、開啟數據庫事務,這樣當保存訂單失敗時(例如庫存數不夠)則回滾,確保數據庫內容沒有受影響
3、將購物車中的所有商品添加到訂單
4、調用訂單對象的 save() 方法
  4.1、遍歷訂單的所有項目,減少商品的庫存(如果此時失敗,商品的 decrRemaining() 方法會拋出異常)
  4.2、調用模型父類的 save() 方法
5、清空購物車,返回新建的訂單對象


整個流程我們假定創建訂單就等同於客戶確認訂單,此時減少庫存。也有可能是后台確認訂單配貨后才減少庫存,這和賣家的經營策略有關。

這兩個例子里面,業務邏輯都在模型中實現,控制器(也就是封裝應用程序邏輯的層)僅僅完成處理輸入數據、調用業務方法、反饋結果等任務。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM