image
Несколько дней назад я переключил свой сервер с порядка 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, который верно служил мне много лет.

Вряд ли вы встретите какие-то проблемы кроме вышеперечисленных, но если вам интересно то полный список доступен на сайте PHP.

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

P.S.: Фея в заголовке статьи — наш праздничный логотип PHPixie 3, он не совсем в тему, но очень хотелось поделиться. Ну можете считать, что это она PHP 7 несет в мешке.

Комментарии (44)


  1. maxru
    18.11.2015 18:19

    Расширение mysql больше недоступно

    Как и memcached


    1. jigpuzzled
      18.11.2015 18:24

      насколько я понимаю внутренности поменялись гораздо сильнее чем сам язык. Как раз поэтому автор XCache написал что пока нет планов на версию для 7-ки.


    1. pherum
      18.11.2015 19:11
      +3

      что с memcached не так? на homebrew он устанавливается, только доступен из ветки dev-master
      видимо выкатят стабильную версию после релиза самого php7


    1. Blumfontein
      19.11.2015 07:38
      +2

      memcache или memcacheD?


  1. romy4
    18.11.2015 18:36

    То есть, код

    $array = [1,2,3];
    foreach ( $array as $k=>&$v )
    {
        $v = get_something_else(); // return 3 4 5
    }
    var_dump($array);
    

    что в итоге даст?


    1. jigpuzzled
      18.11.2015 18:42
      +2

      с & совсем другое дело, тут работать также будет. Имеется ввиду такое:

      $a = array(1,2,3);
      $b = &$a;
      foreach($a as $v) {
          echo "$v\n";
          unset($a[1]);
      }
      


      1. romy4
        18.11.2015 18:53
        +2

        Понятно, спасибо. Делать unset() внутри foreach никогда не было безопасно.


        1. Sild
          19.11.2015 17:36
          +1

          Расскажите тогда, как стоит поступать в таких ситуациях?

          $a = array("test"=>"1", "test2"=>2, "test3"=>3);
          $needed = array("test", "test2");
          foreach($a as $i => $v) {
              if(!in_array($i, $needed)) {
                  unset($a[$i]);
              }   
          }
          


          Ну надо мне провалидировать что-то. Собирать новый массив?


          1. Fesor
            19.11.2015 17:59
            +2

            Собирать новый массив?

            Именно так.

            $a = array("test"=>"1", "test2"=>2, "test3"=>3);
            $needed = array("test", "test2");
            
            $a = array_filter($a, function ($item) {
                 return in_array($item, $needed);
            });
            


            1. bolk
              20.11.2015 17:09
              +2

              Вы use($needed) забыли.


          1. romy4
            20.11.2015 15:16

            Нашёл два замечательных поста: [1] Тонкости работы foreach в php [2] References in foreach


            1. Sild
              20.11.2015 18:28

              Наткнулся в комментариях на ещё один пост: http://habrahabr.ru/post/114899/

              У меня прям все написанные исходники перед глазами пронеслись. Думал в такие моменты, что нужно больше спать, и переписывал на if-else.


              1. romy4
                21.11.2015 13:53

                Да, TheShock умеет «накинуть» :) Там же в комментах, вместо if-else

                switch(true){
                    case isCondFirst():
                        value = valueFirst();
                        break;
                    case isCondSecond():
                        value = valueSecond();
                        break;
                    case isCondThird():
                        value = valueThird();
                        break;
                    default:
                        value = valueDefault();
                }
                


                просто нечто.


          1. Xu4
            23.11.2015 07:11

            Я конкретно эту ситуацию имею ввиду:

            $a = ['test' => '1', 'test2' => 2, 'test3' => 3];
            $filter = ['test', 'test2'];
            
            $a = array_intersect_key($a, array_flip($filter));
            


            Если ситуация отличается, то и решение может быть другое. Но вот в данном конкретном случае такой код лучше подойдёт, мне кажется. Как минимум, одной переменной меньше и используются встроенные функции, вместо реализации алгоритма вручную.


      1. dim_s
        19.11.2015 10:23

        А что если?

        $a = array(1,2,3);
        foreach($a as $i => $v) {
            echo "$v\n";
            $a[$i] = $v * 2;
        }
        
        var_dump($a); // ???
        


        1. jigpuzzled
          19.11.2015 12:23
          +3

          1. romy4
            19.11.2015 15:39

            какая полезная песочница. Я постоянно юзал sandbox.onlinephpfunctions.com


  1. romy4
    18.11.2015 18:39
    +2

    И мне нужен xdebug для отладки, а то без него ой как плохо отлаживать сложные прыжки в коде. Жду, когда они 2.4.0 в релиз выпустят.


    1. jigpuzzled
      18.11.2015 18:45

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


      1. romy4
        18.11.2015 18:53

        Я для себя придерживаюсь железного правила:

        ini_set("error_reporting",65535);
        и чтобы не было ни одного уведомления в работе. Жаль только, такого очень трудно достичь используя чужие фреймворки.


        1. jigpuzzled
          18.11.2015 19:02

          В PHPixie все строго, заходи =)


        1. vlreshet
          18.11.2015 19:41

          Не нашёл здесь 65535 http://php.net/manual/ru/errorfunc.constants.php. Что вы имеете ввиду?


          1. romy4
            18.11.2015 19:44

            Я имел в виду E_ALL и ещё один бит.


        1. bolk
          19.11.2015 09:19
          +2

          error_reporting(-1);


      1. OnYourLips
        19.11.2015 13:37
        +5

        У вас на prod и dev разные версии PHP?
        Мне одному кажется такое недопустимым?


    1. Fesor
      19.11.2015 13:51

      Есть phpdbg


  1. stalkerg
    18.11.2015 21:57
    +1

    А адаптеры для Postgres шевелятся?


    1. jigpuzzled
      18.11.2015 23:57
      +1

      так они в PDO входят же, так что конечно


    1. Fesor
      19.11.2015 13:48
      +1

      ext-pgsql работает без нареканий.


  1. summerwind
    18.11.2015 23:38
    +1

    Для примера простой сайт на PHPixie заработал почти в три раза быстрее практически сравнившись со скоростью Phalcon на PHP 5.6, несколько сайтов на Wordpress показали стабильный прирост в скорости в два раза.

    Странные какие-то сравнения. В два, в три раза… По сравнению с чем? Какие задачи сравнивались? Какие операции?
    Если учесть, что в обычных сайтах основная часть времени уходит на запросы к БД, то непонятно, как смена версии PHP могла это ускорить. Или там на сайтах интегралы численными методами высчитываются?)


  1. jigpuzzled
    18.11.2015 23:57

    основная часть времени уходит на запросы к БД


    это давно уже совсем не так, вот например бенчмарки от Techempower: www.techempower.com/benchmarks/#section=data-r9&hw=peak&test=fortune&l=sg

    По условиям теста запросов у каждого фреймворка получается столько же, но вот скорость сильно отличается


  1. SamDark
    19.11.2015 13:24

    Сегфолтит семёрка пока по-страшному. Правят оперативно, но надо больше тестов. Прошу всех погонять свои проекты и заслать в багтрекер трейсы, дампы или, что вообще лучше всего, короткие кусочки кода, которые PHP валят.


    1. zou
      19.11.2015 13:32

      Сейчас пишу новый проект на семерке. Стремно, но пишу. Пока что не словил ни единого бага, вылета и тд. Расширения спокойно собрал вручную, все что для проекта нужно — работает. Вот интересно что может быть аргументом против запуска нового проекта на РНР 7 на следующий день после его релиза.


      1. SamDark
        19.11.2015 14:08

        Против проверки на тестовом сервере — ничего. Против выката на продакшн много чего. Как минимум стоит спланировать откат до 5.6 в деталях.


        1. Fesor
          19.11.2015 14:23

          У меня коллеги как раз таки из-за сегфолтов php5.6 апнулись на семерку. hhvm как оказалось отвратительно работает с postgresql.

          Это я к чему, для любого апдейта должны быть причины. Уж темболее если это апдейта на релиз кандидат или бетку.


          1. SamDark
            19.11.2015 15:06

            Думаю, получить от 30% прироста производительности — хороший аргумент за переход на семёрку. Но делать это надо осторожно.


    1. sergebezborodov
      19.11.2015 18:30

      Саш, а как с yii на семерке?


      1. SamDark
        19.11.2015 18:48

        В общем и целом отлично. Код работать будет. Все сегфолты воспроизведены и закинуты в трекер. Большинство Расмус уже поправил.

        Новых фич семёрки, конечно же, из за обратной совместимости, не используем пока.


        1. sergebezborodov
          19.11.2015 19:13

          интересно очень, дождусь релиза и запущу отдельный сервер с семеркой и налью часть трафа hotwork.ru померяю реальное ускорение


          1. Fesor
            19.11.2015 19:23

            неужели у вас нет старых добрых нагрузочных тестов?


            1. sergebezborodov
              19.11.2015 19:32

              не применяли, в системе 100к суточных визитов, нагрузка растет плавно, поэтому гонять нагрузку в суточные 1млн визитов смысла особо нет
              а ливануть пару тыс живого трафа на хорошее дело всегда можно ;)


  1. WellWisher
    19.11.2015 13:58

    Если только отсутствие нужных библиотек, совместимых с PHP 7.
    Пока дойдете до релиза думаю что если «вдруг» что-то и появится внезапное, — то всё будет пофикшено.


    1. Fesor
      19.11.2015 14:02

      на данный момент есть аж 2 инструмента что бы помочь быстрее мигрировать проекты на php7:

      github.com/Alexia/php7mar
      github.com/sstalle/php7cc

      В принципе популярные фреймворки уже совместимы с PHP7. В частности у Symfony небыло никаких проблем.


  1. bolk
    20.11.2015 17:10
    +1

    Безумству храбрых поём мы песню, конечно. На ветке PHP7 постоянно находятся неприятные баги. Падения, зацикливания, утечки. Например описание сегодняшнего исправления такое: «try{ } finally{} can create infinite chains of exceptions».