idn_to_ascii

(PHP 5 >= 5.3.0, PHP 7, PHP 8, PECL intl >= 1.0.2, PECL idn >= 0.1)

idn_to_ascii将域名转换为 IDNA ASCII 格式

说明

过程式风格

idn_to_ascii(
    string $domain,
    int $flags = IDNA_DEFAULT,
    int $variant = INTL_IDNA_VARIANT_UTS46,
    array &$idna_info = null
): string|false

此函数将 Unicode 域名转换为 IDNA ASCII 兼容格式。

参数

domain

要转换的域名,必须使用 UTF-8 编码。

flags

转换选项 - IDNA_* 常量的组合(除了 IDNA_ERROR_* 常量)。

variant

INTL_IDNA_VARIANT_2003(自 PHP 7.2.0 起已弃用)用于 IDNA 2003 或 INTL_IDNA_VARIANT_UTS46(仅在 ICU 4.6 及更高版本可用)用于 UTS #46。

idna_info

仅当 INTL_IDNA_VARIANT_UTS46 用于 variant 时,才能使用此参数。在这种情况下,它将被填充为一个数组,其中包含键 'result'(转换后的可能非法结果)、'isTransitionalDifferent'(一个布尔值,指示 UTS #46 的过渡机制的使用是否或将更改结果)以及 'errors'(一个 int,表示 IDNA_ERROR_* 错误常量的位集)。

返回值

以 ASCII 兼容格式编码的域名,如果失败则返回 false

变更日志

版本 说明
7.4.0 variant 的默认值现在为 INTL_IDNA_VARIANT_UTS46,而不是已弃用的 INTL_IDNA_VARIANT_2003
7.2.0 INTL_IDNA_VARIANT_2003 已被弃用;请改用 INTL_IDNA_VARIANT_UTS46

范例

范例 #1 idn_to_ascii() 范例

<?php

echo idn_to_ascii('täst.de');

?>

以上范例将输出

xn--tst-qla.de

参见

添加备注

用户贡献备注 4 则备注

11
edible dot email at gmail dot com
12 年前
此函数的备注不太清楚,而且有点误导。

首先,<=5.3,您需要使用互联网上提供的几个脚本或类之一,这些脚本或类可能需要安装 intl 和 idn PECL 扩展...并且您需要具有 !<4.0 才能安装这两个扩展。

其次,如果您有 >=5.4,您将不需要 PECL 扩展。

第三,使用 utf8_encode() 是不必要的。事实上,它可能会完全阻止 idn_to_ascii() 工作。

在我的设置中,有必要在脚本元标记中将字符集更改为 UTF-8

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

...以及在 php.ini 文件(/usr/local/lib/php.ini、whereis php.ini、find / -name php.ini)中更改 charset_default

default_charset = "UTF-8"

以上更改意味着现在可以使用该语法(不需要 utf8_encode())使用 idn_to_ascii()。以前,该函数可以转换一些 IDN,但无法转换日语和西里尔字母 IDN。此外,没有启用或添加其他语言环境,并且 Apache 的字符集文件保持不变。

还要记住,只在需要的地方应用该函数,例如

idn_to_ascii(cåsino.com) // 错误

...而...

iden_to_ascii(cåsino) // 正确

...还要注意不支持 UTF-8 编码的文本编辑器,或者 $domain = 'cåsino' 值将变为 $domain = '??????'...并且该函数将失败。

我发现 Notepad++ 可以轻松可靠地处理 UTF-8 编码,使用 UTF-8 作为编码选项(而不是不带 BOM 的 UTF-8)就可以为该函数工作。
7
mschrieck at gmail dot com
7 年前
要使用 IDNA2008 定义转换 IDN 域名,请使用以下命令。

idn_to_ascii('teßt.com',IDNA_NONTRANSITIONAL_TO_ASCII,INTL_IDNA_VARIANT_UTS46)

结果将如预期

xn--tet-6ka.com
1
alexchexes at gmail dot com
11 个月前
idn_to_ascii 和 idn_to_utf8 函数不能正确处理完整的 URL(即包含方案和路径的 URL),因此这里提供了一些辅助函数来处理所有 URL,包括包含路径但没有方案的 URL

<?php
/**
* 将 URL 转换为 Punycode
* 它不会对其他部分进行 URL 编码
* 原始代码来自 snipp.ru 网站,这里是对处理没有方案的 URL 的修改版本
*/
function punycode_encode($url)
{
$no_scheme = false;
if (!
preg_match('/^.+?:\/\//', $url) && substr($url, 0, 2) !== '//') {
$url = '//' . $url;
$no_scheme = true;
}

$parts = parse_url($url);

$out = '';
if (!empty(
$parts['scheme'])) $out .= $parts['scheme'] . ':';
if (!empty(
$parts['host'])) $out .= '//';
if (!empty(
$parts['user'])) $out .= $parts['user'];
if (!empty(
$parts['pass'])) $out .= ':' . $parts['pass'];
if (!empty(
$parts['user'])) $out .= '@';
if (!empty(
$parts['host'])) $out .= idn_to_ascii($parts['host']);
if (!empty(
$parts['port'])) $out .= ':' . $parts['port'];
if (!empty(
$parts['path'])) $out .= $parts['path'];
if (!empty(
$parts['query'])) $out .= '?' . $parts['query'];
if (!empty(
$parts['fragment'])) $out .= '#' . $parts['fragment'];

if (
$no_scheme) {
$out = substr($out, 2);
}

return
$out;
}

function
punycode_decode($url)
{
$no_scheme = false;
if (!
preg_match('/^.+?:\/\//', $url) && substr($url, 0, 2) !== '//') {
$url = '//' . $url;
$no_scheme = true;
}

$parts = parse_url($url);
$out = '';
if (!empty(
$parts['scheme'])) $out .= $parts['scheme'] . ':';
if (!empty(
$parts['host'])) $out .= '//';
if (!empty(
$parts['user'])) $out .= $parts['user'];
if (!empty(
$parts['pass'])) $out .= ':' . $parts['pass'];
if (!empty(
$parts['user'])) $out .= '@';
if (!empty(
$parts['host'])) $out .= idn_to_utf8($parts['host']);
if (!empty(
$parts['port'])) $out .= ':' . $parts['port'];
if (!empty(
$parts['path'])) $out .= $parts['path'];
if (!empty(
$parts['query'])) $out .= '?' . $parts['query'];
if (!empty(
$parts['fragment'])) $out .= '#' . $parts['fragment'];

if (
$no_scheme) {
$out = substr($out, 2);
}

return
$out;
}
0
mpf at mk dot de
8 个月前
文档中没有清楚说明返回部分的错误意味着什么。这应该替换成类似以下内容:

"如果给定的字符串无法转换,则返回失败"。
To Top