Мы можем явно установить набор символов utf8 при инициализации PDO, просто добавьте « charset=utf8
» в строку dsn. Но как конкретно указывать сортировку, используемую в соединении MySQL при использовании PDO?
Я не хочу использовать дополнительный запрос для этого:
SET NAMES utf8 COLLATE utf8_unicode_ci;
Есть ли какой-либо способ, не прибегая к «SET NAMES»? Или, будет ли проблема, если я не укажу сортировку?
Вот два ответа.
Вы можете установить это в DSN или как MYSQL_ATTR_INIT_COMMAND (параметры подключения).
Думаю, DSN лучше.
$connect = new PDO( "mysql:host=$host;dbname=$db;charset=utf8", $user, $pass, array( PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" ) );
Если вы укажете UTF-8
вы работаете со значением по умолчанию для utf8_general_ci
по utf8_general_ci
, если ваша таблица или поле db не использует что-то другое.
Если вы хотите, чтобы весь сервер ответил на эту настройку по умолчанию, используйте директивы конфигурации:
collation_server=utf8_unicode_ci character_set_server=utf8
Поэтому вам не нужно указывать его при подключении каждый раз.
Сопоставления влияют на сортировку символов и устанавливаются в таблице и в полях в вашей базе данных. Эти параметры соблюдаются при запросе таблицы. Убедитесь, что они установлены. Используйте имена UTF-8 с настройкой сортировки в вашем db.
Ваш комментарий:
«Люди должны знать, что набор символов и сортировка – это две разные вещи».
Давайте дадим цитату из руководства MySQL для доказательства этого:
SET NAMES 'charset_name'
эквивалентен этим трех операторам:SET character_set_client = charset_name; SET character_set_results = charset_name; SET character_set_connection = charset_name;
Установка
character_set_connection
в charset_name также неявно устанавливаетcollation_connection
дляcollation_connection
по умолчанию для charset_name.
Мой ответ: он работает неявно, если ваши таблицы не меняют это явно.
Вопрос от комментария:
Как убедиться, что я не испортил вещи, поскольку мои таблицы не являются стандартными настройками utf8_general_ci?
Пример: сортировка столбцов отменяет сопоставление таблиц
CREATE TABLE t1 ( col1 CHAR(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci ) CHARACTER SET latin1 COLLATE latin1_bin;
Если оба параметра CHARACTER SET X и COLLATE Y указаны в столбце, используются набор символов X и сортировка Y. Столбец имеет набор символов utf8
и colulation utf8_unicode_ci
как указано в столбце таблицы, тогда как таблица находится в latin1 + latin1_bin.
Пример: в общей таблице используется сортировка
Если сортировка явно не указана в столбце / поле, то используется сортировка таблицы:
CREATE TABLE t1 ( col1 CHAR(10) ) CHARACTER SET latin1 COLLATE latin1_bin;
col1 имеет сортировку latin1_bin.
Если вы хотите, чтобы сортировка utf8_unicode_ci
, установите ее в свои таблицы в целом или в столбцы / поля.
Вопрос: «Как указать сортировку с PDO без SET NAMES? .. как явно указывать сортировку, используемую при подключении MySQL при использовании PDO?»
Ответ. Вы просто не можете сделать это, не используя SET NAMES или что-то подобное. Использование PDO::MYSQL_ATTR_INIT_COMMAND
в массиве $options
из PDO constuctor является единственным способом явно установить сопоставление соединений непосредственно в вашем коде соединения с использованием PDO. В противном случае вы будете полагаться на нечто меньшее, чем явный синтаксис (который не является ответом на вопрос). Конечно, любой другой метод менее прямой.
Некоторые версии MySQL (5.1) имеют две, 3-байтные Unicode, uft8-сортировки (unicode и general). Просто использование utf8 в строке $ dsn не будет явно выбирать версию «unicode» или «общую» версию коллекций utf8. PDO не является читателем разума.
Поэтому строка параметров может выглядеть примерно так:
$options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_PERSISTENT => true, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8' COLLATE 'utf8_unicode_ci'"];
или
$options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_PERSISTENT => true, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8' COLLATE 'utf8_general_ci'"];
Более поздние версии MySQL имеют 4-байтовую реализацию unicode utf8. Здесь вы должны указать utf8mb4, а не uft8.
$options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_PERSISTENT => true, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'"];