Русские буквы и символы в php скриптах и базе данных mysql

Кодировка в базе данных MySQL

Пункт четвертый


После этого некорректные символы с сайта должны исчезнуть. Однако не отовсюду. Кроме файлов сайт держится еще на базах данных, таблицы и поля которых тоже имеют свою кодировку. Кодировка таблиц и полей базы данных должна также совпадать с кодировкой всех файлов сайта и самого сервера. Если же после выставления правильной кодировки в базе данных перед вами все равно возникают непонятные символы, то проблема в кодировке подключения к базе данных. Для решения данной проблемы подключитесь к серверу баз данных с правами mysql root пользователя.

mysql -u root -p

выберите необходимую вам БД

USE имя_базы;

и выполните следующий запрос:

SET NAMES 'utf8’;

Если вы используете кодировку Windows-1251, то вместо utf-8 следует прописать cp1251. Так данную кодировку называет сервер MySQL.

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

На этом всё. Ваш сайт должен отображаться как надо.

Примечание

Часто возникают ситуации, связанные с тем, что файл .htaccess не работает. Это связано с настройками Apache для вашего сервера или же для отдельного виртуального хоста, на котором содержится Ваш сайт. За опции данного файла отвечает директива AllowOverride, которая используется в конфигурационном файле Apache – httpd.conf. Если данная директива выглядит так: AllowOverride None, то сервер будет игнорировать файлы .htaccess. Для решения этой проблемы следует заменить None на All. Это даст вам возможность переопределять все допустимые настройки с помощью файла .htaccess. После внесения изменений в файл httpd.conf необходимо либо перезапустить веб-сервер (лучше), либо выполнить команду service httpd reload (перечитать директивы без перезапуска веб-сервера), чтобы изменения вступили в силу.

Подробнее о виртуальных хостах вы можете прочитать в статье Настройка виртуальных хостов в Apache.

Исправление проблемы кодировки MySQL, если запрос SET NAMES не помог

Перед тем, как изменить кодировку MySQL, вновь выполните запрос «Set Names», но уже с указанием кодировки таблицы (мы должны её выяснить).

  1. Причина кроется в том, что для таблиц настройка в одной кодировке, а данные в них — в другой.
  2. Попробуйте начать с простого решения — того же запроса «Set Names», но в кодировке таблицы.
  3. Для этого задайте запрос для названия вашей таблицы: show create table `table`
  4. Используйте полученную кодировку в запросе «Set Names»:SET NAMES кодировка«кодировка» — это параметр, который показал результат запроса «Show Create Table» из пункта 3 (DEFAULT CHARSET=кодировка).
  5. Так вы уберёте «крякозябры» и знаки вопросов из MySQL, настроите правильную отдачу и запись русских букв в данных (главное, чтобы у самой веб-страницы была соответствующая кодировка), но проблему сортировки и поиска пока не решите. Идём дальше.

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

  1. Через mysqldump создайте дамп базы данных.
  2. Используйте эту команду, в которой вместо слова «кодировка» вставьте параметр, выясненный из кодировки таблицы:mysqldump -uUSERNAME -pPASSWORD DB_NAME —allow-keywords —create-options —complete-insert —default-character-set=кодировка —add-drop-table > dump.sql
  3. Главное не перепутать кодировку таблиц с кодировкой данных.
  4. Проверьте дамп на правильное отображение кодировки уже в формате данных таблицы, а не самой таблицы, как в пункте 3 (то есть уже не latin1, а utf8, например). Скопируйте бэкап дампа отдельно.
  5. В дампе найдите оператор «Create Database» и проверьте, правильная ли в нём кодировка.
  6. Если нет, то исправьте. Тоже самое можно (и лучше сделать) с оператором «Create Table».
  7. Используйте эту команду для заливки дампа, где «кодировка» — параметр данных таблицы (utf8, а не latin1 из нашего примера):mysql -uUSERNAME -pPASSWORD DB_NAME —default-character-set=utf8 < dump.sql
  8. На веб-странице сайта найдите функцию mysql_connect, затем mysql_select_db и ниже их размещения добавьте строчку, где «кодировка» — это параметр данных таблицы, а не самой таблицы:mysql_query(«SET NAMES кодировка»)

