Intereting Posts
preg_match (): Неизвестный модификатор '@' Компиляция PHP с поддержкой GD и libjpeg CodeIgniter session set-cookie duplicated – как решить Ошибка «Font_Glyph_Outline» при использовании WebFonts с DOMPDF Ajax-вызов для динамического меню работает для первого элемента <select>, но не дополнительных Отправить номер, используя форму HTML в Laravel Какой метод предпочтительнее для проверки строки после импорта csv Composer – запрошенный пакет существует, но они отклоняются вашим ограничением Показывать только повторяющиеся элементы из массива Использование вызова функции в цикле foreach Регулярное выражение для строки, которая должна содержать минимум 14 символов, где минимум 2 – числа, а минимум 6 – буквы Изменяйте случайные строки в цвета, последовательно Изменить пароль в Active Directory с помощью LDAP / PHP / IIS / SSL Как удалить прозрачный цвет в изображениях? Автоматическое увеличение в phpmyadmin

Многобайтовая безопасная функция wordwrap () для UTF-8

wordwrap() PHP не работает правильно для многобайтовых строк, таких как UTF-8.

В комментариях есть несколько примеров безопасных функций mb, но с некоторыми различными тестовыми данными все они, похоже, имеют некоторые проблемы.

Функция должна принимать те же параметры, что и wordwrap() .

В частности, убедитесь, что он работает:

  • вырезать среднее слово, если $cut = true , не вырезать среднее слово иначе
  • не вставляйте лишние пробелы в словах, если $break = ' '
  • также работают для $break = "\n"
  • работа для ASCII, и все действующие UTF-8

Related of "Многобайтовая безопасная функция wordwrap () для UTF-8"

Я не нашел для меня никакого рабочего кода. Вот что я написал. Для меня это работает, подумал, что это, вероятно, не самый быстрый.

 function mb_wordwrap($str, $width = 75, $break = "\n", $cut = false) { $lines = explode($break, $str); foreach ($lines as &$line) { $line = rtrim($line); if (mb_strlen($line) <= $width) continue; $words = explode(' ', $line); $line = ''; $actual = ''; foreach ($words as $word) { if (mb_strlen($actual.$word) <= $width) $actual .= $word.' '; else { if ($actual != '') $line .= rtrim($actual).$break; $actual = $word; if ($cut) { while (mb_strlen($actual) > $width) { $line .= mb_substr($actual, 0, $width).$break; $actual = mb_substr($actual, $width); } } $actual .= ' '; } } $line .= trim($actual); } return implode($break, $lines); } 
 /** * wordwrap for utf8 encoded strings * * @param string $str * @param integer $len * @param string $what * @return string * @author Milian Wolff <mail@milianw.de> */ function utf8_wordwrap($str, $width, $break, $cut = false) { if (!$cut) { $regexp = '#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){'.$width.',}\b#U'; } else { $regexp = '#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){'.$width.'}#'; } if (function_exists('mb_strlen')) { $str_len = mb_strlen($str,'UTF-8'); } else { $str_len = preg_match_all('/[\x00-\x7F\xC0-\xFD]/', $str, $var_empty); } $while_what = ceil($str_len / $width); $i = 1; $return = ''; while ($i < $while_what) { preg_match($regexp, $str,$matches); $string = $matches[0]; $return .= $string.$break; $str = substr($str, strlen($string)); $i++; } return $return.$str; } 

Общее время: 0.0020880699 – хорошее время 🙂

