组成部分
配置文件/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的那个字段有哪个错。