Бортовой журнал. Стоит ли переходить на PHP7? Переход с php 5.6 на 7

Стоит ли переходить на новую версию PHP 7.0 ? – Однозначно стоит, даже не думайте - переходите!

В седьмой версии достаточно много нововведений. Основные из них:

  • в основе ядра PHP 7 используется PHPNG . Новое ядро дает прирост производительности сайтам от 40%;
  • type Hints и возвращаемые значения . Теперь при объявлении функции для каждой переменной можно указывать свой тип, а также тип данных, который вернет функция. Доступные типы: int , float , string и bool ;
  • комбинированный оператор сравнения и многое другое.

В PHP 7 были удалены некоторые расширения:

  • mysql

Уже в PHP 5.6.x использование этих расширений было нежелательным. Вместо «mysql» следует использовать «PDO», а вместо ereg → preg .

Более детально ознакомиться с новинками PHP 7 можно на официальной странице

Стоит ли переходить на PHP 7?

На данный момент самое простое, что вы можете сделать для увеличения производительности сайта, это перейти на PHP 7.0.x. Прирост скорости также зависит от того, как написан ваш проект. Если вы еще сомневаетесь, покажем некоторые сравнения:

Бенчмарки PHP 5.6 vs PHP 7 для нектоторых фреймфорков (Zend framework, Magento, Drupal, Mediawiki, WordPress, Laravel, SugarCRM и др):

По всем фреймворкам прирост производительности значительный. Давайте посмотрим, как обстоит дело с функциями и конструкциями ядра:

Бенчмарки PHP 5.6 vs PHP 7 для функций и конструкций ядра:

Если графики вас убедили, можно попробовать перенести свой сайт на новую версию PHP и ощутить прирост на реальном проекте.

Коллеги с Elasticweb рассказали, что перед запуском нового сервера с PHP 7 они запустили на нем крупный государственный проект, работающий на Laravel 5. Это был своеобразный тест производительности новой версии PHP и сервера в целом. Ранее этот проект был на сервере с PHP 5.6. После переноса сайта страницы начали открываться значительно быстрее, при этом использование ресурсов сократилось вдвое.

Для подготовки переезда на PHP 7 они использовали PHP 7 Migration Assistant Report (MAR) . Большинство популярных CMS/Framework уже обладают совместимостью с PHP 7, поэтому основная задача сводилась к тестированию custom плагинов.

WordPress 4, Drupal 8/7 и последняя версия Joomla уже готовы к PHP 7!

Итак, у вас есть старенький, но уж очень милый сердцу сайт, который вы решаетесь из жалости (или, возможно, перечитав Хабра) перевести на PHP7. С волнением ожидая резкого роста производительности, вы смахиваете пыль с бедного сайта и решительно переключаете в панели управления хостингом версию PHP.

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

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

Резервные копии

Делаем резервные копии сайта (а заодно и баз данных). Ведь кто не делает резервные копи - сам себе враг, верно? Для разного рода экспериментов имеет смысл добавить еще один сайт на хостинге и скопировать в него файлы, которые мы сейчас будем править.

Журналы ошибок

Настроим ведение журнала ошибок PHP в файл.htaccess (если он не был настроен ранее):

php_value display_errors 0
php_value log_errors 1
php_value error_log /home/vasya/domains/mysite.ru/logs/error.log

Работа с MySQL

Допустим, сайт использует базы данных, и вы видите ошибки вроде такой:

Fatal error: Uncaught Error: Call to undefined function mysql_connect()

Это оттого, что в современных версиях PHP (начиная с PHP 5.5.0) оригинальное расширение MySQL не поддерживается. Разработчики рекомендуют использовать MySQLi или PDO. Попробуем перейти на MySQLi, это просто:

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

$link = mysql_connect(‘localhost’, $user, $password)
mysql_select_db($dbname, $link)
mysql_query(‘set names cp1251’)

можно заменить на:

