本文目录导读:

生成短链接的核心思路就是建立“短码”和“长链接”的映射关系,并进行重定向,下面从流程、算法、数据库设计和代码实现四个层面拆解。
核心流程(一次完整请求)
用户访问短链 http://a.cn/xYz9k
↓
PHP 解析 URL,取出短码 "xYz9k"
↓
查数据库/缓存:SELECT long_url FROM short_urls WHERE short_code = 'xYz9k'
↓
找到后,返回 301/302 重定向到长链接
↓
浏览器跳转到目标网站
短码生成算法(重点)
短码一般由 62个字符(0-9、a-z、A-Z)组成,长度通常 6~8 位。
随机字符串(简单但需防冲突)
function generateShortCode($length = 6) {
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$code = '';
for ($i = 0; $i < $length; $i++) {
$code .= $chars[random_int(0, 61)];
}
return $code;
}
缺点:需要查重,并发高时可能冲突。
自增ID + 进制转换(推荐,无冲突)
- 数据库插入一条记录,获得自增ID(10001)
- 将这个ID转换为62进制字符串,作为短码
function idToShortCode($id) {
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$code = '';
while ($id > 0) {
$code = $chars[$id % 62] . $code;
$id = intdiv($id, 62);
}
return str_pad($code, 6, '0', STR_PAD_LEFT); // 补位,保证长度
}
优点:绝对不冲突,还可以反向解码(由短码推出ID,便于统计)。
MD5/SHA1 截取(适合无需存储的短码)
$code = substr(md5($longUrl . time() . rand()), 0, 6);
缺点:碰撞概率高(6位62进制 = 568亿组合),需查重,且无法反向解码做统计。
数据库设计
CREATE TABLE short_urls (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
short_code VARCHAR(10) NOT NULL UNIQUE,
long_url TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
visit_count INT DEFAULT 0,
INDEX idx_code (short_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
PHP 完整实现
生成接口(接收长链接,返回短链接)
// generate.php
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$longUrl = $_POST['url'] ?? '';
if (!filter_var($longUrl, FILTER_VALIDATE_URL)) {
die('Invalid URL');
}
// 首先检查是否已存在
$stmt = $pdo->prepare("SELECT short_code FROM short_urls WHERE long_url = ?");
$stmt->execute([$longUrl]);
$exists = $stmt->fetchColumn();
if ($exists) {
echo "http://a.cn/{$exists}";
exit;
}
// 插入获取自增ID
$pdo->prepare("INSERT INTO short_urls (long_url) VALUES (?)")->execute([$longUrl]);
$id = $pdo->lastInsertId();
// ID转短码
$code = idToShortCode($id);
$pdo->prepare("UPDATE short_urls SET short_code = ? WHERE id = ?")->execute([$code, $id]);
echo "http://a.cn/{$code}";
访问重定向入口
// index.php (配合 .htaccess 将所有短链请求转发到这里)
<?php
$requestUri = $_SERVER['REQUEST_URI'];
$shortCode = ltrim($requestUri, '/'); // 取出短码
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->prepare("SELECT long_url FROM short_urls WHERE short_code = ?");
$stmt->execute([$shortCode]);
$longUrl = $stmt->fetchColumn();
if ($longUrl) {
// 302 临时重定向(方便后期修改长链接);301 永久重定向有SEO优势
header("Location: " . $longUrl, true, 302);
exit;
} else {
http_response_code(404);
echo "链接不存在";
}
性能优化要点(进阶)
使用 Redis 缓存热点短码
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$longUrl = $redis->get("short:{$shortCode}");
if (!$longUrl) {
// 查数据库
$longUrl = queryDB($shortCode);
// 写入缓存,设置过期时间
$redis->setex("short:{$shortCode}", 86400, $longUrl);
}
header("Location: " . $longUrl);
使用异步/队列写入数据
高并发场景下,可以先写Redis再异步同步到MySQL。
防恶意刷接口
限制同一IP每天生成次数,或使用验证码。
生产环境注意事项
| 事项 | 说明 |
|---|---|
| 短码长度 | 建议 6~8 位,越短越利于复制,但碰撞率越高 |
| 重定向状态码 | 302 便于后期修改;如果确定永久不改用 301 |
| 自定义短码 | 增加允许用户自定义(需检查唯一) |
| 过期时间 | 非永久短链需加 expire_at 字段 |
| 安全过滤 | 防止 javascript: 等危险协议,需校验 http/https |
完整项目结构建议
/your-project/
├── index.php # 重定向入口
├── generate.php # 短链生成接口
├── .htaccess # 伪静态规则
├── config.php # 数据库配置
└── lib/
└── shortener.php # 核心类(生成+解析)
就是PHP生成短链接的完整思路,核心是ID→62进制编码保证无冲突,配合Redis缓存 + 数据库持久化即可支撑高并发场景。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播