加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 钦州站长网 (https://www.0777zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

Lavavel 面向对象学习 - 代码修改后的面向对象风格

发布时间:2022-10-18 10:58:43 所属栏目:PHP教程 来源:
导读:  系列文章:

  Lavavel 面向对象学习 - 代码修改前过程方法风格Lavavel 面向对象学习 - 代码修改后的面向对象风格

  Lavavel 面向对象学习 - 代码修改后的面向对象风格需求分析

  因为消息模板
  系列文章:
 
  Lavavel 面向对象学习 - 代码修改前过程方法风格Lavavel 面向对象学习 - 代码修改后的面向对象风格
 
  Lavavel 面向对象学习 - 代码修改后的面向对象风格需求分析
 
  因为消息模板实际有多个的。业务进度消息只是其中一个模板。
 
  控制器类 WechatPushController.php
 
  返回给前端的公共对象类 ResultStandard.php
 
  消息类公共接口 InterfaceMessage.php
 
  业务进度消息类 MessageBusinessProgress.php
 
  微信推送消息类 WechatPush.php
 
  用户 openid 查找类 UserIdToOpenId.php
 
  代码真实可用。
 
  修改后的代码控制器类 WechatPushController.php
 
  class WechatPushController extends Controller
  {
      // 控制器方法,发送模板消息。
      public function template_message(Request $request, MessageBusinessProgress $message)
      {
          $user_id = $request->input('user_id');
          $message->setMessageTitle($request->input('message_title'));
          $message->setMessageOrderNo($request->input('message_order_no'));
          $message->setMessageContent($request->input('message_content'));
          $message->setMessageRemark($request->input('message_remark'));
          $json_result = $message->push($user_id);
          return response()->json( $json_result->to_json() )->setEncodingOptions(JSON_UNESCAPED_UNICODE);
      }
  }
  返回给前端的公共对象类 ResultStandard.php
 
  <?php
  namespace App\Services;
  /**
   * 公共结果对象
   *
   * @author  x
   */
  class ResultStandard
  {
      const RIGHT_CODE =200;
      protected $code;
      protected $message;
      protected $data;
      public function __construct(bool $boo, $data=[], $message='')
      {
          if ($boo) {
              $this->code = self::RIGHT_CODE;
          }
          $this->data = $data;
          $this->message=$message;
      }
      public static function get_instance(bool $boo, $data=[], $message='')
      {
          return new self($boo, $data, $message);
      }
      public function to_json()
      {
          if ($this->code == self::RIGHT_CODE ){
              return [
                  'code'   => $this->code,
                  'errMsg' =>'成功',
                  'data'=> $this->data,
              ];
          }
          return [
              'code'   => $this->code,
              'errMsg' =>$this->message ?: '错误',
              'data'=> $this->data ?: [],
          ];
      }
  }
  消息类公共接口 InterfaceMessage.php
 
  <?php
  namespace App\Services\ThirdApi\Wechat;
  use App\Services\ResultStandard;
  /**
   * 业务进度消息类公共接口
   *
   * @author  11
   */
  interface InterfaceMessage
  {
      // 获取业务进程消息的模板id
      public function get_template_id():string ;
      // 微信推送
      public function push($user_id): ResultStandard;
      //收集推送的数据。
      public function get_push_data():array;
  }
  业务进度消息类 MessageBusinessProgress.php
 
  <?php
  namespace App\Services\ThirdApi\Wechat;
  use App\Services\ResultStandard;
  /**
   * 业务进度消息类
   *
   * @author  11
   */
  class MessageBusinessProgress implements InterfaceMessage
  {
      const TEMPLATE_ID = 'f9it7NnvjG1XyxtRCGoFo-V7u96TIhT1ZP2yUfE-zNs';
      protected $message_order_no; // 订单号
      protected $message_title;    // 标题
      protected $message_content;  // 消息主体内容。控制在80个汉字以内比较好
      protected $message_remark;   // 简短的备注
      private $servicePush;
      private $serviceUser;
      public function __construct()
      {
          $this->servicePush = new WechatPush();
          $this->serviceUser = new UserIdToOpenId();
      }
      // 获取业务进程消息的模板id
      public function get_template_id():string
      {
          return self::TEMPLATE_ID;
      }
      // 微信推送
      public function push($user_id): ResultStandard
      {
          $user_id = intval($user_id);
          $openid = $this->serviceUser->find_openid($user_id);
          if (!$openid) {
              return ResultStandard::get_instance(false, [], $this->serviceUser->get_err());
          }
          try {
              $this->servicePush->push($this, $openid);
          } catch (\Exception $e) {
              return ResultStandard::get_instance(false, [], $e->getMessage());
          }
          return ResultStandard::get_instance(true);
      }
      public function get_push_data():array
      {
          return [
            'first' => $this->getMessageTitle(),
            'keyword1' => $this->getMessageOrderNo(),
            'keyword2' => $this->getMessageContent(),
            'keyword3' => date('Y-m-d H:i:s'),
            'remark' => $this->getMessageRemark(),
         ];
      }
      /**
       * @return mixed
       */
      public function getMessageOrderNo()
      {
          return $this->message_order_no;
      }
      /**
       * @param mixed $message_order_no
       */
      public function setMessageOrderNo($message_order_no): void
      {
          $this->message_order_no = $message_order_no;
      }
      /**
       * @return mixed
       */
      public function getMessageTitle()
      {
          return $this->message_title;
      }
      /**
       * @param mixed $message_title
       */
      public function setMessageTitle($message_title): void
      {
          $this->message_title = $message_title;
      }
      /**
       * @return mixed
       */
      public function getMessageContent()
      {
          return $this->message_content;
      }
      /**
       * @param mixed $message_content
       */
      public function setMessageContent($message_content): void
      {
          $this->message_content = $message_content;
      }
      /**
       * @return mixed
       */
      public function getMessageRemark()
      {
          return $this->message_remark;
      }
      /**
       * @param mixed $message_remark
       */
      public function setMessageRemark($message_remark): void
      {
          $this->message_remark = $message_remark;
      }
  }
  微信推送消息类
 
  <?php
  namespace App\Services\ThirdApi\Wechat;
  use App\Lib\Err;
  use EasyWeChat\Factory;
  /**
   * 微信推送
   *
   * @author  11
   */
  class WechatPush
  {
      use Err;
      protected $app;
      public function __construct()
      {
          $config = [
              'app_id' => config('yansongda.wechat.app_id'),
              'secret' => config('yansongda.wechat_secret'),
              'response_type' => 'array',
          ];
          $this->app = Factory::officialAccount($config);
      }
      /*
       * 推送微信模板消息
       *
       * //{{first.DATA}}
       * //业务单号:{{keyword1.DATA}}
       * //办理进度:{{keyword2.DATA}}
       * //时间:{{keyword3.DATA}}
       * //{{remark.DATA}}
       *
       * @param MessageBusinessProgress $message
       * @param string $openid
       * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
       * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
       * @throws \GuzzleHttp\Exception\GuzzleException
       */
      public function push(InterfaceMessage $message, string $openid)
      {
          $result = $this->app->template_message->send([
              'touser' => $openid,
              'template_id' => $message->get_template_id(),
              'url' => '',
              'miniprogram' => [],
              'data' => $message->get_push_data(),
          ]);
          return $result;
      }
  }
  用户 openid 查找类 UserIdToOpenId.php
 
  <?php
  namespace App\Services\ThirdApi\Wechat;
  use App\Lib\Err;
  use App\Models\User;
  use App\Models\UserWx;
  /**
   * 处理http.
   *
   * @author  11
   */
  class UserIdToOpenId
  {
      use Err;
      public  function  find_openid($user_id) : ?string
      {
          $user = User::find($user_id);
          if ($user && $user->union_id) {
              $wx_record = UserWx::query()->where('unionid', $user->union_id)->first();
              if ($wx_record && $wx_record->openid ) {
                  return $wx_record->openid;
              }else {
                  $this->set_err('用户未关注公司微信公众号,或关注记录没有保存openid字段');
              }
          }else {
              $this->set_err('用户不存在,或用户没有union_id');
          }
          return null;
      }
  }
  总结
 
  1、修改后,可维护性极大提高,总共也不知道多少行了,花去的时间至少是写修改前代码的 3 倍不止。
 
  2、从代码中可以看出,每个类功能单一,这是 solid 原则的最基本原则,已经实现。
 
  3、具体过程就是分析出有哪些对象,然后让对象之间互相交互。
 
  4、面向对象就是先写出高层代码,不考量具体实现,假定有一个类能够实现。
 
  5、然后把任务分解为一个个的类,直到不能继续分解任务了,再考量如何实现。
 
  6、比如当前这个需要,可以构造一个message 的具体类,里面有对应这个消息模板的字段,然后这个类有个方法叫做push,参数是user_id。为了set和get写的方便,我还用了phpstorm的功能:code - generate - getter and setter
 
  7、这个就是最核心的抽象,想象这个类非常聪明,它竟然能自己把自己发送出去,这样就可以了。
 
  8、为了实现这个目标,给这个类加成员变量,是实际发送消息的类,这样就真的自己可以发送自己了。具体方式就是把自己传给实际发送消息的类。
 
  9、之前还需要把 user_id 转变成 openid,不要自己实现,必须再把任务分配给其他类,保持单一职责。
 
  10、而为了能让实际发送消息类能不需要自己去分辨模板有哪些字段,可以让消息类自己有个拼凑发送字段的方法。
 
  11、实际上,获取openid的类也可以再修改,比如它的目的是获取openid,所以可以有个方法是get_open_id,然后构造方法带一个用户id这样。
 
  12、对比一下修改前的代码就可以知道PHP面向对象,这里经过了大量的思考,大量的修改。当然消耗的时间也是成数倍增长的。
 
  13、修改之后的代码是可以写单元测试的。这里可以 mock 微信的返回格式来测试其余的代码。
 
  14、之前的过程代码就很难测试。因为访问了实际的微信服务器。
 
  15、所以,为了让自己的代码通过单元测试,你只能精心的进行面向对象编程。
 
  16、反过来,不在乎单元测试,则各种可能都有,代码可能好,也可能不好,因为没人强制。而只要为了早下班,不加班,同时催的急,就只能面向过程了,毕竟简单直接,无需思考各种对象交互。也就是修改前的代码。
 
  17、其实只要多写多练多实践,面向对象也就慢慢习惯了,并没有特别难以理解的地方。
 

(编辑:PHP编程网 - 钦州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!