HOOK的使用和思考


組成部分
配置文件/advanced/mobile/config/params-hook.php
    這個hook的配置文件,就是一個名稱對應一個數組,每個數組都是由一個class和一個params項組成。
return [
    'CheckCartGoods' => [
        //when submit order check goods in cart
        [
            'class' => 'mobile\models\hooks\CheckDeliveryDate',
            'params' => []
        ],
        //check cart goods amount more than 188
        [
            'class' => 'mobile\models\hooks\CheckTotalAmountLimit',
            'params' => ['total' => 188]
        ],
    ],
    'GeneratedOrderHook' => [
        //submit order,generated order record then execute
        [
            'class' => 'mobile\models\hooks\UpdateCheckout',
            'params' => []
        ],
        //del cart goods which is submitted
        [
            'class' => 'mobile\models\hooks\UpdateCartGoods',
            'params' => []
        ],
        //no need pay order redirect
        [
            'class' => 'mobile\models\hooks\SetNoNeedPayOrder',
            'params' => []
        ],
        //create dispatch record
        [
            'class' => 'mobile\models\hooks\CreateOrderDispatch',
            'params' => []
        ],
    ],
    'PayMoneyHook' => [
        //pay id is 1,cash money pay
        [
            'class' => 'mobile\models\hooks\CashPayment',
            'params' => []
        ],
        //pay id is 9, weixin pay
        [
            'class' => 'mobile\models\hooks\WeixinPayment',
            'params' => []
        ],
        //pay id is 2, alipay pay
        [
            'class' => 'mobile\models\hooks\AlipayPayment',
            'params' => []
        ],
    ],
    //pay success hook
    'PaySuccessHook' => [
        [
            'class' => 'mobile\models\hooks\UpdatePayStatus',
            'params' => []
        ],
        [
            'class' => 'mobile\models\hooks\PushMessage',
            'params' => []
        ]
    ],
    'LoginSuccessHook' => [
        //login success hook
        [
            'class' => 'mobile\models\hooks\UpdateWXOpenId',
            'params' => []
        ],
    ],
];

2.接口類
   /advanced/common/vendor/hook/HookInterface.php
namespace common\vendor\hook;
interface HookInterface
{
    function execute($data);
}

3. 抽象類
/advanced/common/vendor/hook/BaseHook.php
這個類實現了hook接口,其核心就是executeHook($hook, $data)方法。
讀取配置文件,根據方法傳入的參數$hook這樣就能讀取到全部要處理的class,實例化,執行這個class的execute方法


<?php
/**
 * base hook.
 * User: root
 * Date: 7/1/15
 * Time: 2:00 PM
 */

namespace common\vendor\hook;

use common\libs\Constant;
use yii;
use yii\base\Exception;
use yii\web\Controller;

/**
 * Class BaseHook
 * @package common\vendor\hook
 */
abstract class BaseHook extends Controller implements HookInterface
{
    /**
     * unset init function
     */
    public function __construct(){}
    /**
     * @param array $data
     * @param array $configParams which in configuration file (params-hook.php) params
     * @return  mixed it must return $data structure as same as pass in or throw Exception
     */
    abstract function execute($data, $configParams = []);

    /**
     * execute hook
     * @param string $hook
     * @param array $data
     * @return bool|array
     */
    public static function executeHook($hook = '', & $data = [])
    {
        $params = Yii::$app->params;
        try {
            if (!isset($params[$hook])) {
                Constant::throwException(Constant::ERROR_INVALID_PARAM);
            }
            $hooks = $params[$hook];
            if (empty($hook) || !is_array($hooks) || !is_array($data)) {
                Constant::throwException(Constant::ERROR_INVALID_PARAM);
            }
            $returnData = $data;
            foreach ($hooks as $hook) {
                if (isset($hook['class'])) {
                    $hookObj = new $hook['class']();
                    $returnData = $hookObj->execute($returnData, $hook['params']);
                    if (!is_array($returnData)) {
                        Constant::throwException(Constant::ERROR_RETURN_DATA);
                    }
                    //check data structure ,it can not change
                    /*if (array_diff(array_keys($data), array_keys($returnData))) {
                        throw new Exception(Constant::$returnMsg[Constant::ERROR_DATA], Constant::ERROR_DATA);
                    }*/
                }
            }
            $data = $returnData;
        }
        catch (Exception $e) {
            Yii::info($e->getMessage());
            return Constant::getReturn($e->getCode(), $e->getMessage());
        }
        return Constant::getReturn(Constant::SUCCESS);
    }
}

4. 具體實現類
/advanced/mobile/models/hook/UpdateCheckout.php
namespace mobile\models\hooks;


use common\libs\Constant;
use common\models\Checkout;
use common\vendor\hook\BaseHook;

class UpdateCheckout extends BaseHook
{

    public function execute($data, $params = [])
    {
        if (isset($data['order_sn'])) {
            $checkout = [
                'pay_sn' => $data['order_sn'],
                'pay_id' => 0,
                'amount' => $data['order_amount'] * 100,
                'status' => $data['pay_status'],
                'add_time' > time(),
            ];
            $model = new Checkout();
            $model->setAttributes($checkout);
            if (!$model->save()) {
                Constant::throwException(Constant::SAVE_DATA_FAILED);
            }
        }
        return $data;
    }

}



思考1

hook的本質是:根據參數(hook配置的鍵名)讀取配置文件中的一個配置,是一個或者一組類,分別實例化每個類再調用他們的excute方法。

實現類中代碼(上面代碼紅色部分),利用了類的繼承、多態特性。

因爲每一個hook的實現類,都是實現了hook抽象類,因此他們必須實現抽象方法execute(),這是類的繼承特性的體現。

對於任何hook實現類對象,他們也都是BaseHook類的對象,調用其execute方法,就會根據這個對象具體的實現類,調用對象的具體的execute方法。這就是類的多態特性的實現。

思考2
yii2.0中的rules驗證過程如下
讀取rules中的每條數據(每條數據是一個數組,由數據項,規則名稱,其他參數等組成),根據每條數據的第二項規則名稱,看它是行內驗證器(在當前model中自定義的方法)還是內部驗證器(在yii中驗證器數據中有),來實例化對應的校驗類的對象,組成一個對象數組。
遍歷這個校驗類對象組成的數組,調用其validate方法校驗指定的數據,有錯誤,就把錯誤寫到model類的_errors類變量中,指明model的那個字段有哪個錯。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章