Потому что никакой ответ не обрабатывал каждый случай использования, вот что-то, что делает. Код основан на Drupal's AbstractStringWrapper::wordWrap .

 <?php /** * Wraps any string to a given number of characters. * * This implementation is multi-byte aware and relies on {@link * http://www.php.net/manual/en/book.mbstring.php PHP's multibyte * string extension}. * * @see wordwrap() * @link https://api.drupal.org/api/drupal/core%21vendor%21zendframework%21zend-stdlib%21Zend%21Stdlib%21StringWrapper%21AbstractStringWrapper.php/function/AbstractStringWrapper%3A%3AwordWrap/8 * @param string $string * The input string. * @param int $width [optional] * The number of characters at which <var>$string</var> will be * wrapped. Defaults to <code>75</code>. * @param string $break [optional] * The line is broken using the optional break parameter. Defaults * to <code>"\n"</code>. * @param boolean $cut [optional] * If the <var>$cut</var> is set to <code>TRUE</code>, the string is * always wrapped at or before the specified <var>$width</var>. So if * you have a word that is larger than the given <var>$width</var>, it * is broken apart. Defaults to <code>FALSE</code>. * @return string * Returns the given <var>$string</var> wrapped at the specified * <var>$width</var>. */ function mb_wordwrap($string, $width = 75, $break = "\n", $cut = false) { $string = (string) $string; if ($string === '') { return ''; } $break = (string) $break; if ($break === '') { trigger_error('Break string cannot be empty', E_USER_ERROR); } $width = (int) $width; if ($width === 0 && $cut) { trigger_error('Cannot force cut when width is zero', E_USER_ERROR); } if (strlen($string) === mb_strlen($string)) { return wordwrap($string, $width, $break, $cut); } $stringWidth = mb_strlen($string); $breakWidth = mb_strlen($break); $result = ''; $lastStart = $lastSpace = 0; for ($current = 0; $current < $stringWidth; $current++) { $char = mb_substr($string, $current, 1); $possibleBreak = $char; if ($breakWidth !== 1) { $possibleBreak = mb_substr($string, $current, $breakWidth); } if ($possibleBreak === $break) { $result .= mb_substr($string, $lastStart, $current - $lastStart + $breakWidth); $current += $breakWidth - 1; $lastStart = $lastSpace = $current + 1; continue; } if ($char === ' ') { if ($current - $lastStart >= $width) { $result .= mb_substr($string, $lastStart, $current - $lastStart) . $break; $lastStart = $current + 1; } $lastSpace = $current; continue; } if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) { $result .= mb_substr($string, $lastStart, $current - $lastStart) . $break; $lastStart = $lastSpace = $current; continue; } if ($current - $lastStart >= $width && $lastStart < $lastSpace) { $result .= mb_substr($string, $lastStart, $lastSpace - $lastStart) . $break; $lastStart = $lastSpace = $lastSpace + 1; continue; } } if ($lastStart !== $current) { $result .= mb_substr($string, $lastStart, $current - $lastStart); } return $result; } ?> по <?php /** * Wraps any string to a given number of characters. * * This implementation is multi-byte aware and relies on {@link * http://www.php.net/manual/en/book.mbstring.php PHP's multibyte * string extension}. * * @see wordwrap() * @link https://api.drupal.org/api/drupal/core%21vendor%21zendframework%21zend-stdlib%21Zend%21Stdlib%21StringWrapper%21AbstractStringWrapper.php/function/AbstractStringWrapper%3A%3AwordWrap/8 * @param string $string * The input string. * @param int $width [optional] * The number of characters at which <var>$string</var> will be * wrapped. Defaults to <code>75</code>. * @param string $break [optional] * The line is broken using the optional break parameter. Defaults * to <code>"\n"</code>. * @param boolean $cut [optional] * If the <var>$cut</var> is set to <code>TRUE</code>, the string is * always wrapped at or before the specified <var>$width</var>. So if * you have a word that is larger than the given <var>$width</var>, it * is broken apart. Defaults to <code>FALSE</code>. * @return string * Returns the given <var>$string</var> wrapped at the specified * <var>$width</var>. */ function mb_wordwrap($string, $width = 75, $break = "\n", $cut = false) { $string = (string) $string; if ($string === '') { return ''; } $break = (string) $break; if ($break === '') { trigger_error('Break string cannot be empty', E_USER_ERROR); } $width = (int) $width; if ($width === 0 && $cut) { trigger_error('Cannot force cut when width is zero', E_USER_ERROR); } if (strlen($string) === mb_strlen($string)) { return wordwrap($string, $width, $break, $cut); } $stringWidth = mb_strlen($string); $breakWidth = mb_strlen($break); $result = ''; $lastStart = $lastSpace = 0; for ($current = 0; $current < $stringWidth; $current++) { $char = mb_substr($string, $current, 1); $possibleBreak = $char; if ($breakWidth !== 1) { $possibleBreak = mb_substr($string, $current, $breakWidth); } if ($possibleBreak === $break) { $result .= mb_substr($string, $lastStart, $current - $lastStart + $breakWidth); $current += $breakWidth - 1; $lastStart = $lastSpace = $current + 1; continue; } if ($char === ' ') { if ($current - $lastStart >= $width) { $result .= mb_substr($string, $lastStart, $current - $lastStart) . $break; $lastStart = $current + 1; } $lastSpace = $current; continue; } if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) { $result .= mb_substr($string, $lastStart, $current - $lastStart) . $break; $lastStart = $lastSpace = $current; continue; } if ($current - $lastStart >= $width && $lastStart < $lastSpace) { $result .= mb_substr($string, $lastStart, $lastSpace - $lastStart) . $break; $lastStart = $lastSpace = $lastSpace + 1; continue; } } if ($lastStart !== $current) { $result .= mb_substr($string, $lastStart, $current - $lastStart); } return $result; } ?> 

Вот многобайтовая функция wordwrap, которую я закодировал, беря вдохновение от других, найденных в Интернете.

 function mb_wordwrap($long_str, $width = 75, $break = "\n", $cut = false) { $long_str = html_entity_decode($long_str, ENT_COMPAT, 'UTF-8'); $width -= mb_strlen($break); if ($cut) { $short_str = mb_substr($long_str, 0, $width); $short_str = trim($short_str); } else { $short_str = preg_replace('/^(.{1,'.$width.'})(?:\s.*|$)/', '$1', $long_str); if (mb_strlen($short_str) > $width) { $short_str = mb_substr($short_str, 0, $width); } } if (mb_strlen($long_str) != mb_strlen($short_str)) { $short_str .= $break; } return $short_str; } 

Не забудьте настроить PHP для использования UTF-8 с:

 ini_set('default_charset', 'UTF-8'); mb_internal_encoding('UTF-8'); mb_regex_encoding('UTF-8'); 

Я надеюсь, это поможет. Гийом

Вот моя собственная попытка выполнить функцию, которая прошла несколько моих собственных тестов, хотя я не могу обещать, что она на 100% идеальна, поэтому, пожалуйста, напишите лучше, если вы видите проблему.

 /** * Multi-byte safe version of wordwrap() * Seems to me like wordwrap() is only broken on UTF-8 strings when $cut = true * @return string */ function wrap($str, $len = 75, $break = " ", $cut = true) { $len = (int) $len; if (empty($str)) return ""; $pattern = ""; if ($cut) $pattern = '/([^'.preg_quote($break).']{'.$len.'})/u'; else return wordwrap($str, $len, $break); return preg_replace($pattern, "\${1}".$break, $str); } 

Кажется, это хорошо работает …

 function mb_wordwrap($str, $width = 75, $break = "\n", $cut = false, $charset = null) { if ($charset === null) $charset = mb_internal_encoding(); $pieces = explode($break, $str); $result = array(); foreach ($pieces as $piece) { $current = $piece; while ($cut && mb_strlen($current) > $width) { $result[] = mb_substr($current, 0, $width, $charset); $current = mb_substr($current, $width, 2048, $charset); } $result[] = $current; } return implode($break, $result); }