$link = mysqli_connect(‘localhost’, $user, $password, $dbname)
mysqli_query($link, ‘set names cp1251’)

для запросов:

$result=mysql_query($query,$cid)

заменить на:

$result=mysqli_query($cid, $query)

Другие популярные функции легко меняются на их аналоги с буквой ‘i’:

mysqli_fetch_array()
mysqli_fetch_row()
mysqli_fetch_assoc()
mysqli_fetch_array()
mysqli_num_rows()
mysqli_insert_id()
mysqli_close()

В результате этих несложных действий данные из БД должны успешно собираться и отправляться.

Кодировка

Настоящий олдскул - это сайт в CP1251 (как минимум). Всё превратилось в ромбики или прочие козяблики?

Скорее всего, достаточно будет указать кодировку в.htaccess таким образом:

php_value default_charset «cp1251»

Регулярные выражения

Также вы можете наблюдать ошибки следующего рода:

Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead

Это означает, что модификатор /e, который позволял передать произвольной функции результат регулярного выражения, теперь не поддерживается. В таких случаях рекомендуется использовать функцию preg_replace_callback

Допустим, у нас есть такое регулярное выражение:

$string=preg_replace(«/:({1,10}):/e», «print_smile(‘\\1’)», $string)

с заменой на preg_replace_callback оно должно выглядеть вот так:

$string=preg_replace_callback(«/:({1,10}):/», create_function(‘$matches’, ‘return print_smile($matches)’), $string)

здесь все просто, регулярное выражение теперь указывается в качестве первого аргумента (без модификатора /e, разумеется), а в качестве второго аргумента указывается анонимная функция (которая будет выполнена после применения регулярного выражения) с двумя аргументами: массив $matches, где будут сохранены данные, совпадающие с регулярным выражением и вызов внешней функции с аргументами. В данном примере внешняя функция называется print_smile и ей передается аргументом первое найденное вхождение. То, что в preg_replace было \\1 (первое найденное вхождение) станет $matches (если аргументов было больше, то будет $matches, $matches и так далее).

Вот еще один пример, посложнее:

Было так:

$out=preg_replace(«/<(=[\’\»]{0,1}|)(.*?)([\’\»]{0,1})>(.*?)<\/>/es», «feed_out_sub_rm(‘\\2′,’$base_prefix’,’$nick’,’$id_entry’)», $out)

Стало вот так:

