商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > 怎样用 PHP 实现简单的短链接生成器_基于进制转换算法实现

怎样用 PHP 实现简单的短链接生成器_基于进制转换算法实现

  发布于2026-07-10 阅读(0)

扫一扫,手机访问

很多人在实现短链接时都会遇到一个选择——到底用62进制还是16进制?这个问题看似基础,但背后确实藏了一些设计逻辑。

怎样用 PHP 实现简单的短链接生成器_基于进制转换算法实现

短链接为什么用 62 进制而不是 16 进制

原因是,16进制(0–9 + a–f)总共只有16个字符,生成的ID映射太短,很容易被暴力猜出原始URL。而62进制(0–9 + a–z + A–Z)提供了62个唯一字符,在同样长度下能编码的整数范围要大得多——比如6位62进制数可以表示大约568亿个ID,对大多数中小项目来说,长期使用都够用了。

关键不是“进制多高级”,而是要在实际字符集中避开容易混淆的那些,比如0O1l。实践中常用的是精简版62进制表,像这样:'23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'(去掉了0O1lI等)。

PHP 中怎么把自增 ID 转成短码(encode)

核心思路是模拟“除k取余”的过程,但不能直接用base_convert()——它不支持自定义字符集,也不处理0的边界情况。

实践中的做法是:

  • 用循环对ID做取模和整除,每次取$chars[floor($id % 62)],然后$id = floor($id / 62)
  • 当ID为0时需要单独返回第一个字符,否则循环不执行,即if ($id === 0) return $chars[0];
  • 结果字符串要strrev(),因为余数是从低位开始取的。
  • 不要用递归实现,大ID(比如大于1e6)可能触发PHP栈溢出。

示例代码:

$chars = '23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';function idToShort($id, $chars) {    if ($id === 0) return $chars[0];    $short = '';    while ($id > 0) {        $short .= $chars[$id % 62];        $id = (int)($id / 62);    }    return strrev($short);}

怎么把短码还原回 ID(decode)

这是encode的逆过程:从左到右遍历字符,在$chars中查索引,按位权累加。注意大小写敏感,strpos()array_search()更快,且不依赖键名。

容易踩的坑:

  • 输入含非法字符(如-_、空格)会导致strpos()返回false,后续计算直接崩掉——提前用preg_match('/^[2-9a-zA-Z]+$/', $short)校验一下就好。
  • 没处理空字符串或超长串(比如超过10位),可能会隐式转换出错——建议限制长度为2–8位。
  • pow(62, $i)计算位权,浮点误差在高位时会导致ID偏移——改用整型累乘:$multiplier *= 62

示例代码:

function shortToId($short, $chars) {    if (!preg_match('/^[2-9a-zA-Z]{2,8}$/', $short)) return false;    $id = 0;    $multiplier = 1;    for ($i = strlen($short) - 1; $i >= 0; $i--) {        $pos = strpos($chars, $short[$i]);        if ($pos === false) return false;        $id += $pos * $multiplier;        $multiplier *= 62;    }    return $id;}

数据库怎么存、怎么防重复和并发冲突

短码本质上是ID的“别名”,不是随机字符串,所以不能靠uniqid()random_bytes()生成——那样无法反解,也丧失了映射的确定性。

必须基于主键ID编码,因此流程是:插入原始URL → 获取自增ID → encode成短码 → 更新该记录的short_code字段

这里有几个常见的坑:

  • 不加事务,高并发下两个请求可能拿到相同ID并生成相同短码——必须用INSERT ... ON DUPLICATE KEY UPDATE或先SELECT FOR UPDATE
  • 短码字段没建唯一索引,重复插入失败后没有兜底重试——short_code列必须加UNIQUE索引。
  • 用MyISAM引擎,不支持行锁——换成InnoDB,配合事务和INSERT ... SELECT来避免竞态。

真正考验功夫的往往不是算法本身,而是确保“ID → 短码”整个过程幂等,并且在数据库层面不允许出现多个URL映射到同一个短码的情况。

本文转载于:https://www.php.cn/faq/2398522.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注