当前位置:首页 > PHP

php实现punycode

2026-02-14 09:57:48PHP

Punycode 简介

Punycode 是一种将 Unicode 字符串转换为 ASCII 字符串的编码方式,常用于国际化域名(IDN)的转换。PHP 提供了内置函数实现 Punycode 编码和解码。

使用 idn_to_asciiidn_to_utf8

PHP 内置了 idn_to_asciiidn_to_utf8 函数,可以直接用于 Punycode 转换。

编码(Unicode 转 Punycode)

$unicodeDomain = '例子.测试';
$punycodeDomain = idn_to_ascii($unicodeDomain, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
echo $punycodeDomain; // 输出: xn--fsq.xn--0zwm56d

解码(Punycode 转 Unicode)

$punycodeDomain = 'xn--fsq.xn--0zwm56d';
$unicodeDomain = idn_to_utf8($punycodeDomain, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
echo $unicodeDomain; // 输出: 例子.测试

检查扩展是否启用

确保 PHP 安装了 intl 扩展:

if (!extension_loaded('intl')) {
    echo 'intl 扩展未启用,请安装或启用。';
}

手动实现 Punycode

如果无法使用 intl 扩展,可以手动实现 Punycode 编码和解码。以下是一个简单的实现示例:

php实现punycode

Punycode 编码函数

function punycode_encode($input) {
    $output = '';
    $chars = preg_split('//u', $input, -1, PREG_SPLIT_NO_EMPTY);
    $n = 128;
    $delta = 0;
    $bias = 72;
    $basic = '';

    foreach ($chars as $char) {
        if (ord($char) < 128) {
            $basic .= $char;
        }
    }

    if ($basic !== '') {
        $output = $basic . '-';
    }

    $h = $b = strlen($basic);
    while ($h < strlen($input)) {
        $m = 0x7FFFFFFF;
        foreach ($chars as $char) {
            $c = ord($char);
            if ($c >= $n && $c < $m) {
                $m = $c;
            }
        }

        $delta += ($m - $n) * ($h + 1);
        $n = $m;

        foreach ($chars as $char) {
            $c = ord($char);
            if ($c < $n) {
                $delta++;
            } elseif ($c === $n) {
                $q = $delta;
                for ($k = 36;; $k += 36) {
                    $t = ($k <= $bias) ? 1 : ($k >= $bias + 26) ? 26 : $k - $bias;
                    if ($q < $t) break;
                    $output .= chr($t + ($q - $t) % (36 - $t) + 97);
                    $q = floor(($q - $t) / (36 - $t));
                }

                $output .= chr($q + 97);
                $bias = adapt($delta, $h + 1, $h === $b);
                $delta = 0;
                $h++;
            }
        }

        $delta++;
        $n++;
    }

    return $output;
}

function adapt($delta, $numpoints, $firsttime) {
    $delta = $firsttime ? floor($delta / 700) : floor($delta / 2);
    $delta += floor($delta / $numpoints);
    $k = 0;
    while ($delta > 455) {
        $delta = floor($delta / 35);
        $k += 36;
    }
    return $k + floor(36 * $delta / ($delta + 38));
}

Punycode 解码函数

function punycode_decode($input) {
    $output = '';
    $n = 128;
    $i = 0;
    $bias = 72;
    $basic = preg_replace('/-[^-]*$/', '', $input);
    $basic = preg_replace('/-$/', '', $basic);

    if ($basic !== '') {
        $output = $basic;
        $i = strlen($basic);
    }

    $pos = strrpos($input, '-');
    if ($pos !== false) {
        $input = substr($input, $pos + 1);
    }

    while (!empty($input)) {
        $oldi = $i;
        $w = 1;
        for ($k = 36;; $k += 36) {
            $digit = ord($input[0]) - 97;
            $input = substr($input, 1);
            $i += $digit * $w;
            $t = ($k <= $bias) ? 1 : ($k >= $bias + 26) ? 26 : $k - $bias;
            if ($digit < $t) break;
            $w *= (36 - $t);
        }

        $bias = adapt($i - $oldi, strlen($output) + 1, $oldi === 0);
        $n += floor($i / (strlen($output) + 1));
        $i %= (strlen($output) + 1);
        $output = substr($output, 0, $i) . chr($n) . substr($output, $i);
        $i++;
    }

    return $output;
}

注意事项

  • intl 扩展是官方推荐的方式,支持最新的 IDNA 标准(如 UTS #46)。
  • 手动实现的 Punycode 函数可能不完全符合标准,仅适用于简单场景。
  • 对于生产环境,建议优先使用 idn_to_asciiidn_to_utf8

标签: phppunycode
分享给朋友:

相关文章

php实现栈

php实现栈

栈的基本概念 栈(Stack)是一种遵循后进先出(LIFO)原则的数据结构。核心操作包括: push:元素入栈。 pop:元素出栈(返回并移除栈顶元素)。 peek:查看栈顶元素(不移除…

php 队列的实现

php 队列的实现

PHP 队列的实现方法 使用数据库实现队列 创建一个数据表存储队列任务,包含任务ID、状态、创建时间等字段。通过SQL语句实现任务的入队和出队操作。 // 入队操作 INSERT INTO queu…

php搜索功能的实现

php搜索功能的实现

实现PHP搜索功能的方法 数据库搜索 使用SQL的LIKE语句进行模糊匹配,适用于简单的搜索需求。 $searchTerm = $_GET['search']; $query = "SELECT *…

php实现区块链

php实现区块链

PHP 实现区块链的基本步骤 PHP 可以用于实现一个简单的区块链系统,以下是关键步骤和代码示例: 区块类实现 创建一个 Block 类来表示区块链中的单个区块: class Block {…

php实现图片上传预览

php实现图片上传预览

图片上传预览的实现方法 在PHP中实现图片上传预览功能,通常需要结合前端JavaScript和后端PHP代码。以下是具体的实现步骤: 前端HTML和JavaScript部分 创建包含文件输入和预览…

php树形菜单的实现

php树形菜单的实现

PHP树形菜单的实现方法 实现树形菜单通常涉及数据库设计、数据查询和前端展示三个部分。以下是几种常见的实现方式: 邻接列表模型(Adjacency List) 这是最简单的树形结构存储方式,每个节点…