Корректное урезание строк по словам в PHP
13-12-2007Reading time ~ 1 min.PHP 35481
Все гениальное не просто, а очень просто! Константин придумал способ как корректно обрезать текст по словам причем без использвания строковых функций.
Проблема собственно в том, что юникодовский текст занимает больше байт, чем количество символов. Поэтому обычный substr и т.п. могут обрезать текст по служебному байту, что приводит к отображению браузером знака вопроса в конце текста. Все это не очень красиво.
До недавнего времени я вынужден был вообще пойти на крайнее извращение и перед использованием str_функций преобразовывал текст в windows-1251, выполнял нужные операции, а потом кодировал обратно в utf-8.
Константин сделал совсем просто: строка разбивается в массив (которые уже корректно работают с utf-8), массив обрезается, а потом объединяется в строку. Все элементарно. :)
Вот немного модифицированная функция для таких случаев:
function maxsite_str_word($text, $counttext = 10, $sep = ' ') { $words = split($sep, $text); if ( count($words) > $counttext ) $text = join($sep, array_slice($words, 0, $counttext)); return $text; }
То есть в ней можно указать сам текст, количество слов и разделитель (это для универсальности).
http://php.net/mb_substr
http://php.net/manual/en/ref.mbstring.php
?
Жаль, что я в этом нифига не понимаю :mrgreen:
Ну правильно, разбиваем по пробелам, потом соединяем... У мну тоже где-то подобная функция через регулярку валялась... можно еще поверить знак препинания в конце: если запятая, двоеточие и т.п. - отрезать, ибо неэстетично, но это уже так, изыски...
Тут главное не в том, чтобы разбить по пробелу, а в том, что стандартные str_ некорректно работают с юникодовскими строками. Поэтому нужно либо локаль подключать, либо mbstrings пользоваться. Но не всегда mb включены на серверах, поэтому нужно всегда проверять наличие этих функций перед использованием. При использовании же массива все очень просто, быстро и без проблем с совместимостью.
как вариант:
А можно пример в коде ???
а то на словах не совсем понятно
Dimox, чем-то мы с тобой похожи :???:
Вот такой код может неверно обрезать текст:
$TEXT = substr($TEXT, 0, $counttext );
Уже давным давно, когда я только переделывал виджеты, я переделал виджет и "последние комментарии". Мне ещё тогда в дефолтном бесило, что делиться всё по символам, а не по словам. И я переделал виджет. Но у меня почему то и со split-ом была проблема, добавлялось в конце всегда ? (символ пробела видимо не в той кодировке). Вот выдержки из обновлённого виджета latest comments который работает по такому же принципу, что и описывается:
забыл про эти символы :-)
то есть, explode вместо split тоже может сработать некорректно?
А почему бы не взять готовую функцию из Drupal? там вообще много всего хорошего уже сделано :Р
Идея со сплитом не очень быстродейственная. А ведь есть еще и разные разделительные знаки... :)
а чем же вам не нравятся регэкспы?
2CTapbIu: Вариант с preg_match, тоже хорош.
Действительно, а чем не устраивают мультибайтовые строковые функции? (как сказано в первом коменте)
http://php.net/manual/en/ref.mbstring.php
Урезание по словам - это не то, что требуется в большинсте случаев, так как фраза из N слов может быть очень разной по длине.
Но если стоит задача именно разбиения по словам, то я бы использовал explode, implode.
я бы чесно говоря если надо было бы сразу через массив делал
Спасибо за статью.
Предлогаю модификацию функции где текст урезается не только по словам , но и по символам в случае если текст длиннннннее заданного количества $maxchar .
Может быть кому нибудь пригодится :mad:
Метод хороший, только непонятно, что делать, если мне заранее не известно количество слов?
Как вариант, если используете codeigniter, то есть функция "word_limiter($text, $number_of_world)" хелпера "Text Helper"
Чтобы уже все окончательно встало на свои места,
найдено на просторах интернета:
Для корректной работы с многобайтными кодировками в PHP предусмотрен набор функций, их легко можно узнать по наличию приставки mb_
Рассмотри корректный код усечения строки в многобайтной кодировка:
Операция усечения выполняется в два этапа, сначала задается кодировка строки и только после этого выполняется усечение.
Кодировку достаточно указать только один раз, даже в случае применения нескольких функций.
Внимание
С версии PHP 5.3.0 эта функция считается УСТАРЕВШЕЙ. Крайне не рекомендуется полагаться на эту возможность.