当前位置:首页 > PHP

php实现punycode

2026-02-14 09:57:48PHP

Punycode 简介

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

php实现punycode

使用 idn_to_asciiidn_to_utf8

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

php实现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 编码和解码。以下是一个简单的实现示例:

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实现分页

PHP实现分页的基本方法 使用原生PHP实现分页功能需要结合数据库查询和HTML展示。以下是核心实现步骤: 数据库查询与分页逻辑 // 连接数据库 $conn = new mysqli('lo…

php实现文件上传

php实现文件上传

PHP 文件上传实现方法 在 PHP 中实现文件上传需要处理 HTML 表单和服务器端脚本。以下是详细步骤: 创建 HTML 表单 使用 enctype="multipart/form-data"…

php实现树

php实现树

PHP实现树结构的方法 在PHP中实现树结构通常可以通过递归或迭代的方式完成。以下是几种常见的实现方法: 递归实现树结构 递归是处理树结构的自然方式,尤其适用于具有未知深度的树。 class…

php实现图片上传

php实现图片上传

实现图片上传的基本步骤 创建HTML表单用于文件上传,表单需设置enctype="multipart/form-data"属性,确保文件数据正确传输。 <form action="uploa…

php 实现自动收货

php 实现自动收货

PHP 实现自动收货功能 自动收货功能通常用于电商系统,在订单超过一定时间未手动确认收货时自动完成订单。以下是实现方法: 数据库设计 需要订单表包含以下关键字段: CREATE TABLE o…

php实现上传

php实现上传

PHP 文件上传实现 HTML 表单设置 创建一个包含文件上传字段的 HTML 表单,确保表单的 enctype 属性设置为 multipart/form-data,这是文件上传必需的设置。 <…