пятница, января 19, 2007

Кириллица и php_json

Поддержка UTF-8 в PHP весьма слабая, то же касается и кириллицы. Начав использовать javascript-библиотеку Prototype и AJAX я столкнулся с тем, что модуль php_json, который включен в PHP с версии 5.2.0 (для остальных доступен в виде extension), категорически отказывается воспринимать русский язык. Кириллица просто вырезается.

Дело в том, что php_json обрабатывает только ISO-8859-1, а остальные символы отбрасывает. Функция utf8_encode() тоже не подходит из-за того, что неправильно определяет код символа. Например, русская буква "а" имеет код \u0434, а utf8_encode() кодирует ее как \u00e4. В итоге - на странице кракозябры.

Положение спасает iconv(): iconv('cp1251', 'utf-8', $string). Преобразование корректное. Но, к сожалению, это исключает использование функции json_encode() "как есть" - придется написать свою функцию json_safe_encode() для кодирования данных в формат JSON:
function json_safe_encode($var)
{
return json_encode(json_fix_cyr($var));
}

function json_fix_cyr($var)
{
if (is_array($var)) {
$new = array();
foreach ($var as $k => $v) {
$new[json_fix_cyr($k)] = json_fix_cyr($v);
}
$var = $new;
} elseif (is_object($var)) {
$vars = get_object_vars($var);
foreach ($vars as $m => $v) {
$var->$m = json_fix_cyr($v);
}
} elseif (is_string($var)) {
$var = iconv('cp1251', 'utf-8', $var);
}
return $var;
}

PS.
На www.json.org масса полезных ссылок.

UPD 2008-02-06: $vars = get_object_vars($var); instead of $vars = get_class_vars(get_class($var));. Thanks to Pascal Martineau

понедельник, августа 21, 2006

Работа PHP4 и PHP5 на одном сервере

PHP-программисту порой требуется иметь на своем компьютере несколько версий PHP. Чаще всего это последние версии PHP4 и PHP5. Полностью переустанавливать PHP неудобно и долго - это замена файлов в системных каталогах, настройка веб-сервера и PHP.

Я расскажу об одном из способов иметь на Windows XP две версии PHP одновременно. В результате у вас будет рабочий компьютер с Apache 2, PHP4 и PHP5. Если у вас уже установлены веб-сервер Apache и обе версии PHP, то переходите к третьему шагу.

Первый шаг: Установка Apache 2.

Скачайте последнюю версию Apache 2.0. На данный момент это версия 2.0.59. Во время установки в качестве хоста укажите localhost, порт 80, электронный адрес webmaster@localhost, место для установки C:\usr\local\apache2.
Программы, которые были портированы с Linux я рекомендую устанавливать в X:\usr\local и придерживаться этого правила. Множество веб-приложений написаны с расчетом на то, что они будут работать под управлением веб-сервера на Linux или FreeBSD. Руководства по установке для таких веб-приложений написаны с учетом отличной от Windows струкруты каталогов. Вам будет проще их настраивать если структруа ваших каталогов будет близка к Linux.
Остальные настройки оставьте по-умолчанию. Убедитесь, что Apache будет установлен как сервис.

Второй шаг: Установка PHP.

Скачайте PHP4 (на данный момент 4.4.4) и PHP5 (5.2.0) в zip-архивах. Распакуйте файлы в C:\usr\local\php4 и C:\usr\local\php5 соответственно. Выполните необходимые действия по настройке PHP, описанные в install.txt, глава Manual Installation Steps.

Третий шаг: Включаем обе версии.

Идея заключается в том, что в конфигурационном файле Apache (httpd.conf) можно указать местоположения php.ini с помощью директивы PHPIniDir, а так же из httpd.conf можно загружать другие конфигурационные файлы. Эти два факта позволяют сделать два конфигурационных файла, которые будут отличаться значением LoadModule и PHPIniDir, а остальные директивы (те, которые одинаковы для PHP4 и PHP5) брать из других файлов.

Так как Apache не может загрузить модули PHP4 и PHP5 одновременно, мы сделаем два разных конфигурационных файла: httpd-php4.conf и httpd-php5.conf.

Переименуйте httpd.conf (находится в C:\usr\local\apache2\conf) в httpd-common.conf. Создайте пустой файл httpd-php4.conf и скопируйте в него:

## PHP 4 Apache configuration

#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
ServerRoot "C:\usr\local\apache2"

# PHP Settings
PHPIniDir "C:\usr\local\php4"
LoadModule php4_module C:\usr\local\php4\php4apache2.dll
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps

# Load default Apache settings
Include conf/httpd-common.conf


Обратите внимание, что файл C:\usr\local\php4\sapi\php4apache2.dll необходимо скопировать в C:\usr\local\php4!

Теперь создайте httpd-php5.conf:

## PHP 5 Apache configuration

#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
ServerRoot "C:\usr\local\apache2"

# PHP Settings
PHPIniDir "C:\usr\local\php5"
LoadModule php5_module C:\usr\local\php5\php5apache2.dll
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps

# Load default Apache settings
Include conf/httpd-common.conf


Закомментируйте в файле httpd-common.conf сроку с директивой ServerRoot:

...
#
# Do NOT add a slash at the end of the directory path.
#
# ServerRoot "D:/usr/local/Apache2"
...


Теперь настроим сервисы. Остановите Apache если он запущен. Сначала удалим сервис, который был добавлен во время установки веб-сервера (Пуск->Выполнить, наберите cmd, затем нажмите OK):

C:\usr\local\apache2\bin\apache.exe -k uninstall

Установка для PHP4:

С:\usr\local\apache2\bin\apache.exe -n apache2-php4 -f "C:\usr\local\apache2\conf\httpd-php4.conf" -k install

Установка для PHP5:

С:\usr\local\apache2\bin\apache.exe -n apache2-php5 -f "C:\usr\local\apache2\conf\httpd-php5.conf" -k install

Если возникли ошибки, то обратитесь к документации Apache или поищите решение в Google.

Проверим установку. Создайте файл C:\usr\local\apache2\htdocs\info.php:

<?php

phpinfo();

?>


Запустите Apache с PHP4:

net start apache2-php4

Откройте свой браузер и наберите http://localhost/info.php. Вверху сраницы вы увидете текст PHP Version 4.x.x. Теперь запустите Apache c PHP5:

net stop apache2-php4
net start apache2-php5


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

start-php4.cmd:

net stop apache2-php5
net start apache2-php4


start-php5.cmd:

net stop apache2-php4
net start apache2-php5



Заключение.

С помощью этого метода можно иметь несколько версий Apache и несколько версий PHP в различных комбинациях. Для того, чтобы PHP4 и PHP5 работали одновременно, потребуется сделать копию веб-сервера, например, в C:\usr\local\apache2_another и настройить его на другой IP или порт.