Переход на PHP5+MySQL5
Переход с РНР 4 на РНР 5
По сравнению с предыдущей версией PHP 5 содержит большое количество нововведений и доработок. Перечислим основные из них:
- Изменение в модели объектно-ориентированного программирования в Zend Engine 2, что дает ощутимый прирост в скорости выполнения большинства скриптов;
- Объектно-ориентированный интерфейс в дополнение к стандартному в новом расширении MySQLi;
- Обновленная поддержка XML в библиотеке libxml версии 2;
- Работа с XML как с PHP-объектами в новом расширении SimpleXML;
- Улучшенные механизмы использования потоков.
Многие CMS поддерживают как PHP 4, так и PHP 5, причём в последних версиях некоторых программных продуктов (например, Drupal 7) присутствует только поддержка PHP 5.
Описание некоторых проблем, возникающих при переходе с PHP 4 на PHP 5:
Режим совместимости
В PHP 4 при передаче объектов в функцию эти объекты копируются; в PHP 5 передается оригинальный объект. В ряде случаев это может привести к ошибкам. Решением может служить передача в функцию клона объекта (clone($obj)) вместо самого объекта.
Более радикальным и надежным представляется изменение настроек PHP 5, а именно — включение режима совместимости (compatibility mode). Для этого следует включить директиву zend.ze1_compatibility_mode в конфигурационном файле php.ini или .htaccess, либо при помощи функции ini_set():
php_flag zend.ze1_compatibility_mode on
или
<?php
ini_set('zend.ze1_compatibility_mode', true);
?>
Помимо смены способа передачи объектов в функции, режим совместимости влияет также на кастинг объектов и их сравнение — при его использовании указанные операции производятся по стандарту PHP 4.
Кастинг объектов
В PHP 4 результат приведения объектов к логическому, целочисленному или типу чисел с плавающей запятой зависел от наличия у объекта переменных. Если объект обладал хотя бы одной переменной, результатом приведения была единица; в противном случае — ноль. В PHP 5 результат приведения всегда равен единице.
<?php
print (int) new stdClass; // 1
?>
В PHP5 объект без свойств больше не считается «пустым»:
<?php
class test { }
$t = new test();
var_dump(empty($t)); // echo bool(false)
if ($t) {
// Будет выполнено
}
?>
Сравнение объектов
В PHP 4 оператор равенства (==), примененный к двум объектам, возвращает true, если все переменные у обоих объектов равны. В PHP 5 для того, чтобы объекты считались равными, необходимо дополнительное уловие: они должны принадлежать одному и тому же классу.
Присвоение $this
Если до введения новой объектной модели можно было свобоно использовать переменную $this по своему усмотрению, то с пятой версии такая конструкция невозможна — нельзя переопределять зарезервированную переменную $this.
<?php
class Foo {
function Foo($class)
{
$this = new $class;
}
}
class Bar {
}
$foobar = new Foo('Bar');
// Fatal error: Cannot re-assign $this
?>
Существует несколько решений этой проблемы — от эмуляции присвоения путем статического вызова конструктора «присваемого» класса до генерации исключительной ситуации или ее эмуляции. Однако наиболее предпочтительным и совместимым с обеими версиями PHP методом является использование шаблона-одиночки (singleton).
<?php
class SingletonClass
{
private static $hash = array();
public static function singleton($class)
{
if (!array_key_exists($class, SingletonClass::$hash))
{
SingletonClass::$hash[$class] = new $class;
}
return SingletonClass::$hash[$class];
}
}
class BarClass
{
private $value;
public function __construct()
{
$this->value = 0;
}
public function setValue($value)
{
$this->value = $value;
}
public function getValue()
{
return $this->value;
}
}
$bar1 = SingletonClass::singleton('BarClass');
$bar1->setValue(6);
$bar2 = SingletonClass::singleton('BarClass');
echo $bar2->getValue();
?>
Список новых зарезервированных слов
Помимо this, в PHP5 введены следующие зарезервированные слова, которые теперь нельзя использовать для именования функций и переменных:
- final
- php_user_filter
- interface
- implements
- extends
- public
- private
- protected
- abstract
- clone
- try
- catch
- throw
- exception
- this
Функция get_class()
В PHP 5 эта функция возвращает название класса с сохранением регистра, в то время как PHP 4 всегда приводит название класса к нижнему регистру. Для совместимости можно использовать следующий код:
<?php
$cname = strtolower(get_class($obj));
?>
Уровень сообщений E_STRICT
В PHP 5 вводится новый уровень сообщений — E_STRICT, который может быть включен путем установки директивы, управляющей уровнем сообщений об ошибках, в состояние E_ALL | E_STRICT.
<?php
error_reporting(E_ALL | E_STRICT);
?>
Сообщения уровня E_STRICT генерируются в тех случаях, когда в коде используются устаревшие возможности предыдущих версий PHP. Несколько таких устаревших возможностей:
Автоматическое создание объектов
При попытке присвоить значение несуществующей переменной несуществующего объекта автоматически создается новый объект класса stdClass.
<?php
$foo->bar = true; // deprecated!
?>
Объявление переменных класса (var)
Поддерживается только ради обратной совместимости. Следует использовать модификаторы уровня доступа: public, protected или private.
Устаревший конструктор
Конструктор с именем, совпадающим с названием класса, поддерживается только ради обратной совместимости. Следует использовать унифицированный конструктор __construct.
Перекрытие наследуемых методов
Изменение объявления одноименных методов в наследуемых классах (изменение числа параметров) не приветствуется в PHP 5.
Функция xslt_create
После перехода на РНР 5 вы стали получать ошибку вида «PHP Fatal error: Call to undefined function xslt_create()»? В РНР 5 существенно поменялось API, вследствии чего функция xslt не поддерживается, поэтому разработчики рекомендуют вместо данной функции использовать xsl:
В этом случае есть два выхода:
- Переписать код ваших скриптов, используя XSL.
- Подключить дополнительный файл, который позволяет использовать функции xslt_create & etc в php5. Для этого нужно подключить файл xslt-php4-to-php5.php в скрипт в котором выполняется xslt_create, например, так:
if (version_compare(PHP_VERSION,'5','>=') && extension_loaded('xsl')) require_once('xslt-php4-to-php5.php');
Второй вариант лучше всего рассматривать как временый, т.к. адаптировав свой код к PHP 5, вы увеличите производительность работы ваших проектов.
Отметим, что подключение функций возможно только в том случае, если вы используете основой PHP, а не скомпилированный. В случае, если вы будете компилировать свой PHP с библиотекой libxslt, то возможно подключить только libxslt версии 1.1.17.
Функция xml_parser_create
В PHP выше 5.0.2 функция xml_parser_create работает в кодировке utf-8.
Здесь могут возникнуть сложности если вы используете информацию из баз данных в кодировке Windows-1251. Для ее разрешения необходимо преобразовать полученные из базы данные:
$data = mb_convert_encoding($data, "UTF-8", "Windows-1251");
где $data — преобразуемые данные.
Внимание!
В обязательном порядке необходимо ознакомиться со списком нововведений, повлекших за собой обратную несовместимость с предыдущими версиями PHP. Ваши скрипты в ряде случаев могут перестать корректно работать при смене версии интерпретатора. Перед переходом на новую версию постарайтесь убедиться в том, что написанные вами скрипты полностью совместимы с новой версией. Даже если перенос прошел без видимых проблем, советуем вам первое время обращать внимание на любые ошибки, возникающие при выполнении ваших скриптов.
Переход с MySQL 4.x.x на MySQL 5.x.x
Теперь на нашем хостинге доступна новая версия MySQL — 5.0.24. Новая версия работает быстрее, а база данных занимает до 20% меньше места на диске. Обо всех нововведениях вы можете почитать в документации на официальном сайте.
В новой версии MySQL появилась новая служебная база данных — INFORMATION_SCHEMA. Она решает задачу реализации словаря данных (data dictionary). INFORMATION_SCHEMA содержит таблицы, описывающие состояние и параметры сервера, в том числе определения и сущности таблиц. Это виртуальная база данных — физически (в виде файлов на диске) она не существует, вся информация динамически предоставляется сервером. Пример использования этой таблицы:
SELECT table_name, table_type, engine
FROM INFORMATION_SCHEMA.tables
WHERE table_schema = ‘tp’
+------------+------------+--------+
| table_name | table_type | engine |
+------------+------------+--------+
| t1 | BASE TABLE | MyISAM |
| t2 | BASE TABLE | MyISAM |
| v1 | BASE TABLE | MyISAM |
+------------+------------+--------+
Обратите внимание!
MySQL 5 имеет некоторые несовместимости с предыдущими версиями, полный список несовместимостей вы найдете здесь.
Проблемы с кодировками
Основная проблема, с которой сталкиваются пользователи при переходе с версий до 4.1 — проблема с кодировками. Причина данной проблемы в том, что MySQL 5 хранит все данные в кодировке UTF-8. Установленный у нас MySQL настроен так, чтобы при операциях ввода/вывода автоматически конвертировать данные из UTF-8 в Windows-1251 и обратно. Однако в некоторых ситуациях (например, если вы передаете в базу данные в кодировке KOI8-R или UTF-8) данные могут загружаться ошибочно или не загружаться совсем (на запрос вместо символов будут выдаваться знаки вопроса).
Возможны два варианта:
-
Клиент использует неправильную кодировку
Симптомы следующие:
- а) В phpMyAdmin (версии 2.6.0 или выше) содержимое таблиц отображается корректно, а в скрипт приходят вопросительные знаки.
- б) Скрипт отправляет в базу данных заведомо русский текст, после чего на запросы к базе как в скрипт, так и в phpMyAdmin возвращаются знаки вопроса.
Решение:
- Попробуйте в начале скрипта, сразу после инициализации соединения с базой данных, выполнить SQL-команду:
SET NAMES кодировка
Где «кодировка» — та кодировка, в которой у вас (по вашему мнению) данные. Это может быть, например, cp1251, koi8r, utf8 и другие.
Если буквы стали русскими — данные в базе находятся в правильной кодировке. Если буквы стали русскими, но слова не читаются (например, вместо слова «вопрос» возвращается слово «бнопня») — надо попробовать другую кодировку.
-
MySQL использует неправильную кодировку
Симптомы следующие:
- Скрипт получает русский текст, но не работают функции сортировки, перевода в верхний/нижний регистр и т.п. Обычно это сопровождается неправильным отображением данных в phpMyAdmin.
Диагностика:
-
Необходимо попробовать выполнить в phpMyAdmin следующий запрос:
Где «таблица», «поле» — соответственно таблица и ее поле, в котором хранится русский текст, «кодировка» — предполагаемая правильная кодировка. Если данные в результате запроса стали отображаться правильно — необходимо конвертировать таблицу.SELECT CONVERT(CONVERT(поле USING binary) USING кодировка) FROM таблица;
Решение:
-
Обязательно сделайте полный backup вашей базы данных, прежде чем выполнять конвертирование таблиц!
Конвертирование полей происходит следующим образом:
Например, есть таблица T со столбцом R, тип которого CHAR (50). Необходимо конвертировать содержимое данного столбца в кодировку cp1251. Выполняем следующие две команды:
ALTER TABLE T MODIFY R BINARY (50); ALTER TABLE T MODIFY R CHAR (50) CHARACTER SET cp1251;
Обратите внимание, что после BINARY в скобках указан размер поля. Если вы конвертируете поле типа TEXT, необходимо указать достаточно большое значение. В противном случае текст будет обрезан.
Более подробно процесс конвертации описан в оригинальной документации.
Особенности работы оператора JOIN
В предыдущих версиях MySQL оператор запятая (,) и JOIN имели одинаковый приоритет и выполнялись по порядку вхождения в запросе. Поэтому выражение
t1, t2 JOIN t3
интерпретировалось как
((t1, t2) JOIN t3)
В пятой версии оператор JOIN имеет более высокий приоритет, и описанное выше выражение интерпретируется иначе:
(t1, (t2 JOIN t3))
При этом может возникнуть ошибка:
Unknown column 't1.name' in 'on clause'
Для решения данной проблемы, необходимо изменить запрос, взяв в скобки имена таблиц после оператора FROM. Например, запрос:
SELECT count(*)FROM table1 t1, table2 t2 JOIN table3 t3 ON t1.id = t3.id WHERE …
надо заменить на:
SELECT count(*)FROM (table1 t1, table2 t2) JOIN table3 t3 ON t1.id = t3.id WHERE …