Зачем использовать многобайтовые строковые функции в PHP? - PullRequest
9 голосов
/ 17 июля 2011

В настоящий момент я не понимаю , почему действительно важно использовать функции mbstring в PHP при работе с UTF-8? Моя локаль под linux уже установлена ​​на UTF-8, так почему же функции вроде strlen, preg_replace и т. Д. Не работают должным образом по умолчанию?

Ответы [ 6 ]

13 голосов
/ 17 июля 2011

Все строковые функции PHP не обрабатывают многобайтовые строки независимо от локали вашей операционной системы.Вот почему вам нужно использовать многобайтовые строковые функции.

Из Многобайтовой строки Введение :

Когда вы манипулируете (обрезать, разбить, соединить и т. Д.).) Строки, закодированные в многобайтовой кодировке, необходимо использовать специальные функции, поскольку два или более последовательных байта могут представлять один символ в таких схемах кодирования.В противном случае, если вы примените к строке не-многобайтовую строковую функцию, она, вероятно, не сможет обнаружить начало или конец многобайтового символа и в результате получит поврежденную строку мусора, которая, скорее всего, потеряет свое первоначальное значение.

6 голосов
/ 17 июля 2011

Люди здесь не понимают UTF-8.

Вам не нужно использовать код с поддержкой UTF-8 для обработки UTF-8.По большей части.

Я даже написал верхний / нижний регистр Unicode, и преобразования NFC и NFD, используя только байт-зависимые функции.Трудно придумать что-нибудь более сложное, чем то, что требует такой деликатной и детальной обработки UTF-8.И все же он по-прежнему работает с байтовыми функциями.

Очень редко, когда вам нужен код с поддержкой UTF-8.Может быть, чтобы посчитать количество символов, или переместить точку вставки вперед на 1 символ.Но на самом деле, даже тогда ваш код не будет работать;) из-за разложенных символов.

Но если все, что вы делаете, это замены, поиск вещей или даже синтаксический анализ, вам просто нужны байт-зависимые функции.

Я объясню почему.

Это потому, что внутри любого другого символа UTF-8 нельзя найти символ UTF-8.Вот как это устроено.

Попытайтесь объяснить мне, как вы можете получить ошибки обработки текста в терминах многобайтовой системы, где внутри другого символа не может быть найдено ни одного символа?Только один пример дела!Самое простое, о чем вы только можете подумать.

4 голосов
/ 17 июля 2011

Вот мой ответ на простом английском языке.Один японский, китайский и корейский символы занимают более одного байта.Например, типичный символ, скажем, x, занимает 1 байт на английском языке, а на японском, китайском и корейском - более 100 байт.Теперь стандартные строковые функции PHP предназначены для обработки одного символа как 1 байта.Поэтому, если вы пытаетесь сравнить два японских, китайских или корейских символа, они не будут работать так, как ожидалось.Например, длина "Hello World!"на японском, китайском или корейском языке будет иметь более 12 байтов.

Читать http://www.php.net/manual/en/intro.mbstring.php

1 голос
/ 08 января 2017

PHP-строки являются просто байтовыми последовательностями.Они не имеют никакого значения сами по себе.И они также не используют какую-либо конкретную кодировку символов.

Так что, если вы читаете файл, используя file_get_contents(), вы получите бинарно-безопасное представление файла.Может ли это быть (двоичное) представление изображения или текстового файла, читаемого человеком - PHP не волнует.

Теперь, пока вам нужно просто выполнить базовую обработку строки, вам не нужнонужно знать кодировку символов вообще.Так что если вы хотите сохранить строку обратно в файл, используя file_put_contents() или хотите получить ее длину ( не количество символов ), используя strlen() Вы в порядке.

Однако, как только вы начнете выполнять более сложные манипуляции со строками, вам нужно будет знать кодировку !Нет способа сохранить его как часть строки, поэтому вы должны либо отслеживать его отдельно, либо, что делает большинство людей, использовать соглашение о наличии всех (текстовых) строк в общей кодировке символов, такой как US-ASCII или в настоящее время UTF-8 .

Так как невозможно установить кодировку символов для строки, PHP не знает, какой кодировкой строки используется .В связи с этим единственное, что нужно сделать для strlen(), - это вернуть количество байтов, поскольку это единственное, что PHP знает наверняка.

Если вы предоставите дополнительную информацию об используемой кодировке символов, вам нужно использовать другую функцию - в этом случае она называется mb_strlen().

То же относится и к preg_replace(): если вы хотите заменитьumlaut-a или соответствует трем одинаковым символам подряд, вам необходимо знать, как кодируется umlaut-a, и вообще как кодируются символы.

Так что если у вас есть гипотетическая кодировка символов, которая кодируетстрочные буквы a как a1 и прописные буквы A как a2, b как b1 и B как b2 (и т. д.), вы можете иметь(закодированная) строка a1a1a1, которая состоит из трех одинаковых символов в строке.Однако, не зная кодировку и просто взглянув на последовательность байтов, невозможно обнаружить это.

Сводка:

Нет нормального «по умолчанию», поскольку строки PHP не содержаткодировка символов.И даже если одна функция, такая как strlen(), не может вернуть длину последовательности байтов, как требуется для Content-Length HTTP-заголовка и в то же время количество символов, которое полезно для обозначения длиныстатья в блоге.

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

0 голосов
/ 04 марта 2019

Рауль Гонсалес - прекрасный пример того, почему:

Речь идет о сокращении слишком длинных имен пользователей для базы данных MySQL, скажем, у нас есть ограничение в 10 символов и Raul González.

Приведенный ниже модульный тест является примером того, как можно получить такую ​​ошибку

Общая ошибка: 1366 Неверное строковое значение: '\ xC3' для столбца 'имя' в строке 1 (SQL: обновление users установить name = Рауль Гонсо, updated_at = 2019-03-04 04: 28:46 где id = 793)

и как этого избежать

public function test_substr(): void
{
    $name = 'Raul González';
    $user = factory(User::class)->create(['name' => $name]);
    try {
        $name1      = substr($name, 0, 10);
        $user->name = $name1;
        $user->save();
    } catch (Exception $ex) {

    }
    $this->assertTrue(isset($ex));

    $name2      = mb_substr($name, 0, 10);
    $user->name = $name2;
    $user->save();

    $this->assertTrue(true);
}

PHP Laravel и PhpUnit использовались для иллюстрации.

0 голосов
/ 22 июля 2016

multibyte => multi + byte.

1) Используется для работы со строкой в ​​другом языке (значит, не на английском).

2) Строковые функции PHP по умолчанию корректно работают только с английским (или выпущенным для него) языком.

3) Если вы хотите использовать strlen () или strpos () или uppercase () илиstrreplace () для специального символа,
Предположим, нам нужно применить строковые функции к «Hello».
В китайском (你好), арабском (مرحبا), японском (こ ん に ち は), хинди (नमस्ते), гуджарати (હેલો).
Различный язык может иметь свои собственные наборы символов

, так что mbstring введен для общения с различными языками, такими как (китайский, японский и т. Д.).

...