使用策略模式和简单工厂模式重写支付模块(二)-优化$request

前情提要

上一篇文章 使用策略模式和简单工厂模式重写支付模块 最后提到有 两点不足之处 后来思考了下觉得可以用一个实体类,把需要的参数都 set 进实体,用 get 方法获取参数,这样 $request 既可以不向下传递,使用 get 方法获取参数又能很明确。

建立实体类

  1. 根据 vipStrategy策略 第三步中,提取临时订单中公共的数据添加对应的成员方法,并添加 getset 方法,完成公共实体类

     namespace App\Http\Services\PayOrder\Strategy;
    
     abstract class Entity
     {
         protected $ip;
         protected $packageCope;
         protected $code;
         protected $uid;
         protected $type;
    
         public function __construct(Request $request)
         {
             $this->ip          = $request->getClientIp();
             $this->code        = $request->get('code');
             $this->uid         = Auth::id();
             $this->packageCope = app(PayOrderService::class)->getVipByCode($this->code);
    
             // 为成员方法 `set` 值
             foreach ($request->all() as $fields => $value) {
                 $property = 'set' . Str::studly($fields);
                 if (property_exists($this, $fields)) {
                     $this->$property = $value;
                 }
             }
         }
    
         public function getIp() { return $this->ip;}
         public function setIp($ip) { $this->ip = $ip;}
    
         public function getCode() { return $this->code;}
         public function setCode($code) { $this->code = $code;}
    
         public function getUid() { return $this->uid;}
         public function setUid($uid) { $this->uid = $uid;}
    
         public function getType() { return $this->type;}
         public function setType($type) { $this->type = $type;}
    
         public function getPackageCope() { return $this->packageCope;}
         public function setPackageCope($packageCope) {$this->packageCope = $packageCope;}
     }
  2. 开通vip实体类

     namespace App\Http\Services\PayOrder\Entity;
    
     class VipEntity extends Entity
     {
         // 开通vip月数
         protected $buyMonth;
    
         public function getBuyMonth() { return $this->buyMonth;}
         public function setBuyMonth($buyMonth){ $this->buyMonth = $buyMonth;}
     }

修改代码

vip 接口

public function vip(Request $request)
{
    $strategy = new VipStrategy();

      // 原代码将$request向下传传递
    $tmpOrderKey = (new PayOrderContext($strategy))->createOrder($request);
      // 修改后:通过VipEntity() 构造实体
      $vipEntity   = new VipEntity($request);
    $tmpOrderKey = (new PayOrderContext($strategy))->createOrder($vipEntity);

    return $this->data(['key' => $tmpOrderKey]);
}

VipStrategy.php

原来:接收vip接口传入的 $request

function createTemporaryOrder(Request $request)
{
    $packageCode = $request['code'];
      $buyMonth    = $request['buy_month'];
    $package     = app(PayOrderService::class)->getVipByCode($packageCode);

    // 临时订单数据
    $tmpOrder = [
        'package_cope' => $package->toArray(),
        'type'         => PayOrderService::TYPE_VIP,
        'uid'          => 1,
        'ip'           => $request->ip(),
        'buy_month'    => $buyMonth
        // ....
    ];
}

修改后:接收实体类,通过 $entity 可明确知道有什么参数

function createTemporaryOrder(Entity $entity)
{
    // 临时订单数据
    $tmpOrder = [
        'package_cope' => $entity->getPackageCope(),
        'type'         => PayOrderService::TYPE_VIP,
        'uid'          => $entity->getUid(),
        'ip'           => $entity->getIp(),
        'buy_month'    => $entity->getBuyMonth()
        // ....
    ];

    $tmpOrderKey = app(PayOrderService::class)->saveTemporaryOrder($tmpOrder);

    return $tmpOrderKey;
}

总结

  • 建立 VipEntity 实体类之后就可以明确参数,并且将 $request 留在控制器中不再向下传递。
  • 第二个问题不明确 redis 临时订单中有什么数据也可以建立一个实体类,然后想参数 set 完成后就可以愉快的 get 了。
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 4

实体类构造方法里的 getVipByCode是不是要考量一下

3年前 评论
zxr615 (楼主) 3年前

$this->$property = $value; 这个没有看明白

1年前 评论
zxr615 (楼主) 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!