Bằng cách sử dụng chức năng wordwrap . Nó phân chia các văn bản thành nhiều dòng sao cho chiều rộng tối đa là chiều rộng bạn đã chỉ định, phá vỡ các ranh giới từ. Sau khi chia tách, bạn chỉ cần lấy dòng đầu tiên:
substr($string, 0, strpos(wordwrap($string, $your_desired_width), "\n"));
Một điều mà oneliner này không xử lý là trường hợp khi bản thân văn bản ngắn hơn chiều rộng mong muốn. Để xử lý trường hợp cạnh này, người ta nên làm một cái gì đó như:
if (strlen($string) > $your_desired_width)
{
$string = wordwrap($string, $your_desired_width);
$string = substr($string, 0, strpos($string, "\n"));
}
Giải pháp trên có vấn đề cắt văn bản sớm nếu nó chứa một dòng mới trước điểm cắt thực tế. Đây là một phiên bản giải quyết vấn đề này:
function tokenTruncate($string, $your_desired_width) {
$parts = preg_split('/([\s\n\r]+)/', $string, null, PREG_SPLIT_DELIM_CAPTURE);
$parts_count = count($parts);
$length = 0;
$last_part = 0;
for (; $last_part < $parts_count; ++$last_part) {
$length += strlen($parts[$last_part]);
if ($length > $your_desired_width) { break; }
}
return implode(array_slice($parts, 0, $last_part));
}
Ngoài ra, đây là lớp kiểm tra PHPUnit được sử dụng để kiểm tra việc thực hiện:
class TokenTruncateTest extends PHPUnit_Framework_TestCase {
public function testBasic() {
$this->assertEquals("1 3 5 7 9 ",
tokenTruncate("1 3 5 7 9 11 14", 10));
}
public function testEmptyString() {
$this->assertEquals("",
tokenTruncate("", 10));
}
public function testShortString() {
$this->assertEquals("1 3",
tokenTruncate("1 3", 10));
}
public function testStringTooLong() {
$this->assertEquals("",
tokenTruncate("toooooooooooolooooong", 10));
}
public function testContainingNewline() {
$this->assertEquals("1 3\n5 7 9 ",
tokenTruncate("1 3\n5 7 9 11 14", 10));
}
}
BIÊN TẬP :
Các ký tự UTF8 đặc biệt như 'à' không được xử lý. Thêm 'u' vào cuối REGEX để xử lý nó:
$parts = preg_split('/([\s\n\r]+)/u', $string, null, PREG_SPLIT_DELIM_CAPTURE);