提示
本教程相关代码托管在Gitee:gitee.com/toshcn/micr…
创建UserRegisterForm注册账号表单,通过表单接入前端输入,验证输入的数据,生成用户表记录。
修改Utils工具类
打开common/components/Utils.php文件,增加正则验证方法,修改内容如下:
<?php
/**
* @link https://gitee.com/toshcn/micro-hau
* @copyright Copyright (c) 2022/4/20 micro-hau
* @author toshcn <toshcn@foxmail.com>
*/
namespace common\components;
use yii\base\BaseObject;
/**
* 公共的常用工具类组件 调用方式 \Yii::$app->utils->方法名()
* Class Utils
* @package common\components
*/
class Utils extends BaseObject
{
// ...
// 增加以下内容
/**
* 正则检查
* @param {String} value 要检查的值
* @param {Object} type 正则检查类型:cn_mobile手机号
* @return bool|false|int
*/
public static function regExp($value, $type)
{
if (empty($value)) {
return false;
}
$res = false;
switch ($type) {
case 'cn_mobile':
/**
* 数据卡:14号段以前为上网卡专属号段,如中国联通的是145,中国移动的是147,中国电信的是149等等。
* 虚拟运营商:170[1700/1701/1702]、162(电信),1703/1705/1706、165(移动),1704/1707/1708/1709(联通)、171、167(联通)
* 卫星通信: 1740[0-5] (电信),1349(移动)
* 物联网网号:10648、1440 (移动),10646、146(联通),10649、1410(电信)
* 国家工信部应急通信:1740[6-9],1741[0-2]
* 手机号码: 13[0-9], 14[5,6,7,8,9], 15[0-3, 5-9], 16[2,5,6,7], 17[0-8], 18[0-9], 19[0-3, 5-9]
* 移动号段: 13[4-9],147,148,15[0-2,7-9],165,170[3,5,6],172,178,18[2-4,7-8],19[5,7,8]
* 联通号段: 130,131,132,145,146,155,156,166,167,170[4,7,8,9],171,175,176,185,186,196
* 电信号段: 133,149,153,162,170[0,1,2],173,174[0-5],177,180,181,189,19[0,1,3,9]
* 广电号段: 192
*
* 作者:bingxuePI
* 链接:https://www.jianshu.com/p/5fbb85967bfd
*/
$res = preg_match('/^(13[0-9]|14[5-9]|15[0-3,5-9]|16[2,5,6,7]|17[0-8]|18[0-9]|19[0-3,5-9])\d{8}$/i', $value);
break;
case 'power_password':
// 强密码 必须包含大小写字母和数字的组合,长度在8-20之间
$res = preg_match('/^.*(?=.{8,20})(?=.*\d)(?=.*[A-Z]{1,})(?=.*[a-z]{1,})(?=.*[!@#$%^&*?\(\)]{0,}).*$/', $value);
break;
}
return $res;
}
}
修改BaseModel类
打开common/models/BaseModel.php文件,获取表单第一个校验错误字段,修改内容如下:
<?php
/**
* @link https://gitee.com/toshcn/micro-hau
* @copyright Copyright (c) 2022/4/21 micro-hau
* @author toshcn <toshcn@foxmail.com>
*/
namespace common\models;
use yii\base\Model;
/**
* 公共模型基类
* Class BaseModel
* @package common\models
*/
class BaseModel extends Model
{
/**
* 获取表单第一个校验错误信息
* @return string
*/
public function getFirstErrorMessage()
{
$msg = \Yii::t('common', 'Field Error.');
if ($this->getErrors()) {
foreach ($this->getErrors() as $name => $error) {
return $msg = $error[0];
}
}
return $msg;
}
/**
* 获取表单第一个校验错误字段
* @return string|boolean
*/
public function getFirstErrorField()
{
if ($this->getErrors()) {
foreach ($this->getErrors() as $name => $error) {
return $name;
}
}
return false;
}
/**
* 获取表单第一个校验错误的第一个错误信息
* @return array|boolean
*/
public function getFirstOneError()
{
if ($this->getErrors()) {
foreach ($this->getErrors() as $name => $error) {
return [$name => $error[0]];
}
}
return false;
}
}
修改Api控制器类,增加检测POST请求方法
打开api/controllers/ApiController.php文件,增加内容如下:
<?php
/**
* @link https://gitee.com/toshcn/micro-hau
* @copyright Copyright (c) 2022/4/20 micro-hau
* @author toshcn <toshcn@foxmail.com>
*/
namespace api\controllers;
use yii\rest\Controller;
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
/**
* API 项目基类控制器 api项目所有接口控制器都要继承此类
* Class ApiController
* @package api\controllers
*/
class ApiController extends Controller
{
const ERROR_CODE_NOT_POST = 4405; // 接口错误码 不是POST请求
const ERROR_CODE_FORM_FIELD_ERROR = 4001; // 接口错误码 表单字段错误
const ERROR_CODE_FORM_ERROR = 5000; // 接口错误码 服务器出错 表单保存出错
// ...
/**
* 检测post请求
* 如果非post请求,发送4405代码
* @return mixed
*/
public function validateIsPost()
{
if (!\Yii::$app->getRequest()->getIsPost()) {
$response = \Yii::$app->getResponse();
$response->data = \Yii::$app->api->error(static::ERROR_CODE_NOT_POST, \Yii::t('common', 'The request is not in a post way.'));
$response->send();
}
return true;
}
}
修改User模型类,增加密码生成和验证方法
打开common/models/User.php文件,修改内容如下:
<?php
/**
* @link https://gitee.com/toshcn/micro-hau
* @copyright Copyright (c) 2022/4/16 micro-hau
* @author toshcn <toshcn@foxmail.com>
*/
namespace common\models;
use Yii;
use yii\db\ActiveRecord; // 活动记录模型
use yii\filters\RateLimitInterface; // 速率限制接口
use yii\web\IdentityInterface; // 用户身份接口
// ...
class User extends ActiveRecord implements IdentityInterface, RateLimitInterface
{
// ...
// 增加如下方法
/**
* 验证密码
* @param string $password 用户密码
* @return bool
*/
public function validatePassword($password)
{
$pwd = sha1(md5($password . $this->password_salt));
return Yii::$app->getSecurity()->validatePassword($pwd, $this->password_hash);
}
/**
* 生成账号密码
* @param string $password
* @throws \yii\base\Exception
*/
public function setPassword($password)
{
$passwordHashTimes = 10;//密码时间强度 数值越大 运行速度越慢
// 随机生成20位字符 作为密码盐值
$this->password_salt = Yii::$app->getSecurity()->generateRandomString(20);
$pwd = sha1(md5($password . $this->password_salt)); // 密码生成算法
// 生成密码哈希值
$this->password_hash = Yii::$app->getSecurity()->generatePasswordHash($pwd, $passwordHashTimes);
}
/**
* 生成Api登录认证token
* Generates access token
* @throws \yii\base\Exception
*/
public function generateAccessToken()
{
// 生成唯一的token
$this->access_token = md5($this->country_code . $this->mobile . '_' . Yii::$app->getSecurity()->generateRandomString(20));
// token过期时间
$this->access_token_expire = time() + 7 * 86400;
}
}
创建UserRegisterForm账号注册表单类
在项目api/modules/v1/forms目录下创建UserRegisterForm.php文件,文件内容如下:
<?php
/**
* @link https://gitee.com/toshcn/micro-hau
* @copyright Copyright (c) 2022/4/21 micro-hau
* @author toshcn <toshcn@foxmail.com>
*/
namespace api\modules\v1\forms;
use common\models\User;
use Yii;
use common\models\BaseModel;
/**
* User模型注册表单
* Class UserForm
* @package api\modules\v1\forms
*/
class UserRegisterForm extends BaseModel
{
public $mobile; // 用户账号手机号
public $countryCode = 86; // 用户账号手机号国家代码: 86(中国)
public $nickname; // 用户账号昵称
public $password; // 用户账号密码
private $_user = null; // 用户对象
/**
* 表单字段规则
* @return array
*/
public function rules()
{
return [
[['mobile', 'nickname', 'password'], 'trim'],
[['countryCode'], 'number', 'skipOnError' => true],
[['mobile', 'countryCode', 'nickname', 'password'], 'required'],
['mobile', 'validateMobile', 'skipOnError' => true], // 行内验证器 检测手机号码格式
// 限制手国家代码+机号码唯一
[
['mobile'],
'unique',
'skipOnError' => true,
'targetClass' => User::class,
'targetAttribute' => ['mobile', 'countryCode' => 'country_code'],
// 自定义错误消息
'message' => Yii::t('common', 'Mobile "{value}" has already been taken.')
],
// 限制昵称唯一
[
['nickname'],
'unique',
'skipOnError' => true,
'targetClass' => User::class,
'targetAttribute' => ['nickname'],
'message' => Yii::t('common', 'Nickname "{value}" has already been taken.')
],
];
}
/**
* 检测手机号码格式
* @param string $attribute 当前检测的字段名
* @param array $params 以名-值对形式提供的额外参数
* @param \yii\validators\InlineValidator $validator 当前行内验证器 InlineValidator实例。此参数自版本 2.0.11 起可用。
*/
public function validateMobile($attribute, $params, $validator)
{
if (!$this->hasErrors()) {
if (!Yii::$app->utils->regExp($this->$attribute, 'cn_mobile')) {
$validator->addError($this, $attribute, Yii::t('common', 'The mobile "{value}" is invalid for {attribute}.'));
}
}
}
/**
* 返回用户对象
* @return null|@common\models\User
*/
public function getUser()
{
return $this->_user;
}
/**
* 注册账号
* @return bool
*/
public function register()
{
// 打开数据库事务
$trans = Yii::$app->getDb()->beginTransaction();
try {
// rules()规则都验证通过
if ($this->validate()) {
$user = new User();
$user->mobile = $this->mobile;
$user->nickname = $this->nickname;
$user->country_code = $this->countryCode;
$user->generateAccessToken(); // 生成api接口token
$user->setPassword($this->password); // 生成密码
$user->created_at = $user->updated_at = date('Y-m-d H:i:s');
if ($user->save(false)) {
// 创建用户成功 提交事务
$trans->commit();
$this->_user = $user; // 保存用户对象
return true;
}
}
// 创建失败 数据库回滚
$trans->rollBack();
} catch(\Exception $e) {
$trans->rollBack();
}
return false;
}
}
创建AccountControll账号控制器类
在项目api/modules/v1/controllers目录下创建AccountControll.php文件,文件内容如下:
<?php /** @noinspection PhpUndefinedFieldInspection */
/**
* @link https://gitee.com/toshcn/micro-hau
* @copyright Copyright (c) 2022/4/22 micro-hau
* @author toshcn <toshcn@foxmail.com>
*/
namespace api\modules\v1\controllers;
use Yii;
use api\controllers\ApiController;
use api\modules\v1\forms\UserRegisterForm;
/**
* 账号登录,注册相关控制器
* Class AccountController
* @package api\modules\v1\controllers
*/
class AccountController extends ApiController
{
/**
* 账号注册
*/
public function actionRegister()
{
$this->validateIsPost();
$form = new UserRegisterForm();
// 从post中取出数据,赋值给注册表单对应字段
if ($form->load(Yii::$app->getRequest()->post(), '') && $form->register()) {
return Yii::$app->api->success();
}
if ($form->hasErrors()) {
return Yii::$app->api->error(parent::ERROR_CODE_FORM_FIELD_ERROR, $form->errors);
}
return Yii::$app->api->error(parent::ERROR_CODE_FORM_ERROR, Yii::t('common', 'Account registration failed.'));
}
}
测试接口
用Postman模拟请求,设置请求标头content-type为application/json; charset=UTF-8,
提交表单如:
{
"mobile": "13188888888",
"password": "Test12345678",
"nickname": "test"
}
将会看到如下内容:
{
"status": 1,
"code": 1,
"message": "success",
"data": []
}