Разумнее перенос слов в PHP для длинных слов? - PullRequest
14 голосов
/ 22 марта 2012

Я ищу способ сделать перенос слов в PHP немного умнее. Таким образом, он не прерывает длинные слова, оставляя одни только маленькие слова в одной строке.

Допустим, у меня есть это (реальный текст всегда полностью динамический, это просто показать):

wordwrap('hello! heeeeeeeeeeeeeeereisaverylongword', 25, '<br />', true);

Это выводит:

привет!
heeeeeeeeeeeeeeereisavery
* 1011 длинное слово *

Видите, оно оставляет маленькое слово в первой строке одним. Как я могу заставить его выводить что-то более похожее на это:

привет! heeeeeeeeeeee
eeereisaverylongword

Таким образом, он использует любое доступное пространство в каждой строке. Я пробовал несколько пользовательских функций, но ни одна из них не была эффективной (или у них были некоторые недостатки).

Ответы [ 5 ]

15 голосов
/ 22 марта 2012

Я попробовал пользовательскую функцию для этого умного переноса слов:

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";

РЕДАКТИРОВАТЬ : заметил несколько предостережений.Одним из основных предостережений с этим (а также с встроенной функцией) является отсутствие многобайтовой поддержки.

13 голосов
/ 22 марта 2012

Как насчет

$string = "hello! heeeeeeeeeeeeeeereisaverylongword";
$break = 25;

echo implode(PHP_EOL, str_split($string, $break));

Какие выходные данные

hello! heeeeeeeeeeeeeeere                                                                                                                                                           
isaverylongword

str_split () преобразует строку в массив кусков $ break size.

implode () joinмассив обратно вместе как строка, использующая клей, который в данном случае является маркером конца строки (PHP_EOL), хотя это может быть просто '<br/>'

10 голосов
/ 13 августа 2014

Это также решение (для браузеров и т. Д.):

$string = 'hello! heeeeeeeeeeeeeeeeeeeeeereisaverylongword';
echo preg_replace('/([^\s]{20})(?=[^\s])/', '$1'.'<wbr>', $string);

Он помещает <wbr> в слова с 20 или более символами

<wbr> означает «возможность разрыва слова», поэтому только разрывается, если необходимо (продиктовано шириной элемента / браузера / зрителя / другого). В противном случае он невидим.

Подходит для гибкой / чувствительной компоновки, где нет фиксированной ширины. И не переносит лишнее, как php's wordwrap

5 голосов
/ 22 марта 2012

Вы можете использовать CSS для этого.

word-wrap: break-word;

Это сломает слово для вас. Вот ссылка, чтобы увидеть его в действии:

http://www.css3.info/preview/word-wrap/

2 голосов
/ 22 марта 2012

Это должно сработать ...

$word = "hello!" . wordwrap('heeeeeeeeeeeeeeereisaverylongword', 25, '<br />', true);
echo $word;
...