PHP HTML truncate and UTF-8


PHP HTML truncate and UTF-8

我需要截断字符串到指定的长度,忽略HTML标记。我在这里找到了合适的函数

所以我对它做了轻微的改变,添加了缓冲输入ob_start();

问题在于UTF-8。如果截断字符串的最后一个符号是from区间[ą、čę、ėį,š,ų,ū,ž],然后我得到替换字符U + FFFD�

这是我的代码。你可以复制粘贴,然后自己试试:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>String truncate</title>
</head>
<?php   
    $html = '<b>Koks nors tekstas</b>. <p>Lietuviškas žodis.</p>';
    $html = html_truncate(27, $html);
    echo $html;
    /* Truncate HTML, close opened tags
    *
    * @param int, maxlength of the string
    * @param string, html       
    * @return $html
    */  
    function html_truncate($maxLength, $html){
        $printedLength = 0;
        $position = 0;
        $tags = array();
        ob_start();
        while ($printedLength < $maxLength && preg_match('{</?([a-z]+)[^>]*>|&#?[a-zA-Z0-9]+;}', $html, $match, PREG_OFFSET_CAPTURE, $position)){
            list($tag, $tagPosition) = $match[0];
            // Print text leading up to the tag.
            $str = substr($html, $position, $tagPosition - $position);
            if ($printedLength + strlen($str) > $maxLength){
                print(substr($str, 0, $maxLength - $printedLength));
                $printedLength = $maxLength;
                break;
            }
            print($str);
            $printedLength += strlen($str);
            if ($tag[0] == '&'){
                // Handle the entity.
                print($tag);
                $printedLength++;
            }
            else{
                // Handle the tag.
                $tagName = $match[1][0];
                if ($tag[1] == '/'){
                    // This is a closing tag.
                    $openingTag = array_pop($tags);
                    assert($openingTag == $tagName); // check that tags are properly nested.
                    print($tag);
                }
                else if ($tag[strlen($tag) - 2] == '/'){
                    // Self-closing tag.
                    print($tag);
                }
                else{
                    // Opening tag.
                    print($tag);
                    $tags[] = $tagName;
                }
            }
            // Continue after the tag.
            $position = $tagPosition + strlen($tag);
        }
        // Print any remaining text.
        if ($printedLength < $maxLength && $position < strlen($html))
            print(substr($html, $position, $maxLength - $printedLength));
        // Close any open tags.
        while (!empty($tags))
             printf('</%s>', array_pop($tags));

        $bufferOuput = ob_get_contents();
        ob_end_clean();         
        $html = $bufferOuput;   
        return $html;   
    }
?>
<body>
</body>
</html>

这个函数的结果看起来像这样:

kks nors tekstas.
Lietuvi�

知道为什么这个函数在使用UTF-8时会出错吗?

知道为什么这个函数在使用UTF-8时会出错吗?

一般的问题是该函数不处理UTF-8字符串,而是处理US-ASCII、Latin-1或任何其他单字节字符集的字符串。

您正在寻找使函数与UTF-8字符集兼容。UTF-8是一个多字节字符集。

为此,有必要验证该函数内部使用的每个字符串函数是否正确处理UTF-8多字节字符集:

  • preg_match需要一个带有u修饰符Docs的模式来处理UTF-8字符串。
  • substr需替换为mb_substr Docs
  • strlen需要替换为mb_strlen Docs

当你处理HTML时,使用DOMDocument来操作HTML块可能更节省。提醒一下,它更灵活,工作也更正常。

我建议简单地使用unicode安全的子字符串函数,例如mb_substr(),来截断unicode字符串。

所以基本上尝试用mb_substr()替换所有substr()的出现。

在此之前,检查mbstring PHP模块是否在您的环境中启用。

你要找的

:

mb_strlen()

和关联的函数

只需使用以下函数

echo utf8_encode($match[0])//$match[0]这是你想要打印的变量