php ucfirst ucwords 讨论

php ucfirst ucwords discussion

我只是想分享我在需要处理与语言无关的 ucfirst 版本时的经验。 问题是当你将英文文本与日文、中文或其他语言混合使用时,例如在我的情况下,有时瑞典语等与 ÅÄÖ,传统的 ucfirst 在将字符串转换为大写时存在问题。

不过前段时间我在堆栈溢出时偶然发现了以下代码片段:

function myucfirst($str) {
    $fc = mb_strtoupper(mb_substr($str, 0, 1));
    return $fc.mb_substr($str, 1);
}

它在大多数情况下工作正常,但最近我还需要使用 TCPDF 在动态 pdf 中自动生成翻译文本。

这是我突然想到为什么 TCPDF 的文本有问题的时候。我在其他任何地方都没有问题,字符编码是 utf8,但仍然变砖了。

日文汉字显示时,我只是忽略了使用上述函数将单词大写,但突然在瑞典语中,当我需要大写ÅÄÖ时,我遇到了同样的问题。

这让我意识到上面函数的问题在于它只查看第一个字符。 ÅÄÖ 占用 2 个字母空间,中文或日文汉字占用 3 个字母空间,上面的函数没有考虑导致 TCPDF 变砖。

为了提供更多上下文,当使用 TCPDF 生成 PDF 文档时,TCP 字体最终会出现错误,因为 gerneal mb_string 函数会将第一个字符转换为瑞典语单词 Övrigt 的“?”vrigt 和例如日语“?��”のととろ,对于邻のととロ(我的邻居龙猫。)这将使 � 的字体翻译无法正常工作。您需要对前两个字母 substr($str, 0,2) 进行 ÅÄÖ 转换才能正确转换字母。

我也不确定你是否看到我给出的代码示例,但由于中文或日文在他们的书写语言中都不使用大写字母,我排除了每个需要 3 个字母空格的符号,因为他们不管理大写 /小写字母。我真的不想排除它们,但通过 mb_string 解析它们会导致 TCPDF 中出现类似的错误,因此,我的示例是目前的解决方法,或者如果有人有更好的解决方案。

所以...我的方法是使用以下函数解决上述问题。

function myucfirst($str) {
    if ($str[0] !== "?"){
        for($i = 1; $i <= 3; $i++){
            $first = substr($str, 0, $i);
            $first = mb_convert_case($first, MB_CASE_UPPER, "UTF-8");
            if ($first !== '?'){                
                $rest = substr($str, $i);
                break;
            }
        }
        if ($i < 3){
            $ret_string = $first . $rest;
        } else {
            $ret_string = $str;
        }
    } else {
        $ret_string = $str;
    }   
    return $ret_string;
}

感谢以下 Steven Pennys 的帮助,这是适用于瑞典语和日语/中文特殊字符的解决方案,即使需要使用 TCPDF 库的字符串来动态创建 PDF:

function myucfirst($str) {
    $ret_string = mb_convert_case($str, MB_CASE_TITLE, 'UTF-8');
    return $ret_string;
}

然后对 ucwords 进行类似的修复

function myucwords($str){
    $str = trim($str);
    if (strpos($str, ' ') !== false){
        $str_arr = explode(' ', $str);
        foreach ($str_arr as $word){
            $ret_str .= isset($ret_str)? ' ' . myucfirst($word):myucfirst($word);
        }
    } else {
        $ret_str = myucfirst($str);
    }
    return $ret_str;
}

myucwords 使用第一个 myucfirst 来大写每个单词。

由于我作为开发人员或堆栈溢出贡献者的经验不多,您应该能够看到 3 个代码示例,如果有更好的方法来编写这些函数,我将不胜感激,但现在,对于那些已经类似问题,请欣赏!

/克里斯

你给的例子很差,因为 Övrigt 输入完全一样 作为输出。所以我修改了示例,以便它们有用。见下文:

<?php
# example 1
$s1 = mb_convert_case('åäö', MB_CASE_TITLE);
# example 2
$s2 = mb_convert_case('övrigt', MB_CASE_TITLE);
# exmaple 3
$s3 = mb_convert_case('隣のトトロ', MB_CASE_TITLE);
# print
var_dump($s1 == 'Åäö', $s2 == 'Övrigt', $s3 == '隣のトトロ');

请注意,您的 php.ini 中需要它,如果还没有的话:

extension = mbstring

https://php.net/function.mb-convert-case