仓储模式(一)

2018-06-04 02:44:05 语法专题 616 0

仓储模式

常应用于:与第三方对接、内部服务调用

  • Controller
    • 一个服务对应一个控制器
      • 比如,积分服务
        • 这层只负责数据过滤与Logic层调用
    • Logic
      • 一个服务对应一个逻辑类
        • 比如,积分服务,只负责调用 对应Process层的 run 方法
      • Process
        • 一个服务中的某个业务对应一个过程类
          • 比如,新用户送100积分,就是一个业务
          • run 方法负责接收来自控制器传入的数据
            • Rule
              • 一个 Rule 调用 Repository 中的一个方法
              • Repository
                • 实现具体逻辑
                  • 数据库操作(操作实体 - 某张表)
                  • 缓存操作(比如,存储与查询调用第三方应用时,需要的 access_token )
                  • 逐级传出结果到Controller
            • Entity
              • 记录当前操作,对实体数据(某张表)造成的影响(记录数据变化的具体细节)

示例:内部服务

Controller

<?php

namespace App\Http\Controllers;

use App\Logic\Point\Point;
use App\Logic\Point\PointCode;
use Illuminate\Http\Request;

class PointController extends BaseController
{

    /**
     * 商城下单,扣取积分
     *
     * @param Request $request
     * @return string
     */
    public function handleGoodsOrderDec(Request $request)
    {
        $filter = [
            'user_id'    => 'required',
            'related_id' => 'required',
        ];
        $this->validate($request, $filter);
        $params = [
            'user_id'    => $request->input('user_id'),
            'related_id' => $request->input('related_id'),
        ];
        $result = Point::handleGoodsOrderDec($params);

        $code    = array_get($result, 'code', PointCode::CODE_SUCCESS);
        $date    = array_get($result, 'data', []);
        $message = array_get($result, 'message', '');

        return $this->output($date, $code, $message);
    }

    /**
     * JSON输出
     *
     * @param array $data
     * @param integer $code
     * @param string $message
     * @return Json
     */
    private function output($data, $code = PointCode::CODE_SUCCESS, $message = '')
    {
        if (empty($message)) {
            $message = PointCode::getMessage($code);
        }

        $output = [
            'code'    => $code,
            'message' => $message,
            'data'    => $data,
        ];

        CustomLog::dayLog('user_point', 'POINT_OUTPUT', ['output' => $output]);

        return response()->json($output);
    }

}

Logic

<?php

namespace App\Logic\Point;

use App\Logic\Point\Processes\HandleGoodsOrderDecProcess;

class Point
{

    /**
     * 商城下单,扣取积分
     *
     * @param array $params
     * @return array
     */
    public static function handleGoodsOrderDec($params)
    {
        return HandleGoodsOrderDecProcess::run($params);
    }

}

Process

<?php

namespace App\Logic\Point\Processes;

use Log;
use App\Logic\Point\Helpers\ServiceException;
use App\Logic\Point\PointCode;
use App\Logic\Point\PointConst;
use App\Logic\Point\Domains\PointRule;
use App\Logic\Point\Entities\PointEntity;

class HandleGoodsOrderDecProcess
{
    public static function run($params)
    {
        try {
            $return = ['code' => PointCode::CODE_SUCCESS, 'data' => [], 'message' => ''];

            $user_id = $params['user_id'];
            $related_id = $params['related_id'];
            $action = PointConst::POINT_ACTION_GOODS_ORDER_DEC;
            $point = PointRule::getGoodsOrderDec($user_id, $related_id);
            \Log::info('HandleGoodsOrderDecProcess,point:'. $point);

            $point_entity = new PointEntity();
            $point_entity->setUserId($user_id);
            $point_entity->setRelatedId($related_id);
            $point_entity->setAction($action);
            $point_entity->setPoint($point);
            $point_entity->initPointInfo();
            $point_entity->doPointAction();

            $return['data'] = $point_entity->getUserPointInfo();

            return $return;

        } catch (ServiceException $e) {
            Log::error($e);
            $return['code'] = $e->getCode();
            $return['data'] = $e->getData();
            $return['message'] = $e->getMessage();
            return $return;
        }
    }

}

Rule

<?php

namespace  App\Logic\Point\Domains;

use App\Logic\Point\PointCode;
use App\Logic\Point\PointConst;
use App\Logic\Point\Repositories\PointRepository;
use App\Logic\Point\Helpers\ServiceException;

class PointRule
{

    /**
     * 检测商城下单操作是否重复
     *
     * @param string action
     * @param integer user_id
     * @param integer related_id
     * @return boolean
     */
    public static function getGoodsOrderDec($user_id, $related_id)
    {
        $action = PointConst::POINT_ACTION_GOODS_ORDER_DEC;
        $point_items = PointRepository::getUserPointItemsByAction($action, $user_id, $related_id);
        if (count($point_items)) {
            throw new ServiceException(PointCode::CODE_POINT_ADD_ITEM_EXISTS);
        }else{
            // 添加
            $point_res = PointRepository::getGoodsOrderDec($action, $user_id, $related_id);
        }
        return $point_res;
    }

}

Repository

<?php

namespace App\Logic\Point\Repositories;

use App\Logic\Point\Models\Order;

