PHP 日本研討會 2024

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',這是一個代表錯誤常數 IDNA_ERROR_* 位元集合的 int

回傳值

以 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

另請參閱

  • idn_to_utf8() - 將網域名稱從 IDNA ASCII 轉換為 Unicode

新增註解

使用者貢獻的註解 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() 運作。

在我的設定中,必須將腳本 meta 標籤中的字元集變更為 UTF-8

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

...並在 php.ini 檔案中變更 charset_default (/usr/local/lib/php.ini, whereis php.ini, find / -name php.ini)

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 作為編碼選項,而不是不含 BOM 的 UTF-8,可以輕鬆且可靠地處理適用於此函式的 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
1 年前
idn_to_ascii 和 idn_to_utf8 函式無法正確處理完整的 URL(即帶有架構和路徑的 URL),因此這裡提供處理所有 URL 的輔助函式,包括帶有路徑但不帶有架構的 URL。

<?php
/**
* 將 URL 轉換為 Punycode
* 不會對其他部分進行 URL 編碼
* 原始程式碼來自 snipp dor ru 網站,這裡是修改後的版本,可以處理不帶 scheme 的 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
1 年前
文件中沒有明確說明返回章節中的「失敗」指的是什麼。應該將其替換為類似以下的描述:

「如果給定的字串無法轉換,則返回失敗。」
To Top