配置参数
Memcache 配置, 在
/app/config/config.ini
文件添加以下代码:
[memcache] host = 127.0.0.1 port = 11211 prefix = api
在 Visual NMP 中,默认已经安装了 Memcache, 可直接使用。如服务未开启,直接打开即可。 默认连接端口:
11211
。缓存键名前缀:prefix = api
,方便区分项目,可随意设置, 一般设置为项目名。
「PHP开发APP接口实战001」开发环境搭建
短信配置, 在
/app/config/config.php
文件添加以下代码:
'sms' => [ 'times' => 3, // 同一手机一小时内发送短信次数, 0 为不限制 'interval' => 60, // 同一手机两次发送间隔时间(单位:秒), 0 为不限制 'valid_time' => 300, // 短信验证码有效时间(单位:秒), 0 为久有效 ],
创建 Memcache 操作类 XMemcache
在 /app/library
目录下创建文件 XMemcache.php
, 添加以下代码:
<?php/** * 缓存 */class XMemcache{ public static $instance; private $memcache = null; // Memcache 对象 private $config = null; // 配置参数 private $tag = null; // 标识 private function __construct($tag = null) { // 初始化 Memcache 对象 $this->memcache = new Memcache(); // 加载配置参数 $this->config = Config::instance()->get('memcache', 'ini'); // 连接Memcache服务器 $this->memcache->addServer($this->config['host'], $this->config['port']); $this->tag = $tag; } /** * @param null $tag 缓存标识 * @return XMemcache */ public static function instance($tag = null) { if (!self::$instance) self::$instance = new self($tag); return self::$instance; } /** * 添加缓存,若不存在则追加,若不存在则新增 * @param $key 键名 * @param $value 缓存内容 * @param int $timeout 0永久有效,604800 7天,最大不能超过30天 * @param int $iszip * @return mixed */ public function append($key, $value, $timeout = 604800, $iszip = 0) { if ($values = $this->get($key)) { $values[] = $value; } else { $values = [$value]; } $this->set($key, $values, $timeout, $iszip); } /** * 设置缓存 * @param $key 键名 * @param $value 缓存内容 * @param int $timeout 0永久有效,604800 7天,最大不能超过30天 * @param int $iszip * @return mixed */ public function set($key, $value, $timeout = 604800, $iszip = 0) { $value = serialize($value); return $this->memcache->set($this->formatKey($key), $value, $iszip, $timeout); } /** * 根据KEY获得缓存内容 * @param $key * @return mixed */ public function get($key) { $value = $this->memcache->get($this->formatKey($key)); return unserialize($value); } /** * 删除指定缓存 * @param $key * @return mixed */ public function delete($key) { return $this->memcache->delete($this->formatKey($key)); } /** * 清空缓存 * @return mixed */ public function flush() { return $this->memcache->flush(); } /** * 重写缓存键名,格式: [prefix]:[tag]:[key] * @param $key * @return string */ private function formatKey($key) { return $this->config['prefix'] . ':' . $this->tag . ':' . $key; } }
这里重写了一些
Memcache
常用的操作函数。 如:设置缓存set()
, 追加缓存append()
, 获取缓存get()
, 删除缓存delete()
, 清空缓存flush()
值得注意的是,我们还对缓存键名进行了重写,方便区分项目和模块。
生成短信验证码
在
/app/library
目录下创建文件SMS.php
, 添加以下代码:
<?php/** * 短信验证码 */class SMS{ public static $instance; // 配置参数 private $config = null; private function __construct() { // 加载短信配置参数 $this->config = Config::instance()->get('sms'); } public static function instance() { if (!self::$instance) self::$instance = new self(); return self::$instance; } }
这里实现了实例化时,自己加载配置参数。
增加验证码改送函数
send()
, 用于外部调用。如:
/** * 发送短信验证码 * @param $mobile * @return array * @throws Exception */ public function send($mobile) { }
此函数里面分四步走:
验证指定手机号,当前是否可以发送验证码
生成四位数字验证码,并配置上生成时间
调用
XMemcache
缓存验证码调用第三方接口,发送验证码,并返回发送状态。(市场上有许多发送第三方平台,都有)
这里调换一下顺序,先讲解生成和缓存验证码。
首先,添加函数generateCode()
, 随机生成4位数字验证码
/** * 随机生成4位数字验证码 * @return int */ private function generateCode() { return rand(1000, 9999); }
然后,在 send()
函数中添加代码:
$item = [ 'code' => $this->generateCode(), // 生成短信验证码 'time' => time(), // 生成时间 'verified' => 0, // 验证状态: 0 未验证, 1 已验证 ];
这里除了生成验证码,同时初始化生成时间
time
, 验证状态verified
,用于验证发送时间和检查验证码是否已验证。
缓存验证码,在
send()
函数中添加代码:
// 缓存短信验证码 XMemcache::instance('sms')->append($mobile, $item, 3600);
这里完成了几个工作:
将
$item
存于以指定手机号为键名的缓存下同一手机号多次发送,都存在同一键名下,用于统计1小时内验证码发送次数。
缓存有效时间设置为 1 小时
现在我们再回来讲解验证是否允许向指定手机号发送验证码。
验证规则:
同一手机两次发送间隔时间1分钟(可配置间隔时间)
同一手机1小时内最多只能发送3次验证码(可配置发送次数)
首先,添加函数 getCacheCodes()
和 validateSend()
, 如:
/** * 获取1小时内发送的验证码 * @param $mobile * @return null */ private function getCacheCodes($mobile) { $codes = XMemcache::instance('sms')->get($mobile); if (!$codes) return []; foreach ($codes as $index => $item) { // 过滤发送超过1小时的验证码 if (time() - $item['time'] > 3600) { unset($codes[$index]); } } // 重置数组索引 $codes = array_values($codes); // 更新缓存 XMemcache::instance('sms')->set($mobile, $codes); return $codes; } /** * 验证是不否允许发送 * @param $mobile * @throws Exception */ private function validateSend($mobile) { $codes = $this->getCacheCodes($mobile); if ($this->config['times'] > 0 && count($codes) >= $this->config['times']) { throw new Exception('一小时内最多只能发送' . $this->config['times'] . '次短信验证码'); } $lastCode = end($codes); if ($this->config['interval'] > 0 && time() - $lastCode['time'] <= $this->config['interval']) { throw new Exception('发送频率太快'); } }
函数
getCacheCodes()
获取指定手机1小时内发送的验证码。函数
validateSend()
实现:
验证一小时内向同一手机发送短信验证码次数是否超过了配置次数;
验证上次发送验证码是否已经超过配置时间;
然后在 send()
函数中,所有代码之前插入代码 $this->validateSend($mobile);
。send()
函数完整代码:
/** * 发送短信验证码 * @param $mobile * @return array * @throws Exception */ public function send($mobile) { // 验证短信发送次数 $this->validateSend($mobile); $item = [ 'code' => $this->generateCode(), // 生成短信验证码 'time' => time(), // 生成时间 'verified' => 0, // 验证状态: 0 未验证, 1 已验证 ]; // 缓存短信验证码 XMemcache::instance('sms')->append($mobile, $item, 3600); // 发送短信验证码 /* ... 调用第三方接口 ... */ return $item; }
再在控制器
SmsController
类的sendAction()
函数中加入以下代码:
// 发送验证码 $result = SMS::instance()->send($this->getPost('user_mobile')); if ($result) {// Output::instance($this->response)->success(’发送成功‘); Output::instance($this->response)->success((object)$result); } else { Output::instance($this->response)->fail('发送失败'); }
这里没有真正实现调用第三方接口,而是直接返回了发送的验证码,以供测试使用。正式代码,只返回发送状态。
SmsController.php
完整代码:
<?phpclass SmsController extends BaseController{ /** * 发送短验证码 */ public function sendAction() { // 验证请求方法是否是POST $this->isPost(); // 验证请求参数 XValidationSms::send($this->getPost()); // 发送验证码 $result = SMS::instance()->send($this->getPost('user_mobile')); if ($result) {// Output::instance($this->response)->success(’发送成功‘); Output::instance($this->response)->success((object)$result); } else { Output::instance($this->response)->fail('发送失败'); } } }
接口调试示例
请求方式:POST
请求参数:user_mobile=18088888888
返回数据:
{ "status": "1", "value": "发送成功"}
开发调试时返回数据 :
{ "status": "1", "item": { "code": "1139", "time": "1520663958", "verified": "0" } }
作者:一念觀心
链接:https://www.jianshu.com/p/0dbdf556b4f3