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的那个字段有哪个错。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值