麻烦与php彩虹文本

时间:2014-10-02 04:38:46

标签: php text

我遇到了php彩虹文字功能。 当我运行此函数时,输出文本不支持越南语。

例如:“tôiyêuem”;

<?php   
function rainbow($text)
{

    /*** initialize the return string ***/
    $ret = '';

    /*** an array of colors ***/
    $colors = array(
        'ff00ff', 'ff0099', 'ff0033', 'ff3300',        
        'ff9900', 'ffff00', '99ff00', '33ff00', 
        '00ff33', '00ff99', '00ffff', '0099ff',        
        '0033ff', '3300ff', '9900ff'
        );
    /*** a counter ***/
    $i = 0;    
    /*** get the length of the text ***/
    $textlength = strlen($text);    
    /*** loop over the text ***/
    while($i<=$textlength)
    {
        /*** loop through the colors ***/
        foreach($colors as $value)
        {
            if ($text[$i] != "")
            {
                $ret .= '<span style="color:#'.$value.';">'.$text[$i]."</span>";
            }
        $i++;
        }
    }
    /*** return the highlighted string ***/
    $ret = html_entity_decode($ret, ENT_QUOTES, 'UTF-8');
    return $ret;
}
echo rainbow('tôi yêu em');
?>

1 个答案:

答案 0 :(得分:1)

由于您迭代字符串字节+颜色的方式,您将使用该函数以任何语言获得未初始化的字符串偏移通知。最好通过InfiniteIterator访问颜色,这只会绕着和绕过。

您对越南语的具体问题是其中一些字符由多个字节组成。像strlen()这样的函数和通过数组括号(如$text[$i]访问偏移量)不是多字节安全的 - 它们可以处理单个字节而不是字符。

虽然使用mb_strlen()代替strlen()来获取字符数而不是字节数可能很诱人,而mb_substr()而不是$text[$i]要获得一个字符而不是一个字节,你仍然会分解像这样的字素(这里的字符编码为e后跟combining grave accent。)解决方法是打破将字符串放入带有正则表达式的数组中。


实施例

function rainbow($text)
{
    $text = html_entity_decode($text, ENT_QUOTES, 'UTF-8');
    $return = '';

    $colors = new InfiniteIterator(
        new ArrayIterator(
            ['ff00ff', 'ff0099', 'ff0033', 'ff3300',
             'ff9900', 'ffff00', '99ff00', '33ff00',
             '00ff33', '00ff99', '00ffff', '0099ff',
             '0033ff', '3300ff', '9900ff']
        )
    );
    $colors->rewind();

    // Match any codepoint along with any combining marks.
    preg_match_all('/.\pM*+/su', $text, $matches);
    foreach ($matches[0] as $char)
    {
        if (preg_match('/^\pZ$/u', $char)) {
            // No need to color whitespace or invisible separators.
            $return .= $char;
        } else {
            $return .= "<span style='color:#{$colors->current()};'>$char</span>";
            $colors->next();
        }
    }

    return $return;
}

echo rainbow('tôi yêu em eve&#x300; foo baz');

输出:

<span style='color:#ff00ff;'>t</span><span style='color:#ff0099;'>ô</span><span style='color:#ff0033;'>i</span> <span style='color:#ff3300;'>y</span><span style='color:#ff9900;'>ê</span><span style='color:#ffff00;'>u</span> <span style='color:#99ff00;'>e</span><span style='color:#33ff00;'>m</span> <span style='color:#00ff33;'>e</span><span style='color:#00ff99;'>v</span><span style='color:#00ffff;'>è</span> <span style='color:#0099ff;'>f</span><span style='color:#0033ff;'>o</span><span style='color:#3300ff;'>o</span> <span style='color:#9900ff;'>b</span><span style='color:#ff00ff;'>a</span><span style='color:#ff0099;'>z</span>