Зачем использовать многобайтовые строковые функции в PHP?

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

Ответ 1

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

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

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

Ответ 2

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

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

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

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

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

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

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

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

Ответ 3

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

Прочитайте http://www.php.net/manual/en/intro.mbstring.php

Ответ 4

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

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

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

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

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

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

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

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

Резюме:

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

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

Ответ 5

multibyte = > multi + byte.

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

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

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

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

Ответ 6

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

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

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

Общая ошибка: 1366 Неверное строковое значение: "\ xC3" для столбца "имя" в строке 1 (SQL: обновлять name users набора = Рауль Гонсо, 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 использовались для иллюстрации.

Ответ 7

Если у вас большой проект, переход на функции MB может быть немного болезненным. в моей компании это заняло некоторое время, но затем мы сделали небольшой сценарий и объяснили его в небольшом блоге. https://link.medium.com/25w1LronCX

что позволяет очень легко перейти на функции mb_.