在 Laravel 中使用 又拍云 的短信服务很简单,但这里主要讨论设计模式: 服务层。
简单讲,服务层可以抽象你的程序逻辑,正如其名,提取通用的服务逻辑,这样只需要在一处,服务层(Service Layer)维护代码即可。
回到这个案例,Upyun 短信发送跟各个服务商大同小异:
- 前端收集手机号码
- 生成短信参数
- 调用短信发送 API
- 处理返回,成功或失败
第三步调用短信发送 API 可以被抽象成服务层,这样,你就可以在不同的控制器方便调用,借助 Laravel 的服务容器,这一过程非常轻松愉悦。
安装依赖: composer require guzzlehttp/guzzle
然后在 app
目录下创建 Services
目录及 UpyunMessenger.php
文件,如果你愿意,可以用自己喜欢的别的名字,但为了使用 PSR-4 自动加载的便利,请记得更改以下代码中的命名空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| <?php namespace App\Services;
use Illuminate\Contracts\Config\Repository; use GuzzleHttp\Client as GuzzleClient; use GuzzleHttp\Psr7\Request as GuzzleRequest;
class UpyunMessenger { protected $uri; protected $method; protected $token; protected $templateId;
protected $client;
function __construct(Repository $config, GuzzleClient $client) { $this->uri = $config['services']['upyun_messenger']['uri']; $this->method = $config['services']['upyun_messenger']['method']; $this->token = $config['services']['upyun_messenger']['token']; $this->templateId = $config['services']['upyun_messenger']['template_id'];
$this->client = $client; }
public function send(string $phoneNumber, string $code) { $request = new GuzzleRequest($this->method, $this->uri); $response = $this->client->send($request, [ 'headers' => [ 'Authorization' => $this->token, ], 'form_params' => [ 'mobile' => $phoneNumber, 'template_id' => $this->templateId, 'vars' => $code, ], ]); return json_decode($response->getBody()); } }
|
之后,就可以在需要的控制器,在构造时自动注入该服务类并调用方法即可,如 PhoneNumberController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| use App\Services\UpyunMessenger;
class PhoneNumberController extends Controller { public function __construct(UpyunMessenger $messenger) { $this->messenger = $messenger; }
public function sendVerification(Request $request, $user) { $code = 'abcdef'; $this->messenger->send($request->phone_number, $code); } }
|
可以看到,只需要定义一个服务类,在控制器中的注入是自动完成的,正如在服务类中注入 app 配置,这完全归功于 Laravel 实现的强大的服务容器(即控制反转IoC或依赖注入DI)。