PHP短地址生成算法

wen PHP项目 1

本文目录导读:

PHP短地址生成算法

  1. 基于MD5的短地址算法(最常用)
  2. 自增ID + 字母数字编码算法
  3. 基于随机数的短地址算法
  4. 完整示例:包含数据库操作的短链接系统
  5. 使用现成库:Guzzle + RandomLib
  6. 注意事项

在PHP中生成短地址(短链接)有多种算法,我来介绍几种常用的方案:

基于MD5的短地址算法(最常用)

<?php
class ShortUrlGenerator {
    /**
     * 生成短地址
     * @param string $url 原始URL
     * @param int $length 短地址长度
     * @return array 返回多个短地址
     */
    public static function generate($url, $length = 8) {
        // 创建MD5哈希
        $md5 = md5($url);
        $shortUrls = [];
        // 通常生成4个短地址供选择
        for ($i = 0; $i < 4; $i++) {
            // 从MD5中取一段,每8个字符一组
            $segment = substr($md5, $i * 8, 8);
            // 将16进制转为10进制
            $hexdec = hexdec($segment);
            // 使用62进制编码
            $shortUrl = self::base62Encode($hexdec);
            // 截取指定长度
            $shortUrls[] = substr($shortUrl, 0, $length);
        }
        return $shortUrls;
    }
    /**
     * 10进制转62进制
     */
    private static function base62Encode($num) {
        $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $result = '';
        while ($num > 0) {
            $result = $chars[$num % 62] . $result;
            $num = floor($num / 62);
        }
        return $result;
    }
}
// 使用示例
$url = 'https://www.example.com/article/123456?ref=homepage';
$shortUrls = ShortUrlGenerator::generate($url);
print_r($shortUrls);
// 输出类似:Array ( [0] => b60e7qKb [1] => 0Qf9HqF6 [2] => 3MaF7sT8 [3] => 9vN4cDmX )
?>

自增ID + 字母数字编码算法

<?php
class ShortUrlService {
    private $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    private $base = 62;
    /**
     * 将数字ID转换为短码
     * @param int $id 自增ID
     * @return string 短码
     */
    public function encode($id) {
        $shortUrl = '';
        while ($id > 0) {
            $shortUrl = $this->alphabet[$id % $this->base] . $shortUrl;
            $id = floor($id / $this->base);
        }
        // 如果结果为空,返回第一个字符
        if (empty($shortUrl)) {
            $shortUrl = $this->alphabet[0];
        }
        return $shortUrl;
    }
    /**
     * 将短码解码为数字ID
     * @param string $code 短码
     * @return int 原始ID
     */
    public function decode($code) {
        $id = 0;
        $len = strlen($code);
        for ($i = 0; $i < $len; $i++) {
            $id = $id * $this->base + strpos($this->alphabet, $code[$i]);
        }
        return $id;
    }
}
// 使用示例
$service = new ShortUrlService();
// 假设数据库中URL的自增ID
$id = 1000000;
$shortCode = $service->encode($id);
echo "短码: " . $shortCode . "\n";  // 输出类似: 4c92
// 解码验证
$decodedId = $service->decode($shortCode);
echo "解码后的ID: " . $decodedId . "\n";
?>

基于随机数的短地址算法

<?php
class RandomShortUrl {
    private $length = 8;
    /**
     * 生成随机短码
     * @param int $length
     * @return string
     */
    public function generateRandom($length = null) {
        $length = $length ?: $this->length;
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomString = '';
        // 使用密码学安全的随机数生成器
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[random_int(0, $charactersLength - 1)];
        }
        return $randomString;
    }
    /**
     * 检查短码是否已存在(需实现已使用短码的存储)
     */
    public function generateUnique() {
        do {
            $code = $this->generateRandom();
            // 这里需要检查数据库中是否已存在该短码
            // $exists = $this->checkExistsInDB($code);
            $exists = false; // 假设不存在
        } while ($exists);
        return $code;
    }
}
// 使用示例
$generator = new RandomShortUrl();
$shortCode = $generator->generateRandom(6);
echo "随机短码: " . $shortCode . "\n";
?>

