Как настроить кодировки для работы с PHP фреймворком CodeIgniter

Владимир | | CodeIgniter, PHP.

Поддержка кодировок в CodeIgniter
Недавно я столкнулся с проблемой.

Создал базу данных и в ней таблицу. Во время создания явно задал кодировку (utf-8).

После этого, установил и настроил CodeIgniter. Все представления (views) тоже были в кодировке utf-8, и, естественно, был добавлен мета-тег:

<meta http-equiv="content-type" content="text/html; charset=UTF-8" />

Т.е. кириллица в браузере отображалась правильно.

Начинаю добавлять данные в БД (с помощью scaffolding). Все отлично работает, буквы отображаются правильно.

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

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

Самое непонятное заключалось в том, что тут же была база данных, созданная WordPress, с теми же самыми кодировками. И в ней все работало отлично, и на сайте, и в phpMyAdmin.

В общем, после недолгих поисков, решение нашлось. Предложил его mihailt.

Идея заключается в том, что нужно выполнить “SET NAMES UTF8” для каждого соединения.

Для это в конфигурационный файл базы данных (/system/application/config/database.php) добавляем

$db[‘default’][‘charset’] = "UTF8";

А в файле /system/database/DB.php добавляем строку

$DB->query(“SET NAMES ?”, $params[‘charset’]);

(сразу после $DB =& new $driver($params);).

Все тут же отлично заработало.

Для справки. Кодировки БД были такими:
character_set_client – utf8
character_set_connection – utf8
character_set_database – utf8
character_set_filesystem – binary
character_set_results – utf8
character_set_server – utf8
character_set_system – utf8
collation_connection – utf8_unicode_ci
collation_database – utf8_general_ci
collation_server – utf8_general_ci

Примечание. Эти данные можно получить с помощью запросов