$out=preg_replace_callback(‘/<(=[\’\»]{0,1}|)(.*?)([\’\»]{0,1})>(.*?)<\/>/s’, create_function(‘$matches’, ‘return feed_out_sub_rm($matches, «‘.$base_prefix."», «‘.$nick."», «‘.$id_entry."») ‘), $out)

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

Копаясь в регулярных выражениях, можно вспомнить еще про две функции, которые с версии PHP 5.3.0 считаются устаревшими (и не поддерживаются). Симптомы следующие:

Fatal error: Uncaught Error: Call to undefined function ereg_replace()

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

$str=ereg_replace(«[\r\t\n]»,»»,$str)
$str=preg_replace(«/[\r\t\n]/»,»»,$str)

Аналогичный симптом:

Fatal error: Uncaught Error: Call to undefined function split()

$var_pair=split(«=»,$tmp)

$var_pair=explode(«=»,$tmp)

Если регулярное выражение посложнее, то пробуем преобразовать к preg_split.

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

Для того, чтобы оставлять комментарии к посту, авторизуйтесь, используя свой аккаунт в социальных сетях ВКонтакте/FaceBook, или аккаунт в Google/Яндекс.

Несколько дней назад я переключил свой сервер с порядка 30-ти сайтами на PHP 7. Некоторые из них были достаточно старыми и составляли широкий набор с различных фреймворков и CMS. Вот несколько советов для тех кто еще не решил переходить на PHP 7 или нет.

Начнем с того что я понимаю что есть много людей которые не считают стабильную версию действительно «стабильной» пока она чуть-чуть не повзрослела, ожидая что еще найдутся какие-то баги или несовместимости. С того что я пока видел, пробуя каждый release candidate как только он выходил, совсем безопасно переключиться на PHP 7 как только он выйдет. Я ни разу не заметил какого-то непонятного поведения или вылета которому виной не был бы я сам. Несмотря на то что это новая версия она не несет много несовместимых изменений, то есть по большому счету можете относиться к ней как к просто PHP 5.7 только существенно быстрее.

И скорость действительно впечатляет, даже невероятно как. Для примера простой сайт на PHPixie заработал почти в три раза быстрее практически сравнившись со скоростью Phalcon на PHP 5.6, несколько сайтов на Wordpress показали стабильный прирост в скорости в два раза. Если учесть недавний отчет от Google что потеря даже 10% производительности загрузки страниц приводит к ощутимой потери клиентов, то если вы можете запросто ускорить работу сайта в два раза просто обновив PHP вы получаете больше продаж ничего не потратив. Вспомните об этом, когда будете убеждать своего менеджера перейти на PHP 7. Ничего не убеждает лучше, чем объем продаж.

Несколько замечаний

Расширение mysql больше недоступно, так что если вы еще не перешли на PDO или mysqli то теперь уж точно придется. Благо во многих случаях достаточно просто заменить вызовы к mysql_ функциям на mysqli_ .

E_STRICT ошибки реклассифицированы как другие типы ошибок. Если раньше вы их прятали или игнорировали, то теперь они начнут всплывать вместе с другими. Например, вызов нестатических методов статически теперь выбрасывает E_DEPRECATED что создало кучу проблем с Joomla 2.5 который почему-то делает это довольно часто. Также несовместимое наследование теперь классифицируется как E_WARNING . Wordpress уже с февраля тестируется на работу с PHP 7, так что с ним самим проблем никаких нет, правда, несколько плагинов таки оказались несовместимыми.

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

Теперь $foo->$bar["baz"] интерпретируется как ($foo->$bar)["baz"] а не $foo->{$bar["baz"]} как в PHP 5. Это редкий случай, но тоже попалось в одном из плагинов, и как оказалось в Magento 1.x (core/Mage/Core/Model/Layout.php ).

Имейте в виду, что не все расширения уже поддерживают PHP 7. Я уже не могу использовать понравившийся мне XCache, который верно служил мне много лет.

В сумме мне заняло около 5 часов чтобы перевести все сайты на PHP 7. Процесс совсем нетрудный и пакеты доступны уже для всех популярных дистрибутивов. Так что даже если вы собираетесь ждать стабильного релиза (уже совсем недолго), нет никакой причины не приготовить свои сайты к миграции наперед.

Стоит ли переходить на новую версию PHP 7.0 ? - Однозначно стоит, даже не думайте — переходите!

В седьмой версии достаточно много нововведений. Основные из них:

  1. в основе ядра PHP 7 используется PHPNG. Новое ядро дает прирост производительности сайтам от 40%;
  2. type Hints и возвращаемые значения. Теперь при объявлении функции для каждой переменной можно указывать свой тип, а также тип данных, который вернет функция. Доступные типы: int, float, string и bool;
  3. комбинированный оператор сравнения и многое другое.

В PHP 7 были удалены расширения:

  • mysql

Удаленные расширения давно были в статусе "deprecated", их использование приводило к выводу на экран warning. Вместо "mysql" нужно использовать "mysqli" или "pdo_mysql", а вместо "ereg" => "preg_*".

Более детально ознакомиться с новинками PHP 7 можно на официальной странице .

Стоит ли переходить на PHP 7?

На данный момент самое простое, что вы можете сделать для увеличения производительности сайта, это перейти на PHP 7.0.x. Прирост скорости также зависит от того, как написан ваш проект. Если вы еще сомневаетесь, покажем некоторые сравнения:

Бенчмарки PHP 5.6 vs PHP 7 для нектоторых фреймфорков и CMS (Zend framework, Magento, Drupal, Mediawiki, WordPress, Laravel, SugarCRM и др):

По всем фреймворкам прирост производительности значительный. Давайте посмотрим, как обстоит дело с функциями и конструкциями ядра:

Если графики вас убедили, можно попробовать перенести свой сайт на новую версию PHP и ощутить прирост на реальном проекте.

При создании ноды, выберите в списке серверов "Blue", для того чтобы нода была создана на сервере с PHP 7.

Вот так показывает себя 1c bitrix на базе SSD диска и PHP 7.0

Решил написать о переходе на PHP 7 , так как сам сейчас занять переводом кода одного движка по PHP 7. И так для начала включаем дебаг или отладчик в админ панели сайта, если такого нет у вас, то можно сделать так, как написано в теме: , теперь на экране монитора, мы можем видеть сообщения ошибках, например, такое:

Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead - dir/file.php (номер строки)


Это сообщение говорит о том, что модификатор e не существует в PHP 7, следует избавляться от него, но если просто удалить данный модификатор, сценарий может выполнятся неправильно, непросто же так его туда писали. Я покажу на примере кода из PHPFOX 3 (как я переписывал код: ), делаем так:
Например, у нас сообщение ошибки указывает на такую строчку:

$sStr = preg_replace("/\.+?\[\/x\]/ise", """.stripslashes(\$this->_parseUserTagged("$1")).""", $sStr);


Её следует изменить так:

$sStr = preg_replace_callback("/\.+?\[\/x\]/is", function($match) { return stripslashes($this->_parseUserTagged($match)); }, $sStr);


Тут мы заменили функцию preg_replace() , на preg_replace_callback() , удалили модификатор e в первом аргументе, которым является регулярное выражение. Второй аргумент заменили анонимной функцией, которая будет выполнятся после применения регулярного выражения. Анонимная функция содержит массив $match , элементы массива заменяют совпадения, например, было: $1 , стало: $match ; было: $2 , стало: $match , и так далее. Убрали кавычки и символ экранирования (обратный слеш \).

В завершении об ошибки несуществующего модификатора e , покажу ещё пару примеров замены кода. Строку:

$aRow["value_actual"] = preg_replace("/s:(.*):\"(.*?)\";/ies", ""s:".strlen("$2").":\"$2\";"", $aRow["value_actual"]);


Меняем так:

$aRow["value_actual"] = preg_replace_callback("/s:(.*):\"(.*?)\";/is", function($match) { return "s:" . strlen($match) . ":"" . $match . "";"; }, $aRow["value_actual"]);


И пример с переменной в регулярном выражении, строка:

$sTxt = preg_replace("/\[" . $sBbcode . "=(.*?)\]/ise", """.\$this->_replaceBbCode("" . \$sBbcode . "", "prefix", true, "$1").""", $sTxt);


Заменяется так:

$sTxt = preg_replace_callback("/\[" . $sBbcode . "=(.*?)\]/is", function($match) use($sBbcode) { return $this->_replaceBbCode($sBbcode, "prefix", true, $match); }, $sTxt);


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

function($match) use($a, $b, $c)

Устаревшая функция ereg_replace()
Как сообщил официальный сайт PHP: http://php.net/:

С версии PHP 5.3.0 эта функция считается УСТАРЕВШЕЙ. Крайне не рекомендуется полагаться на эту возможность.


А уж в PHP 7 про неё вообще забыли... Можно получить такое сообщение об ошибки:

Fatal error: Uncaught Error: Call to undefined function ereg_replace()


Эту функцию следует заменить на preg_replace() , следуя примеру ниже. Допустим у нас такая строка кода:

$str = ereg_replace("[^ -<>-}]", " ", str_replace("\x00", " ", $originalcommentname));


Изменяем код так: