Более разумный перенос слов в PHP для длинных слов?
Я ищу способ сделать перенос слов в PHP немного умнее. Таким образом, он не прерывает длинные слова, оставляя все предыдущие маленькие слова в одной строке.
Допустим, у меня есть это (реальный текст всегда полностью динамичен, это просто для того, чтобы показать):
wordwrap('hello! heeeeeeeeeeeeeeereisaverylongword', 25, '<br />', true);
Это выводит:
Привет!
heeeeeeeeeeeeeeereisavery
длинное слово
Видите, в первой строке остается только маленькое слово. Как я могу заставить его выпустить что-то более похожее это:
Привет! хееееееееее
это очень длинное слово
eeereisaverylongword
Таким образом, он использует любое доступное пространство в каждой строке. Я пробовал несколько пользовательских функций, но ни одна из них не была эффективной (или у них были некоторые недостатки).
5 answers
Я попробовал пользовательскую функцию для этой умной упаковки слов:
function smart_wordwrap($string, $width = 75, $break = "\n") {
// split on problem words over the line length
$pattern = sprintf('/([^ ]{%d,})/', $width);
$output = '';
$words = preg_split($pattern, $string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
foreach ($words as $word) {
if (false !== strpos($word, ' ')) {
// normal behaviour, rebuild the string
$output .= $word;
} else {
// work out how many characters would be on the current line
$wrapped = explode($break, wordwrap($output, $width, $break));
$count = $width - (strlen(end($wrapped)) % $width);
// fill the current line and add a break
$output .= substr($word, 0, $count) . $break;
// wrap any remaining characters from the problem word
$output .= wordwrap(substr($word, $count), $width, $break, true);
}
}
// wrap the final output
return wordwrap($output, $width, $break);
}
$string = 'hello! too long here too long here too heeeeeeeeeeeeeereisaverylongword but these words are shorterrrrrrrrrrrrrrrrrrrr';
echo smart_wordwrap($string, 11) . "\n";
РЕДАКТИРОВАТЬ: Заметил пару предостережений. Одним из основных недостатков этого (а также встроенной функции) является отсутствие многобайтовой поддержки.
Как насчет
$string = "hello! heeeeeeeeeeeeeeereisaverylongword";
$break = 25;
echo implode(PHP_EOL, str_split($string, $break));
Который выводит
hello! heeeeeeeeeeeeeeere
isaverylongword
Str_split() преобразует строку в массив блоков размером $break.
Implode() соединяет массив обратно в виде строки, используя клей, который в данном случае является маркером конца строки (PHP_EOL), хотя с таким же успехом это может быть '<br/>
'
Это также решение (для браузеров и т.д.):
$string = 'hello! heeeeeeeeeeeeeeeeeeeeeereisaverylongword';
echo preg_replace('/([^\s]{20})(?=[^\s])/', '$1'.'<wbr>', $string);
Он помещает <wbr>
в слова с 20 или более символами
<wbr>
означает "возможность разрыва слов", поэтому он прерывается только , если это необходимо (определяется шириной элемента/браузера/средства просмотра/другого). В противном случае он невидим.
Хорошо подходит для гибкого/адаптивного макета, где нет фиксированной ширины. И не обертывает нечетно, как в php wordwrap
Для этого вы можете использовать CSS.
word-wrap: break-word;
Это нарушит слово для вас. Вот ссылка, чтобы увидеть это в действии:
Это должно сработать...
$word = "hello!" . wordwrap('heeeeeeeeeeeeeeereisaverylongword', 25, '<br />', true);
echo $word;