配置参数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