首页 > 解决方案 > PHP字符串重音字符更改

问题描述

我使用 elFinder 作为 PHP 连接器 ( elFinder 文档) 的文件浏览器,我已经为 Sanitizer 插件 ( Sanitizer 插件) 配置了一个回调函数。

function sanitize($filename){ // Or @callable sanitize function
    $a = pathinfo($filename);
    $b = strtourl($a['filename'],false).'.'.$a['extension'];
    echo $b;

    return $b;
}

function strtourl($str, $toLower = true){
    $sr = array('À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď', 'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ', 'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ', 'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ʼn', 'Ō', 'ō', 'Ŏ', 'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ', 'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ', 'Ū', 'ū', 'Ŭ', 'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż', 'ż', 'Ž', 'ž', 'ſ', 'ƒ', 'Ơ', 'ơ', 'Ư', 'ư', 'Ǎ', 'ǎ', 'Ǐ', 'ǐ', 'Ǒ', 'ǒ', 'Ǔ', 'ǔ', 'Ǖ', 'ǖ', 'Ǘ', 'ǘ', 'Ǚ', 'ǚ', 'Ǜ', 'ǜ', 'Ǻ', 'ǻ', 'Ǽ', 'ǽ', 'Ǿ', 'ǿ');
    $rp = array('A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 's', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'IJ', 'ij', 'J', 'j', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'l', 'l', 'N', 'n', 'N', 'n', 'N', 'n', 'n', 'O', 'o', 'O', 'o', 'O', 'o', 'OE', 'oe', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'f', 'O', 'o', 'U', 'u', 'A', 'a', 'I', 'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'A', 'a', 'AE', 'ae', 'O', 'o');

    $url = $str;
    if($toLower) $url = strtolower($url);

    $url = preg_replace('/\s+/', "-", $url);
    $url = str_replace($sr, $rp, $url);
    $url = preg_replace('/[^a-zA-Z0-9_.-]+/i', "-", $url);
    $url = preg_replace('/-{2,}/', "-", $url);
    $url = preg_replace('/-+$/', "", $url);

    return $url;
}

如果我使用自定义字符串手动调用此函数,则效果很好。如果我在插件调用时将 $filename 替换为自定义字符串,则它可以完美运行。

但是当任何函数触及字符串时,从插件到达的文件名会被修改。让我解释。

插件 -> sanitize("Camión Avión.jpg")

如果我注释所有内容并回显 $filename,则输出是预期的Camión Avión.jpg,但如果我取消注释所有内容并在函数开头回显 $filename,则输出为CamioÌn AvioÌn.jpg,但在回显 $filename 之前什么都没有。

让我们继续前进,如果我删除我的自定义函数 strtourl() 并尝试下一个:

function Sanitize($filename){
    var_dump($filename);
    var_dump($filename{5});
    var_dump($filename{6});
    var_dump($filename{7});
}

结果是:

string(20) "CamioÌn AvioÌn.jpg" 
string(1) "Ì"
string(1) ""
string(1) "n"

在 ascii UTF-8 中,“Ì”是 204,“”是 129 代码。

如果我评论 las 3 行:

function Sanitize($filename){
    var_dump($filename);
    //var_dump($filename{5});
    //var_dump($filename{6});
    //var_dump($filename{7});
}

结果是:string(20) "Camión Avión.jpg"

我不知道会发生什么,有人可以帮助我吗?

谢谢你。

标签: phputf-8character-encodingelfinder

解决方案


最后正如@JosefZ 评论的那样,这是一个规范化问题。elFinder 连接器也提供了一个插件来规范文件名,然后再对其进行清理。规范器插件

这是我的最终配置:

         $opts = array(
            'bind' => array(
                'upload.pre mkdir.pre mkfile.pre rename.pre archive.pre ls.pre' => array(
                    'Plugin.Normalizer.cmdPreprocess',
                    'Plugin.Sanitizer.cmdPreprocess'
                ),
                'upload.presave paste.copyfrom' => array(
                    'Plugin.Normalizer.onUpLoadPreSave',
                    'Plugin.Sanitizer.onUpLoadPreSave'
                )
            ),
            'roots'  => array(
                array(
                    'driver' => 'LocalFileSystem',
                    'path'   => ROOT_PATH,
                    'URL'    => URI.ROOT,
                    "trashHash" => "t2_Lw",
                    'alias'  => $_ENV['WEBID'],
                    'attributes' => $attrs,
                    'plugin' => array(
                        'Normalizer' => array(
                            'enable'    => true,
                            'nfc'       => true,
                            'nfkc'      => true,
                            'umlauts'   => false,
                            'lowercase' => false,
                            'convmap'   => array()
                        ),
                        'Sanitizer' => array(
                            'enable' => true,
                            'targets'  => array('\\','/',':','','?','"','<','>','|'), // target chars
                            'replace'  => '_', // replace to this
                            'callBack' => '\App\Admin\Controllers\Sanitize'
                        )
                    )
                ),
                array(
                    'id'            => '2',
                    'driver'        => 'Trash',
                    'path'          => ROOT_PATH . '/.papelera',
                )
            ),
            'maxTargets' => string2bool($_POST['multiple']) ? null : 1,
            'debug' => DEBUG,
            'locale' => 'es_ES.UTF-8',
            'tmbBgColor' => '#FFFFFF',
            'tmbCrop' => false
        );

使用这个 elFinder 连接器选项和之前的函数(strtourl 和 sanitize 回调),它可以按预期工作。

请注意,Normalizer 插件使用需要 intl 扩展的 PHP Normalizer 类。我在 Xampp for Mac 上安装它时遇到了一些麻烦,但我发现这篇文章解决了这个问题。Mac 上 Xammp 的 Intl


推荐阅读