Fundamentals

Before digging deeper, though, let’s quickly review three terms: encoding, charsets, and code point.

3.1. Encoding

Computers can only understand binary representations like 1 and . Processing anything else requires some kind of mapping from the real-world text to its binary representation. This mapping is what we know as character encoding or simply just as encoding.

For example, the first letter in our message, “T”, in US-ASCII encodes to “01010100”.

3.2. Charsets

The mapping of characters to their binary representations can vary greatly in terms of the characters they include. The number of characters included in a mapping can vary from only a few to all the characters in practical use. The set of characters that are included in a mapping definition is formally called a charset.

For example, ASCII has a charset of 128 characters.

3.3. Code Point

A code point is an abstraction that separates a character from its actual encoding. A code point is an integer reference to a particular character.

We can represent the integer itself in plain decimal or alternate bases like hexadecimal or octal. We use alternate bases for the ease of referring large numbers.

For example, the first letter in our message, T, in Unicode has a code point “U+0054” (or 84 in decimal).

Ничего не помогает, проблема кодировки MySQL так и осталась

Объёмный wiki-раздел по кодировке MySQL составили белорусские коллеги, где вы можете получить исчерпывающее описание процесса правильного создания баз данных и таблиц. Ведь именно в этом процессе кроются все причины возникновения проблемы со знаками вопросов MySQL и «крякозябрами» вместо русских букв.

Также обратите внимание и на эти моменты при работе с базами данных

  • правильная ли задана кодировка при создании таблиц (можно использовать любую, но она должна отражать кодировку данных в таблице);
  • правильная ли кодировка у скрипта, работающего с базой данных (кодировка веб-страницы и скрипта должна быть одной);
  • правильная ли кодировка у самого сайта (у веб-страницы и заголовка «Content-Type» сайта она должна быть общая);
  • в правильной ли кодировке сохраняются данные на веб-странице через редактор (выберите в редакторе нужную кодировку, следите за этим).

Не хотите самостоятельно разбираться в настройке MySQL и оптимизировать работу ИТ-инфраструктуры предприятия?

Передайте заботы о программном обеспечении в компанию ИТ-аутсорсинга ZEL-Услуги с полноценным ИТ-аудитом и экспертной поддержкой по любым техническим вопросам и задачам.

Вариант 1 — Через names

mysql> set names 'cp1251';
Query OK,  rows affected (0.00 sec)

mysql> show variables like 'char%';
+--------------------------+----------------------------------+
| Variable_name            | Value                            |
+--------------------------+----------------------------------+
| character_set_client     | cp1251                           |
| character_set_connection | cp1251                           |
| character_set_database   | latin1                           |
| character_set_filesystem | binary                           |
| character_set_results    | cp1251                           |
| character_set_server     | latin1                           |
| character_set_system     | utf8                             |
| character_sets_dir       | /usr/local/share/mysql/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.02 sec)

Ну, тут всё ясно, три самые нужные кодировки в одном )))

Ничего не помогает, проблема кодировки MySQL так и осталась

Объёмный wiki-раздел по кодировке MySQL составили белорусские коллеги, где вы можете получить исчерпывающее описание процесса правильного создания баз данных и таблиц. Ведь именно в этом процессе кроются все причины возникновения проблемы со знаками вопросов MySQL и «крякозябрами» вместо русских букв.

Также обратите внимание и на эти моменты при работе с базами данных

  • правильная ли задана кодировка при создании таблиц (можно использовать любую, но она должна отражать кодировку данных в таблице);
  • правильная ли кодировка у скрипта, работающего с базой данных (кодировка веб-страницы и скрипта должна быть одной);
  • правильная ли кодировка у самого сайта (у веб-страницы и заголовка «Content-Type» сайта она должна быть общая);
  • в правильной ли кодировке сохраняются данные на веб-странице через редактор (выберите в редакторе нужную кодировку, следите за этим).

