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的那個字段有哪個錯。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.