php 版本的字符串截取方法如何通过判断长度来显示指定的更多'...'标记

821 阅读1分钟

在处理字符串截取的时候遇到一个有趣的问题
在使用mb_strlen()方法是第一次没有指定它的第二个参数 导致字符串截取时出错
先上原来的方法

function msubstr($str, $start, $length, $suffix = '', $charset = "utf-8")
{
    if (mb_strlen($str) <= $length)
        $suffix = false;
    if (function_exists("mb_substr"))
        $slice = mb_substr($str, $start, $length, $charset);
    elseif (function_exists('iconv_substr')) {
        $slice = iconv_substr($str, $start, $length, $charset);
        if (false === $slice) {
            $slice = '';
        }
    } else {
        $re['utf-8']  = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
        $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
        $re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
        $re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
        preg_match_all($re[$charset], $str, $match);
        if (count($match[0]) <= $length)
            $suffix = false;
        $slice = join("", array_slice($match[0], $start, $length));
    }
    return $suffix ? $slice . $suffix : $slice;
}

可以看到我在使用mb_strlen()方法时只指定了一个参数另一个没有指定.
这时候我们对陶企技术革命一触即发进行处理(多于12个字的时候进行截断并在后面附上’…’)在服务器端(windows)发现情况是这样的陶企技术革命一触即发...。在我本地(mac os 10.12)是正常的。
于是我在方法的一开始加入了这样的语句进行调试

#此方法判断字符串长度有问题,如需使用请往下看
function msubstr($str, $start, $length, $suffix = '', $charset = "utf-8")
{
    echo(mb_strlen($str) . '-' . $length . '--');
    if (mb_strlen($str) <= $length)
    .....
}

然后再到服务器端进行查看得到结果
服务器端结果:30-12--陶企技术革命一触即发...
本地结果:10-12--陶企技术革命一触即发
卧槽。。。。这是什么鬼?
难道是编码的问题?将调试语句更改为echo(mb_strlen($str) . '-' . mb_internal_encoding() . '--');
服务端结果:30-ISO-8859-1--陶企技术革命一触即发...
本地结果:10-UTF-8--陶企技术革命一触即发
于是发觉问题出在字符串编码上果断在mb_strlen($str,'utf-8');
服务器与本地结果一致10-UTF-8--陶企技术革命一触即发;
结论,如果你在使用字符串截取等对编码占位要求比较严格的方法时请务必带上你指定的字符串编码。
最后截取的方法修改为如下

function msubstr($str, $start, $length, $suffix = '', $charset = "utf-8")
{
    if (mb_strlen($str, $charset) <= $length)
        $suffix = false;
    if (function_exists("mb_substr"))
        $slice = mb_substr($str, $start, $length, $charset);
    elseif (function_exists('iconv_substr')) {
        $slice = iconv_substr($str, $start, $length, $charset);
        if (false === $slice) {
            $slice = '';
        }
    } else {
        $re['utf-8']  = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
        $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
        $re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
        $re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
        preg_match_all($re[$charset], $str, $match);
        $slice = join("", array_slice($match[0], $start, $length));
    }
    return $suffix ? $slice . $suffix : $slice;
}

end

update 20161206 经询问发现windows服务器是64位,但是使用的php版本位32位的。