Не хотите самостоятельно разбираться в настройке MySQL и оптимизировать работу ИТ-инфраструктуры предприятия?

Передайте заботы о программном обеспечении в компанию ИТ-аутсорсинга ZEL-Услуги с полноценным ИТ-аудитом и экспертной поддержкой по любым техническим вопросам и задачам.

Исправляем знаки вопросов в MySQL на русские буквы

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

  1. Дождитесь выполнения соединения с сервером
  2. Введите запрос:set names кодировка«кодировка» — это параметр кодировки, в которой вы выводите данные страницы на сайте.То есть запрос для UTF-8 должен выглядеть так:set names utf8А для Windows-1251 вот так:set names cp1251
  3. Очень часто параметр «Set Names» не помогает решить проблему кодировке при сортировке по имени, хотя буквы отображаются нормально. Как это исправить, читайте далее.


Обратите внимание, что запросы «set names» по факту не влияют на кодировку, которая используется функцией mysql_real_escape_string. Поэтому рекомендуется применять установку кодировки через mysql_set_charset()вместо запроса «set names»

Но даже если вы проигнорируете эту рекомендацию, то для Uta8 и других однобайтных кодировок ничего плохого не последует.

Чтобы не задавать кодировку в каждом скрипте, допишите в my.iniinit-connect=’SET NAMES utf8′

Рабочая конфигурация my.cnf MySQL

Выбираем другой алгоритм. Для начала входим в MySQL через phpmyadmin. На домашней странице в phpmyadmin видим заголовок «Основные настройки», в подразделе «Сопоставление кодировки соединения с MySQL» выбираем UTF8_UNICODE_ci.

Далее проверим конфигурацию MySQL. В phpmyadmin выберем вкладку SQL и пошлем туда запрос вида: SHOW VARIABLES LIKE ‘char%’; в ответ имеем:

Variable_name

Value

character_set_client utf8
character_set_connection utf8

character_set_database

latin1

character_set_filesystem binary
character_set_results utf8

character_set_server

latin1

character_set_system utf8
character_sets_dir /usr/share/mysql/charsets/

Видим в приведенной конфигурации в двух местах значения latin1, которые необходимо исправить в зависимости от того, какая кодировка вам нужна. Допустим, мы будем заменять на cp1251, поэтому в конфигурационном файле my.cnf, который находится в каталоге /etc/mysql/my.cnf, ищем модуль и меняем его на:

skip-character-set-client-handshake character_set_client=cp1251 character_set_server=cp1251

Делаем рестарт MySQL (перезагрузку необходимо делать всегда после внесения каких-либо изменений):  service mysql restart

В phpmyadmin снова посылаем SQL — запрос вида:SHOW VARIABLES LIKE ‘char%’;

Получаем ответ, исходя из которого видим, что наша конфигурация MySQL поменялась:

Variable_name

Value

character_set_client utf8
character_set_connection utf8

character_set_database

cp1251

character_set_filesystem binary
character_set_results utf8

character_set_server

cp1251

character_set_system utf8
character_sets_dir /usr/share/mysql/charsets/

У нас latin1 поменялись на cp1251, соответственно сразу после приведения конфигурации MySQL к указанному виду, из базы у нас извлекается все корректно, наконец-то видим русские слова. Вот пример нашего текста, извлекаемого из БД MySQL.

Source code and resource files

One other thing to remember and verify is that your source code files, resources files, and so on, are all being saved properly with UTF-8 data encoding. Otherwise, any “special” characters in these files may not be handled correctly.

In Netbeans, for example, you can right-click on your project, choose properties and then in “Sources” you will find the data encoding option (it usually defaults to UTF-8, but it’s worth checking).

