106 行
3.1 KiB
PHP
106 行
3.1 KiB
PHP
<?php
|
||
|
||
namespace addons\shopro\service\user;
|
||
|
||
use think\Db;
|
||
use fast\Random;
|
||
|
||
/**
|
||
* 用户昵称规范生成服务
|
||
* 规则:HL + 手机尾号后4位(如 HL5758);若重复则追加递增数字(如 HL57581, HL57582...)
|
||
*/
|
||
class NicknameService
|
||
{
|
||
/** 前缀 */
|
||
const PREFIX = 'HL';
|
||
|
||
/**
|
||
* 生成符合规范且数据库唯一的昵称
|
||
*
|
||
* @param string|null $mobile 手机号(可选)
|
||
* @param int $excludeUserId 排除的用户ID(用于修改资料校验重名时排除自身)
|
||
* @return string 规范昵称
|
||
*/
|
||
public static function generate($mobile = '', $excludeUserId = 0)
|
||
{
|
||
$suffix = self::extractMobileSuffix($mobile);
|
||
|
||
// 基础昵称:HL + 尾号4位
|
||
$baseNickname = self::PREFIX . $suffix;
|
||
|
||
// 查重并保证全局唯一
|
||
return self::ensureUnique($baseNickname, $excludeUserId);
|
||
}
|
||
|
||
/**
|
||
* 提取手机号后4位,若手机号无效则生成4位随机数字
|
||
*
|
||
* @param string|null $mobile
|
||
* @return string 4位数字字符
|
||
*/
|
||
public static function extractMobileSuffix($mobile = '')
|
||
{
|
||
if (!empty($mobile)) {
|
||
// 清除非数字字符(如 +86、空格、破折号)
|
||
$digits = preg_replace('/\D/', '', (string) $mobile);
|
||
if (strlen($digits) >= 4) {
|
||
return substr($digits, -4);
|
||
}
|
||
}
|
||
|
||
// 手机号不足4位或未提供时,生成4位随机数字
|
||
return sprintf('%04d', mt_rand(1000, 9999));
|
||
}
|
||
|
||
/**
|
||
* 确保昵称在数据库 fa_user 表中唯一
|
||
* 若已存在,则追加递增数字后缀(如 HL57581、HL57582...)
|
||
*
|
||
* @param string $baseNickname 基础昵称
|
||
* @param int $excludeUserId 排除的用户ID
|
||
* @return string 唯一昵称
|
||
*/
|
||
public static function ensureUnique($baseNickname, $excludeUserId = 0)
|
||
{
|
||
// 1. 若基础昵称未被占用,直接使用
|
||
if (!self::isNicknameTaken($baseNickname, $excludeUserId)) {
|
||
return $baseNickname;
|
||
}
|
||
|
||
// 2. 若被占用,从数字 1 开始追加尝试(HL57581, HL57582 ...)
|
||
$seq = 1;
|
||
while (true) {
|
||
$candidate = $baseNickname . $seq;
|
||
if (!self::isNicknameTaken($candidate, $excludeUserId)) {
|
||
return $candidate;
|
||
}
|
||
$seq++;
|
||
// 安全防死循环上限
|
||
if ($seq > 9999) {
|
||
return $baseNickname . mt_rand(1000, 9999);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查昵称是否已被占用
|
||
*
|
||
* @param string $nickname 候选昵称
|
||
* @param int $excludeUserId 排除的用户ID
|
||
* @return bool
|
||
*/
|
||
public static function isNicknameTaken($nickname, $excludeUserId = 0)
|
||
{
|
||
try {
|
||
$query = Db::name('user')->where('nickname', $nickname);
|
||
if ($excludeUserId > 0) {
|
||
$query->where('id', '<>', $excludeUserId);
|
||
}
|
||
return $query->count() > 0;
|
||
} catch (\Throwable $e) {
|
||
// 若在脱机/无DB连接测试环境,放行
|
||
return false;
|
||
}
|
||
}
|
||
}
|