完整示例:包含数据库操作的短链接系统

<?php
class ShortLinkSystem {
    private $db;
    private $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    private $base = 62;
    public function __construct($host, $user, $pass, $dbname) {
        // 数据库连接示例(使用PDO)
        $this->db = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
        $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    /**
     * 创建短链接
     */
    public function createShortLink($originalUrl) {
        // 1. 将URL插入数据库,获取自增ID
        $stmt = $this->db->prepare("INSERT INTO urls (original_url, created_at) VALUES (?, NOW())");
        $stmt->execute([$originalUrl]);
        $id = $this->db->lastInsertId();
        // 2. 生成短码
        $shortCode = $this->encode($id);
        // 3. 更新记录的短码
        $stmt = $this->db->prepare("UPDATE urls SET short_code = ? WHERE id = ?");
        $stmt->execute([$shortCode, $id]);
        return $shortCode;
    }
    /**
     * 解析短链接
     */
    public function getOriginalUrl($shortCode) {
        $stmt = $this->db->prepare("SELECT original_url FROM urls WHERE short_code = ?");
        $stmt->execute([$shortCode]);
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($result) {
            // 更新访问次数
            $this->updateClickCount($shortCode);
            return $result['original_url'];
        }
        return null;
    }
    /**
     * 更新点击次数
     */
    private function updateClickCount($shortCode) {
        $stmt = $this->db->prepare("UPDATE urls SET clicks = clicks + 1 WHERE short_code = ?");
        $stmt->execute([$shortCode]);
    }
    /**
     * ID转短码
     */
    private function encode($id) {
        $shortCode = '';
        while ($id > 0) {
            $shortCode = $this->alphabet[$id % $this->base] . $shortCode;
            $id = floor($id / $this->base);
        }
        return $shortCode;
    }
    /**
     * 短码转ID
     */
    private function decode($code) {
        $id = 0;
        $len = strlen($code);
        for ($i = 0; $i < $len; $i++) {
            $id = $id * $this->base + strpos($this->alphabet, $code[$i]);
        }
        return $id;
    }
}
// 使用示例
// $system = new ShortLinkSystem('localhost', 'root', '', 'short_url');
// $shortCode = $system->createShortLink('https://www.example.com/very/long/url');
// $originalUrl = $system->getOriginalUrl($shortCode);
?>

使用现成库:Guzzle + RandomLib

<?php
// 使用 Composer 安装库
// composer require paragonie/random_compat
// 组合使用多种算法生成短码
function generateShortUrl($url, $length = 6) {
    // 方法1:MD5 + base62
    $md5 = md5($url . time() . rand(10000, 99999));
    $hexdec = hexdec(substr($md5, 0, 8));
    $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $short = '';
    while ($hexdec > 0) {
        $short = $chars[$hexdec % 62] . $short;
        $hexdec = floor($hexdec / 62);
    }
    // 截取指定长度
    return substr($short, 0, $length);
}
?>

注意事项

  1. 冲突处理:确保生成的短码在数据库中唯一,需要检查重复
  2. 安全考虑:使用 random_int() 而不是 rand() 生成随机数
  3. 性能优化:对热点短码进行缓存(Redis/Memcached)
  4. 数据库索引:短码字段应该建立唯一索引
  5. URL验证:生成前验证原始URL的格式
  6. 自定义短码:允许用户自定义短码,但需检查可用性

选择哪种算法取决于你的具体需求:

  • 自增ID算法:短码长度固定,可预测,适合内部系统
  • 随机算法:不可预测,安全性更高,适合公开服务
  • MD5算法:基于原始URL生成,可重复生成相同短码

抱歉,评论功能暂时关闭!