Or in Windows Notepad, use the “Save As…” option in the File menu, and select the UTF-8 encoding option at the bottom of the dialog. (Note that the “Unicode” option that Notepad provides is actually UTF-16, so that’s not what you want.)

Устанавливаем MySQL 5.1

test# pkg_add -r mysql51-server
Fetching ftp//ftp.freebsd.org/pub/FreeBSD/ports/i386/
packages-7.0-release/Latest/mysql51-server.tbz... Done.
Fetching ftp//ftp.freebsd.org/pub/FreeBSD/ports/i386/
packages-7.0-release/All/mysql-client-5.1.22.tbz... Done.
Added group "mysql".
Added user "mysql".

************************************************************************

Remember to run mysql_upgrade (with the optional --datadir=<dbdir> flag)
the first time you start the MySQL server after an upgrade from an
earlier version.

************************************************************************

test# echo mysql_enable="YES" >> /etc/rc.conf
test# cp /usr/local/share/mysql/my-large.cnf /etc/my.cnf
test# /usr/local/etc/rc.d/mysql-server start
Starting mysql.
test# sockstat | grep mysql
mysql    mysqld     1154  13 tcp4   *3306                **
mysql    mysqld     1154  14 stream /tmp/mysql.sock
test#

Пускай это не самый «правильный» способ установки MySQL-сервера, зато быстрый и рабочий.

Правильный вариант работы с MySQL

mysql> show variables like 'char%';
+--------------------------+----------------------------------+
| Variable_name            | Value                            |
+--------------------------+----------------------------------+
| character_set_client     | latin1                           |
| character_set_connection | latin1                           |
| character_set_database   | latin1                           |
| character_set_filesystem | binary                           |
| character_set_results    | latin1                           |
| character_set_server     | latin1                           |
| character_set_system     | utf8                             |
| character_sets_dir       | /usr/local/share/mysql/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.02 sec)

## Кодировки выставлены неверно, нужно их настроить
mysql> set names 'koi8r';
Query OK,  rows affected (0.00 sec)

mysql> show variables like 'char%';
+--------------------------+----------------------------------+
| Variable_name            | Value                            |
+--------------------------+----------------------------------+
| character_set_client     | koi8r                            |
| character_set_connection | koi8r                            |
| character_set_database   | latin1                           |
| character_set_filesystem | binary                           |
| character_set_results    | koi8r                            |
| character_set_server     | latin1                           |
| character_set_system     | utf8                             |
| character_sets_dir       | /usr/local/share/mysql/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.02 sec)

## Я работаю через koi8r, поэтому и выставляю её, 
## но данные в таблице буду хранить в cp1251
mysql> create table `test2` (`field` varchar(60)) charset cp1251;
Query OK,  rows affected (0.01 sec)