SHOW VARIABLES LIKE 'character%'
SHOW VARIABLES LIKE 'collation%'
  • Такая модификация позволяет использовать не только UTF-8, а какую угодно кодировку просто изменив параметр в конфиге.

    На некоторых хостах не смотря, на то что всё работает пишет в лог num_rows() ошибку.
    Решить можно заменой :
    $DB->query
    на
    $DB->simple_query

  • Такая модификация позволяет использовать не только UTF-8, а какую угодно кодировку просто изменив параметр в конфиге.

    На некоторых хостах не смотря, на то что всё работает пишет в лог num_rows() ошибку.
    Решить можно заменой :
    $DB->query
    на
    $DB->simple_query

  • MAX

    В 1.6 используется немного другая схема. В конфиге появились строчки

    $db['default']['char_set'] = «utf8»;
    $db['default']['dbcollat'] = «utf8_general_ci»;

    Соотвественно при создании таблиц нужно указывать эти два параметра.

    $charset = $CI->db->char_set ? $CI->db->char_set : 'utf8';
    $collate = $CI->db->dbcollat ? $CI->db->dbcollat : 'utf8_general_ci';

    • в CI 1.6 много вещёй немного меняют в лучшую сторону, но к сожалению он ещё сыроват 😉

    • Насколько я знаю, версия 1.6 еще в разработке, и, значит, могут быть изменения.

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

  • MAX

    В 1.6 используется немного другая схема. В конфиге появились строчки

    $db['default']['char_set'] = «utf8»;
    $db['default']['dbcollat'] = «utf8_general_ci»;

    Соотвественно при создании таблиц нужно указывать эти два параметра.

    $charset = $CI->db->char_set ? $CI->db->char_set : 'utf8';
    $collate = $CI->db->dbcollat ? $CI->db->dbcollat : 'utf8_general_ci';

    • в CI 1.6 много вещёй немного меняют в лучшую сторону, но к сожалению он ещё сыроват 😉

    • Насколько я знаю, версия 1.6 еще в разработке, и, значит, могут быть изменения.

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

  • MAX

    Делов том, что в 1.6 довольно серьезные изменения. Касается это внутренней структуры, а также самого кода. Так что есть смысл уже сейчас использовать новую схему, иначе потом придется еще раз переделывать. Кроме этого SET NAMES передавать вовсе не обязательно каждый раз, если при создании таблицы была верно указана collation и charset. Таким образом ваш способ становится просто бессмысленным. К тому же если при создании таблиц кодировка не указывалась, то она создается в кодировке по-умолчанию. Для наших хостингов это как правило cp1251. Поэтому если вы выполняете set names utf8, то данные в такую базу попадают совсем не в той кодировке, в которой они предназначены, а это вызывает сразу массу проблем. Например сортировка или бэкап будут неверными.

    • В том то и дело что для ваших — для наших 3 языка давно уже стандарт соответственно делать что либо не в utf-8 очень не хорошо.

      Насчёт изменений я так полагаю, что достаточно много проектов так и останутся в предидущей версии.

    • У меня возникли проблемы именно при указанных collation и charset, т.е. в запросе создания БД было
      …DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci
      и при создании таблицы
      …ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci

      Кроме того, сервер MySQL устанавливался с utf8 по-умолчанию.

      Пока не выполнил SET NAMES нормально не заработало.

      P.S. Подробно кодировки я привел в конце поста.

  • MAX

    Делов том, что в 1.6 довольно серьезные изменения. Касается это внутренней структуры, а также самого кода. Так что есть смысл уже сейчас использовать новую схему, иначе потом придется еще раз переделывать. Кроме этого SET NAMES передавать вовсе не обязательно каждый раз, если при создании таблицы была верно указана collation и charset. Таким образом ваш способ становится просто бессмысленным. К тому же если при создании таблиц кодировка не указывалась, то она создается в кодировке по-умолчанию. Для наших хостингов это как правило cp1251. Поэтому если вы выполняете set names utf8, то данные в такую базу попадают совсем не в той кодировке, в которой они предназначены, а это вызывает сразу массу проблем. Например сортировка или бэкап будут неверными.

    • В том то и дело что для ваших — для наших 3 языка давно уже стандарт соответственно делать что либо не в utf-8 очень не хорошо.

      Насчёт изменений я так полагаю, что достаточно много проектов так и останутся в предидущей версии.

    • У меня возникли проблемы именно при указанных collation и charset, т.е. в запросе создания БД было
      …DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci
      и при создании таблицы
      …ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci

      Кроме того, сервер MySQL устанавливался с utf8 по-умолчанию.

      Пока не выполнил SET NAMES нормально не заработало.

      P.S. Подробно кодировки я привел в конце поста.

  • Конструкция set names в MySQL устанавливает кодировку, кроме прочего, и для соединения с базой. То есть вы пытаетесь сказать серверу, в какой кодировке от вас будут посылаться запросы и в какой кодировке сервер должен присылать ответ. Даже если у вас база данных создана в юникоде, то это совсем не значит, что вы будете ее получать именно в юникоде, потому что кодировка, в которой вам будет приходить ответ от сервера определяется именно set names конструкцией. Очень подробно о кодировках (charsets) и сопоставлениях (collations) написано в официальном мануале по MYSQL, правда на английском….

    • Большинство проблем с кодировками как раз и возникает из-за того, что есть очень много параметров, которые ими управляют.

      Кстати, как справедливо заметил MAX, для CI начиная с версии 1.6 описанная проблема не актуальна. Главное правильно указать значения в
      $db['default']['char_set']
      и
      $db['default']['dbcollat']

  • Конструкция set names в MySQL устанавливает кодировку, кроме прочего, и для соединения с базой. То есть вы пытаетесь сказать серверу, в какой кодировке от вас будут посылаться запросы и в какой кодировке сервер должен присылать ответ. Даже если у вас база данных создана в юникоде, то это совсем не значит, что вы будете ее получать именно в юникоде, потому что кодировка, в которой вам будет приходить ответ от сервера определяется именно set names конструкцией. Очень подробно о кодировках (charsets) и сопоставлениях (collations) написано в официальном мануале по MYSQL, правда на английском….

    • Большинство проблем с кодировками как раз и возникает из-за того, что есть очень много параметров, которые ими управляют.

      Кстати, как справедливо заметил MAX, для CI начиная с версии 1.6 описанная проблема не актуальна. Главное правильно указать значения в
      $db['default']['char_set']
      и
      $db['default']['dbcollat']

  • Ну вот, вышел CI 1.7.0, но проблема осталась, не глядя на то, что $db['default']['char_set'] и $db['default']['dbcollat'] прописаны верно.

    • Значит, проблема в чем-то еще. Посмотрите кодировки базы, настройки сервера и php. Я не один раз сталкивался с этой проблемой и она всегда решалась изменением настроек… Правда на поиски иногда уходило по несколько дней 🙁

  • Ну вот, вышел CI 1.7.0, но проблема осталась, не глядя на то, что $db['default']['char_set'] и $db['default']['dbcollat'] прописаны верно.

    • Значит, проблема в чем-то еще. Посмотрите кодировки базы, настройки сервера и php. Я не один раз сталкивался с этой проблемой и она всегда решалась изменением настроек… Правда на поиски иногда уходило по несколько дней 🙁

  • Руслан

    добрый день у меня следующая проблема у меня на http://myblock.ru/ в навигации все хорошо! но при опубликовании блогов или добавлении комментариев на сайте пример » (название блога все нормально)Привет всем ! а далее текст блога :
    «» äîáðûé äåíü êàê ó âàñ äåëà ?? «»
    что и как мне сделать подскажите!

    • Посмотреть сайт у меня не получилось (Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource…).

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

  • Руслан

    добрый день у меня следующая проблема у меня на http://myblock.ru/ в навигации все хорошо! но при опубликовании блогов или добавлении комментариев на сайте пример » (название блога все нормально)Привет всем ! а далее текст блога :
    «» ?????? ???? ??? ? ??? ???? ?? «»
    что и как мне сделать подскажите!

    • Посмотреть сайт у меня не получилось (Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource…).

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

  • D@RK_DIE$EL

    спасибо за статью все понял. Я использую CI 1.7.2, скачал предыдущий пример, все сделал по плану и тоже выводило всякую дребедень, я с кодировками было все в порядке, оказалось, что текстовые файлы, в которых написан код страницы тоже должны быть в кодировке utf-8. Я использовал редактор notepad ++ (очень удобный и быстрый), открыл нужный файл, скопировал текст, поменял кодировку в меню редактора, вставил из буфера скопированный текст и сохранил файлик. Все заработало.

    В файле /system/database/DB.php я не нашел строки $DB =& new $driver($params);, возможно она в другом файле, может кто знает где именно?

    В еще возможно, если у меня так все легко получилось, то ошибка с кодировками в CI 1.7.2 исправлена.?

    • Эта статья немного устарела. Как писал МАХ, в CI 1.7.2 кодировки задаются в параметрах
      $db['default']['char_set'] = «utf8»;
      $db['default']['dbcollat'] = «utf8_general_ci»;
      И я не советую изменять системные файлы фреймворка, разве что в крайнем случае.

  • D@RK_DIE$EL

    спасибо за статью все понял. Я использую CI 1.7.2, скачал предыдущий пример, все сделал по плану и тоже выводило всякую дребедень, я с кодировками было все в порядке, оказалось, что текстовые файлы, в которых написан код страницы тоже должны быть в кодировке utf-8. Я использовал редактор notepad ++ (очень удобный и быстрый), открыл нужный файл, скопировал текст, поменял кодировку в меню редактора, вставил из буфера скопированный текст и сохранил файлик. Все заработало.

    В файле /system/database/DB.php я не нашел строки $DB =& new $driver($params);, возможно она в другом файле, может кто знает где именно?

    В еще возможно, если у меня так все легко получилось, то ошибка с кодировками в CI 1.7.2 исправлена.?

    • Эта статья немного устарела. Как писал МАХ, в CI 1.7.2 кодировки задаются в параметрах
      $db['default']['char_set'] = «utf8»;
      $db['default']['dbcollat'] = «utf8_general_ci»;
      И я не советую изменять системные файлы фреймворка, разве что в крайнем случае.

  • гена

    научите программировать!!

  • Читайте мой блог, и у вас все получится 🙂

  • Dmi51066

    По запросу #
    SHOW VARIABLES LIKE 'collation%'
    Получил ответ:
    collation_connection utf8_general_ci
    collation_database cp1251_general_ci
    collation_server cp1251_general_ci
    Позапросу #
    SHOW VARIABLES LIKE 'character%'
    Ответ:
    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 usrlocalmysql-5.1sharecharsets
    Где найти указанные файлы:
    /system/application/config/database.php
    /system/database/DB.php

  • Эти файлы находятся в дистрибутиве CodeIgniter.

    • Gnus212

      Большое спасибо за статьи! Для новичка, не владеющего английским, это находка!