class PointRepository
{
    /**
     * 获取积分
     *
     * @param string $action
     * @param integer $user_id
     * @param integer $related_id
     * @return integer
     */
    public static function getGoodsOrderDec($action, $user_id, $related_id)
    {
        $point_goods = Order::where('id', $related_id)
            ->where('user_id', $user_id)
            ->first();

        return $point_goods ? $point_goods->user_bill : 0;
    }
}

Entity

<?php

namespace App\Logic\Point\Entities;

use App\Logic\Point\PointCode;
use App\Logic\Point\PointConst;
use App\Logic\Point\Domains\PointRule;
use App\Logic\Point\Helpers\ServiceException;
use App\Logic\Point\Repositories\PointRepository;

class PointEntity
{

    /**
     * 用户ID
     *
     * @var integer
     */
    private $user_id = 0;

    /**
     * 相关ID
     *
     * @var integer
     */
    private $related_id = 0;

    /**
     * 用户操作
     *
     * @var string
     */
    private $action = '';

    /**
     * 操作积分
     *
     * @var integer
     */
    private $point = 0;

    /**
     * 用户积分信息
     *
     * @var array
     */
    private $point_info = [];


    public function setUserId($user_id)
    {
        $this->user_id = $user_id;
    }

    public function setRelatedId($related_id)
    {
        $this->related_id = $related_id;
    }

    public function setAction($action)
    {
        $this->action = $action;
    }

    public function setPoint($point)
    {
        $this->point = $point;
    }

    /**
     * 获取用户当前积分信息
     *
     * @return array
     */
    public function getUserPointInfo()
    {
        $return = $this->point_info;
        $return['action_point'] = $this->point;

        return $return;
    }

    /**
     * 初始化积分实体
     *
     * @return void
     */
    public function initPointInfo()
    {
        $user_id = $this->user_id;
        $user_point = PointRepository::getUserPointInfo($user_id);
        if (empty($user_point)) {
            $user_point = PointRepository::initUserPointInfo($user_id);
        }

        $action = $this->action;
        $related_id = $this->related_id;
        $action_repeat = PointRule::checkActionRepeat($action, $user_id, $related_id);
        if ($action_repeat) {
            throw new ServiceException(PointCode::CODE_POINT_ACTION_REPEAT);
        }
        $times_limit = PointRule::checkTimesLimit($action, $user_id);
        if ($times_limit) {
            throw new ServiceException(PointCode::CODE_POINT_TIMES_LIMIT);
        }

        $this->point_info = $user_point;
    }

    /**
     * 积分操作执行
     *
     * @return array
     */
    public function doPointAction()
    {
        $user_id = $this->user_id;
        $related_id = $this->related_id;
        $action = $this->action;
        $point = $this->point;
        $point_info = $this->point_info;

        if (!isset(PointConst::$action_operate[$action])) {
            throw new ServiceException(PointCode::CODE_POINT_ACTION_NOT_DEFINE);
        }
        $operate = PointConst::$action_operate[$action];
        if ($operate == PointConst::USER_POINT_ITEM_OPERATE_INCR) {
            $old_point = $point_info['point'];
            $new_point = $old_point + $point;
        } else {
            $old_point = $point_info['point'];
            $new_point = $old_point - $point;
        }
        if ($new_point < 0) {
            throw new ServiceException(PointCode::CODE_POINT_DECR_NOT_ENOUGH);
        }

        $user_point = PointRepository::updateUserPointInfo($user_id, $related_id, $action, $operate, $point, $old_point, $new_point);

        $this->point_info = $user_point;
        return $user_point;
    }
}

附:PointConst

<?php

namespace App\Logic\Point;

class PointConst
{

    /**
     * 用户初始化默认积分
     */
    const USER_POINT_INIT_DEFAULT    = 0;

    /**
     * 用户积分状态
     */
    const USER_POINT_STATUS_VALID    = 1;
    const USER_POINT_STATUS_INVALID  = 2;

    /**
     * 积分加减
     */
    const USER_POINT_ITEM_OPERATE_INCR  = 1;
    const USER_POINT_ITEM_OPERATE_DECR  = 2;

    /**
     * 用户积分动作
     */
    const POINT_ACTION_GOODS_ORDER_DEC = 11;
    const POINT_ACTION_GOODS_ORDER_RES = 12;


    /**
     * 提现积分配置状态
     */
    const LOAN_POINT_STATUS_VALID    = 1;
    const LOAN_POINT_STATUS_INVALID  = 2;

    /**
     * 积分商品类型
     */
    const POINT_GOODS_TYPE_VIP_CARD  = 1;
    const POINT_GOODS_TYPE_LOTTERY   = 2;

    /**
     * 积分动作对应加减
     */
    static $action_operate = [
        self::POINT_ACTION_GOODS_ORDER_DEC => self::USER_POINT_ITEM_OPERATE_DECR,
        self::POINT_ACTION_GOODS_ORDER_RES => self::USER_POINT_ITEM_OPERATE_INCR,
    ];

    /**
     * 积分操作次数限制
     */
    static $action_limit = [
        self::POINT_ACTION_GOODS_ORDER_DEC => 1,
        self::POINT_ACTION_GOODS_ORDER_RES => 1,

    ];

    /**
     * 积分获取次数限制
     */
    static $times_limit = [
        self::POINT_ACTION_INVITE_REGISTER => 10,
        self::POINT_ACTION_INVITE_CREDIT   => 10,
    ];
}
注:若无特殊说明,文章均为云天河原创,请尊重作者劳动成果,转载前请一定要注明出处