## Проверяем, всё ли в порядке
mysql> show create table `test2`;
+-------+--------------------------------------------+
| Table | Create Table                               |
+-------+--------------------------------------------+
| test2 | CREATE TABLE `test2` (
  `field` varchar(60) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=cp1251
+-------+--------------------------------------------+
1 row in set (0.01 sec)

## Вносим данные 
mysql> insert into `test2` values ('и раз'), ('Два'),('три'), ('И ять'), ('шесть');
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates:   Warnings: 

## Проверяем сортировки
## В обычном сравнении "И" и "и" одинаковы, поэтому 
## сравнение идёт до первого отличного символа
mysql> select * from `test2` order by `field` collate cp1251_general_ci ASC;
+-------+
| field |
+-------+
| Два   |
| и раз |
| И ять |
| три   |
| шесть |
+-------+
5 rows in set (0.01 sec)

## В бинарном сравнении "И" меньше чем "и", поскольку у неё код меньше
mysql> select * from `test2` order by `field` collate cp1251_bin ASC;
+-------+
| field |
+-------+
| Два   |
| И ять |
| и раз |
| три   |
| шесть |
+-------+
5 rows in set (0.00 sec)

Таким образом, клиент работает в KOI8-R, но данные хранятся в cp1251, MySQL знает об этом и делает перекодировку на лету.

Ну и на посошок:

mysql> set character_set_results='cp1251';
Query OK,  rows affected (0.00 sec)

mysql> select * from `test2`;
+-------+
| field |
+-------+
| Х ПЮГ |
| дБЮ   |
| РПХ   |
| х ЪРЭ |
| ЬЕЯРЭ |
+-------+
5 rows in set (0.00 sec)

Выбирать данные можно в любой кодировке, так же, как и вносить, главное — правильно сообщить об этом MySQL.

PHP UTF-8 Encoding – modifications to your code:

To be sure that your PHP code plays well in the UTF-8 data encoding sandbox, here are the things you need to do:

  • Set UTF-8 as the character set for all headers output by your PHP code

    In every PHP output header, specify UTF-8 as the encoding:

  • Specify UTF-8 as the encoding type for XML

  • Strip out unsupported characters from XML

    Since not all UTF-8 characters are accepted in an XML document, you’ll need to strip any such characters out from any XML that you generate. A useful function for doing this (which I found here) is the following:

    Here’s how you can use this function in your code:

  • Specify UTF-8 as the character set for all HTML content

    For HTML content, specify UTF-8 as the encoding:

    In HTML forms, specify UTF-8 as the encoding:

  • Specify UTF-8 as the encoding in all calls to

    e.g.:

    *Note: As of PHP 5.6.0, value is used as the default. From PHP 5.4.0, UTF-8 was the default, but prior to PHP 5.4.0, ISO-8859-1 was used as the default. It’s therefore a good idea to always explicitly specify UTF-8 to be safe, even though this argument is technically optional.

    Also note that, for UTF-8, and can be used interchangeably.

  • Set UTF-8 as the default character set for all MySQL connections

    Specify UTF-8 as the default character set to use when exchanging data with the MySQL database using :

    Note that, as of PHP 5.5.0, is deprecated, and should be used instead:

  • Always use UTF-8 compatible versions of string manipulation functions

    There are several PHP functions that will fail, or at least not behave as expected, if the character representation needs more than 1 byte (as UTF-8 does). An example is the function that will return the number of bytes rather than the number of characters.

    Two options are available for dealing with this:

    • The functions that are available by default with PHP provide multibyte compatible versions of many of these functions (e.g., , etc.). Remember, though, that the strings you provide to these functions must themselves be properly encoded.

    • There is also the extension to PHP (information on enabling and configuring it is available here). This extension provides a comprehensive set of functions that properly account for multibyte encoding.

From ASCII to UTF-8

ASCII was the first character encoding standard. ASCII defined 128 different characters that could be used on the internet: numbers (0-9), English letters (A-Z), and some special characters like ! $ + — ( ) @ < > .

ISO-8859-1 was the default character set for HTML 4. This character set supported 256 different character codes. HTML 4 also supported UTF-8.

ANSI (Windows-1252) was the original Windows character set. ANSI is identical to ISO-8859-1, except that ANSI has 32 extra characters.

The default character set for HTML5 is UTF-8, which covers almost all of the characters and symbols in the world!

Migrating database data that is already encoded in latin1 to UTF-8

If you have an existing MySQL database that is already encoded in latin1, here’s how to convert the latin1 to UTF-8:

  1. Make sure you’ve made all the modifications to the configuration settings in your file, as described above.

  2. Execute the following command:

  3. Via command line, verify that everything is properly set to UTF-8

  4. Create a dump file with latin1 encoding for the table you want to convert:

    e.g:


  5. Do a global search and replace of the charset in the dumpfile from latin1 to UTF-8:

    e.g., using Perl:

    Note to Windows users: This charset string replacement (from latin1 to UTF-8) can also be done using find-and-replace in WordPad (or some other text editor, such as vim). Be sure to save the file just as it is though (don’t save it as unicode txt file!).

  6. From this point, we will start messing with the database data, so it would probably be prudent to backup the database if you haven’t already done so. Then, restore the dump into the database:

  7. Search for any records that may not have converted properly and correct them. Since non-ASCII characters are multi-byte by design, we can find them by comparing the byte length to the character length (i.e., to identify rows that may hold double-encoded UTF-8 characters that need to be fixed).

    • See if there are any records with multi-byte characters (if this query returns zero, then there don’t appear to be any records with multi-byte characters in your table and you can proceed to Step 8).

    • Copy rows with multi-byte characters into a temporary table:

    • Convert double-encoded UTF-8 characters to proper UTF-8 characters

      This is actually a bit tricky. A double encoded string is one that was properly encoded as UTF-8. However, MySQL then did us the erroneous favor of converting it (from what it thought was latin1) to UTF-8 again, when we set the column to UTF-8 encoding. Resolving this therefore requires a two step process through which we “trick” MySQL in order to preclude it from doing us this “favor”.

      First, we set the encoding type for the column back to latin1, thereby removing the double encoding:

      e.g.:

      Note: Be sure to use the correct field type for your table. In the example above, for our table, the correct field type for ‘ArtistName’ was varchar(128), but the field in your table could be text or any other type. Be sure to specify it properly!

      The problem is that now, if we set the column encoding back to UTF-8, MySQL will run the latin1 to UTF-8 data encoding for us again and we’ll be back to where we started. To avoid this, we change the column type to blob and THEN we set it to UTF-8. This exploits the fact that MySQL will not attempt to encode a blob. We are thereby able to “fool” the MySQL charset conversion to avoid the double encoding issue.

      e.g.:

      (Again, as noted above, be sure to use the proper field type for your table.)

    • Remove rows with only single-byte characters from the temporary table:

    • Re-insert fixed rows back into the original table (before doing this, you may want to run some selects on the temptable to verify that it appears to be properly corrected, just as a sanity check).

  8. Verify the remaining data and, if necessary, repeat the process in step 7 (this could be necessary, for example, if the data was triple encoded). Further errors, if any, may be easiest to resolve manually.

Introduction

This RFC proposes that use default_charset as default character encoding.

Current PHP does not have default encoding setting. This makes adoption of PHP 5.4 difficult, since PHP 5.4’s htmlentities/htmlspecialchars is now default to UTF-8. Some applications are required to set proper encoding for htmlentities/htmlspecialchars for proper character processing. If users mixed ISO-8859-1 and UTF-8 (AND many other multibyte character encodings), it could cause security problem.

There are many encoding setting in php.ini and functions that users simply ignore and leave it alone. However, it is required to handle character encoding properly for secure programs.

Objectives of this proposal are:

  1. Setting charset in HTTP header is recommended since the first XSS advisory in 2000 Feb. by CERT and Microsoft. (Better security)
  2. There are too many encoding settings and it is better to consolidated.
  3. If we have yet another multibyte string module in the future, the new common ini settings can be used. (No more module specific INIs)

Обычный вывод в PHP

Если не отображаются русские символы при обычном выводе через echo, появляются знаки вопроса (?) вместо букв, то проблемой может быть неверно указанная кодировка файла. Стандартная программа блокнот Windows по умолчанию сохраняет файл в кодировке ANSI, в результате чего появляется такая проблема как на картинке.

Знаки вопроса вместо букв

Решить проблему можно сохранив файл в формате UTF-8, для этого в блокноте достаточно нажать Файл->Сохранить как… и в появившемся окне выбрать тип файла «Все файлы» и выбрать кодировку UTF-8. После чего нажать кнопку сохранить и подтвердить замену файла.

Сохранение файла в кодировке UTF-8

Открываем вновь в браузере и видим, что проблема решена.

Нормальное отображение символов в PHP

Этот способ показан для программы Блокнот Windows, т.к. чаще всего проблема возникает именно с ней у начинающих программистов PHP. Для программирования лучше использовать специальный текстовый редактор (Sublme Text, Notepad++ и др.) или IDE PhpStorm, они по умолчанию работают UTF-8.


С этим читают