为了避免中间词被截断,我首先查看wordwrap(),因为它已经默认具有该功能。
所以我将采用的方法是使用wordwrap() 将字符串拆分为大约一半所需总长度的段,减去分隔符字符串的长度。
然后将wordwrap() 中的第一行、分隔符和最后一行组合起来。 (使用explode() 将wordwrap() 输出拆分为行)。
// 3 params: input $string, $total_length desired, $separator to use
function truncate($string, $total_length, $separator) {
// The wordwrap length is half the total minus the separator's length
// trim() is used to prevent surrounding space on $separator affecting the length
$len = ($total_length - strlen(trim($separator))) / 2;
// Separate the output from wordwrap() into an array of lines
$segments = explode("\n", wordwrap($string, $len));
// Return the first, separator, last
return reset($segments) . $separator . end($segments);
}
试试看:http://codepad.viper-7.com/ai6mAK
$s1 = "The quick brown fox jumped over the lazy dog";
$s2 = "Lorem ipsum dolor sit amet, nam id laudem aliquid. Option utroque interpretaris eu sea, pro ea illud alterum, sed consulatu conclusionemque ei. In alii diceret est. Alia oratio ei duo.";
$s3 = "This is some other long string that ought to get truncated and leave some stuff on the end of it.";
// Fox...
echo truncate($s1, 30, "...");
// Lorem ipsum...
echo truncate($s2, 30, "...");
// Other one
echo truncate($s3, 40, "...");
输出:
The quick...the lazy dog
Lorem ipsum...ei duo.
This is some...on the end of it.
请注意,在此输出中,最后一位 ei duo 短一点。那是因为返回的最后一行 wordwrap() 不是总长度。如果它对您很重要,可以通过检查$segments 数组中最后一个元素的strlen() 并且如果它小于某个阈值(比如$len / 2)将它之前的数组元素拆分为单词,可以解决这个问题使用 explode() 并在该数组中添加另一个单词。
这是一个改进的版本,通过从wordwrap() 回溯到倒数第二行并从中弹出单词直到结尾至少是$total_length 长度的一半,从而解决了该问题。它有点复杂,但结果更令人满意。 http://codepad.viper-7.com/mDmlL0
function truncate($string, $total_length, $separator) {
// The wordwrap length is half the total, minus the separator's length
$len = (int)($total_length - strlen($separator)) / 2;
// Separate the output from wordwrap() into an array of lines
$segments = explode("\n", wordwrap($string, $len));
// Last element's length is less than half $len, append words from the second-last element
$end = end($segments);
// Add words from the second-last line until the end is at least
// half as long as $total_length
if (strlen($end) <= $total_length / 2 && count($segments) > 2) {
$prev = explode(' ', prev($segments));
while (strlen($end) <= $total_length / 2) {
$end = array_pop($prev) . ' ' . $end;
}
}
// Return the first, separator, last
return reset($segments) . $separator . $end;
}
// Produces:
The quick...over the lazy dog
Lorem ipsum...Alia oratio ei duo.
This is some other...stuff on the end of it.