Php substr Utf-8 问题
Php substr Utf-8 issue
当我运行这段代码
$string='<p>Şelamiİnnşşasdüğ213,123wqeq.weqw.rqasd</p><p>Şelamiİnnşşasdüğ213,123wqeq.weqw.rqasd</p><p>Şelamiİnnşşasdüğ213,123wqeq.weqw.rqasd</p>';
echo substr(strip_tags(trim(html_entity_decode($string, ENT_COMPAT, 'UTF-8'))), 0, 14);;
我得到了这个结果。
Şelamiİnnş�
我的错误是什么?
你应该使用多字节 substr()
函数。
尝试
<?php
$string = '<p>Şelamiİnnşşasdüğ213,123wqeq.weqw.rqasd</p>p>Şelamiİnnşşasdüğ213,123wqeq.weqw.rqasd</p><p>Şelamiİnnşşasdüğ213,123wqeq.weqw.rqasd</p>';
echo mb_substr(strip_tags(trim(html_entity_decode($string, ENT_COMPAT, 'UTF-8'))), 0, 14);;
?>
首先,总是将您的问题分解成更小的部分,看看哪里出了问题:
$string=html_entity_decode($string, ENT_COMPAT, 'UTF-8');
echo $string, "\n";
$string = trim($string);
echo $string, "\n";
$string = strip_tags($string);
echo $string, "\n";
$string = substr($string, 0, 14);
echo $string, "\n";
如果你运行那个,你会发现问题与strip_tags
无关,它与substr
有关。
原因很简单:PHP中的字符串只是一系列字节; substr
之类的函数不会以任何有意义的方式计算 "characters"。所以 substr($string, 0, 14)
只取字符串的前 14 个字节,在这种情况下,它恰好拆分了一个 "character",它使用 UTF-8 编码为多个字节。
最常见的解决方案是使用 mb_substr
("mbstring" PHP 扩展的一部分),它根据某种编码计算 "characters":
$string = mb_substr($string, 0, 14, 'UTF-8');
echo $string, "\n";
// Şelamiİnnşşasd
请注意,这将 运行cate 到 14 Unicode 代码点,因此如果使用"combining diacritic".
在某些情况下,另一种选择是使用 grapheme_substr
("intl" 扩展的一部分),它在 "graphemes" 上拆分,这大致是人们会想到的作为 "character" 或 "letter"。在这种情况下,它给出相同的结果:
$string = grapheme_substr($string, 0, 14, 'UTF-8');
echo $string, "\n";
// Şelamiİnnşşasd
但在其他情况下,可能不会:
$string = 'noël';
echo mb_substr($string, 0, 3, 'UTF-8'), "\n"; // noe
echo grapheme_substr($string, 0, 3), "\n"; // noë
当我运行这段代码
$string='<p>Şelamiİnnşşasdüğ213,123wqeq.weqw.rqasd</p><p>Şelamiİnnşşasdüğ213,123wqeq.weqw.rqasd</p><p>Şelamiİnnşşasdüğ213,123wqeq.weqw.rqasd</p>';
echo substr(strip_tags(trim(html_entity_decode($string, ENT_COMPAT, 'UTF-8'))), 0, 14);;
我得到了这个结果。
Şelamiİnnş�
我的错误是什么?
你应该使用多字节 substr()
函数。
尝试
<?php
$string = '<p>Şelamiİnnşşasdüğ213,123wqeq.weqw.rqasd</p>p>Şelamiİnnşşasdüğ213,123wqeq.weqw.rqasd</p><p>Şelamiİnnşşasdüğ213,123wqeq.weqw.rqasd</p>';
echo mb_substr(strip_tags(trim(html_entity_decode($string, ENT_COMPAT, 'UTF-8'))), 0, 14);;
?>
首先,总是将您的问题分解成更小的部分,看看哪里出了问题:
$string=html_entity_decode($string, ENT_COMPAT, 'UTF-8');
echo $string, "\n";
$string = trim($string);
echo $string, "\n";
$string = strip_tags($string);
echo $string, "\n";
$string = substr($string, 0, 14);
echo $string, "\n";
如果你运行那个,你会发现问题与strip_tags
无关,它与substr
有关。
原因很简单:PHP中的字符串只是一系列字节; substr
之类的函数不会以任何有意义的方式计算 "characters"。所以 substr($string, 0, 14)
只取字符串的前 14 个字节,在这种情况下,它恰好拆分了一个 "character",它使用 UTF-8 编码为多个字节。
最常见的解决方案是使用 mb_substr
("mbstring" PHP 扩展的一部分),它根据某种编码计算 "characters":
$string = mb_substr($string, 0, 14, 'UTF-8');
echo $string, "\n";
// Şelamiİnnşşasd
请注意,这将 运行cate 到 14 Unicode 代码点,因此如果使用"combining diacritic".
在某些情况下,另一种选择是使用 grapheme_substr
("intl" 扩展的一部分),它在 "graphemes" 上拆分,这大致是人们会想到的作为 "character" 或 "letter"。在这种情况下,它给出相同的结果:
$string = grapheme_substr($string, 0, 14, 'UTF-8');
echo $string, "\n";
// Şelamiİnnşşasd
但在其他情况下,可能不会:
$string = 'noël';
echo mb_substr($string, 0, 3, 'UTF-8'), "\n"; // noe
echo grapheme_substr($string, 0, 3), "\n"; // noë