我需要能够使用 ord() 来获得与 javascript 的 charCodeAt() 函数相同的值。问题是 ord() 不支持 UTF8。
如何让 Ą 在 PHP 中转换为 260?我已经尝试了一些 uniord 函数,但它们都报告 256 而不是 260。
非常感谢您的帮助!
问候
我需要能够使用 ord() 来获得与 javascript 的 charCodeAt() 函数相同的值。问题是 ord() 不支持 UTF8。
如何让 Ą 在 PHP 中转换为 260?我已经尝试了一些 uniord 函数,但它们都报告 256 而不是 260。
非常感谢您的帮助!
问候
mbstring 版本:
function utf8_char_code_at($str, $index)
{
$char = mb_substr($str, $index, 1, 'UTF-8');
if (mb_check_encoding($char, 'UTF-8')) {
$ret = mb_convert_encoding($char, 'UTF-32BE', 'UTF-8');
return hexdec(bin2hex($ret));
} else {
return null;
}
}
使用 htmlspecialchars 和 htmlspecialchars_decode 获取一个字符:
function utf8_char_code_at($str, $index)
{
$char = '';
$str_index = 0;
$str = utf8_scrub($str);
$len = strlen($str);
for ($i = 0; $i < $len; $i += 1) {
$char .= $str[$i];
if (utf8_check_encoding($char)) {
if ($str_index === $index) {
return utf8_ord($char);
}
$char = '';
$str_index += 1;
}
}
return null;
}
function utf8_scrub($str)
{
return htmlspecialchars_decode(htmlspecialchars($str, ENT_SUBSTITUTE, 'UTF-8'));
}
function utf8_check_encoding($str)
{
return $str === utf8_scrub($str);
}
function utf8_ord($char)
{
$lead = ord($char[0]);
if ($lead < 0x80) {
return $lead;
} else if ($lead < 0xE0) {
return (($lead & 0x1F) << 6)
| (ord($char[1]) & 0x3F);
} else if ($lead < 0xF0) {
return (($lead & 0xF) << 12)
| ((ord($char[1]) & 0x3F) << 6)
| (ord($char[2]) & 0x3F);
} else {
return (($lead & 0x7) << 18)
| ((ord($char[1]) & 0x3F) << 12)
| ((ord($char[2]) & 0x3F) << 6)
| (ord($char[3]) & 0x3F);
}
}
PHP 扩展版本:
#include "ext/standard/html.h"
#include "ext/standard/php_smart_str.h"
const zend_function_entry utf8_string_functions[] = {
PHP_FE(utf8_char_code_at, NULL)
PHP_FE_END
};
PHP_FUNCTION(utf8_char_code_at)
{
char *str;
int len;
long index;
unsigned int code_point;
long i;
int status;
size_t pos = 0, old_pos = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &str, &len, &index) == FAILURE) {
return;
}
for (i = 0; pos < len; ++i) {
old_pos = pos;
code_point = php_next_utf8_char((const unsigned char *) str, (size_t) len, &pos, &status);
if (i == index) {
if (status == SUCCESS) {
RETURN_LONG(code_point);
} else {
RETURN_NULL();
}
}
}
RETURN_NULL();
}
ord()
按字节工作(作为大多数 PHP 标准字符串函数 - 如果不是全部)。您需要自己转换它,例如在多字节字符串扩展的帮助下:
$utf8Character = 'Ą';
list(, $ord) = unpack('N', mb_convert_encoding($utf8Character, 'UCS-4BE', 'UTF-8'));
echo $ord; # 260
尝试:
function uniord($c) {
$h = ord($c{0});
if ($h <= 0x7F) {
return $h;
} else if ($h < 0xC2) {
return false;
} else if ($h <= 0xDF) {
return ($h & 0x1F) << 6 | (ord($c{1}) & 0x3F);
} else if ($h <= 0xEF) {
return ($h & 0x0F) << 12 | (ord($c{1}) & 0x3F) << 6
| (ord($c{2}) & 0x3F);
} else if ($h <= 0xF4) {
return ($h & 0x0F) << 18 | (ord($c{1}) & 0x3F) << 12
| (ord($c{2}) & 0x3F) << 6
| (ord($c{3}) & 0x3F);
} else {
return false;
}
}
echo uniord('Ą');
这应该等同于charCodeAt()
基于@hakre 工作的 JavaScript,但更正为实际上与 JavaScript 相同(以我能想到的各种方式进行测试):
function charCodeAt($string, $offset) {
$string = mb_substr($string, $offset, 1);
list(, $ret) = unpack('S', mb_convert_encoding($string, 'UTF-16LE'));
return $ret;
}
(这需要安装和激活PHP 扩展“ mbstring ”。)
这里有一个ord_utf8函数: https ://stackoverflow.com/a/42600959/7558876
这个函数看起来像这样(接受字符串并返回整数)
<?php
function ord_utf8($s){
return (int) ($s=unpack('C*',$s[0].$s[1].$s[2].$s[3]))&&$s[1]<(1<<7)?$s[1]:
($s[1]>239&&$s[2]>127&&$s[3]>127&&$s[4]>127?(7&$s[1])<<18|(63&$s[2])<<12|(63&$s[3])<<6|63&$s[4]:
($s[1]>223&&$s[2]>127&&$s[3]>127?(15&$s[1])<<12|(63&$s[2])<<6|63&$s[3]:
($s[1]>193&&$s[2]>127?(31&$s[1])<<6|63&$s[2]:0)));
}
还有一个快速的 chr_utf8: https ://stackoverflow.com/a/42510129/7558876
这个函数看起来像这样(接受整数并返回一个字符串)
<?php
function chr_utf8($n,$f='C*'){
return $n<(1<<7)?chr($n):($n<1<<11?pack($f,192|$n>>6,1<<7|191&$n):
($n<(1<<16)?pack($f,224|$n>>12,1<<7|63&$n>>6,1<<7|63&$n):
($n<(1<<20|1<<16)?pack($f,240|$n>>18,1<<7|63&$n>>12,1<<7|63&$n>>6,1<<7|63&$n):'')));
}
如果您想要一个示例,请查看链接...</p>