Готовимся к php 7

Готовимся к php 7
image-3045

2015 год стал важный годом для PHP. Спустя одиннадцать лет после выпуска PHP 5.0, новая версия, наконец, готовится к выходу! PHP 7 выйдет до конца этого года, в результате чего мы получим много новых возможностей языка и впечатляющий прирост производительности.
Но как это повлияет на текущий ваш PHP код? Что действительно изменилось? Насколько это безопасно для обновления? Эта статья ответит на эти вопросы и покажет пару новинок которые придут с PHP 7.

Улучшения производительности

Производительность, несомненно, самая главная причина, почему вы должны обновить свои серверы, как только выйдет стабильная версия PHP. Рефакторинг ядра представленный в phpng RFC делает PHP 7, таким же быстрым (или даже быстрее чем) HHVM. Официальные тесты впечатляют, большинство реальных приложений, работающих на PHP 5.6 будет работать, по крайней мере в два раза быстрее на PHP 7.
Для получения подробной информации о тестах производительности, посмотрите на презентации Rasmus Лердорф. Вот показатели WordPress из этого доклада:

image-3046

PHP 7 обрабатывает в два раза больше запросов в секунду, что в практическом плане будет представлять улучшение производительности WordPress сайтов на 100%.

Обратная совместимость

Давайте поговорим о некоторых вещах, которые потенциально могут нарушить работоспособность приложения, работающие на старых версиях PHP.

Устаревшие элементы удалены

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

В частности, теги ASP-стиля (<%, <% = и %>), были удалены вместе с тегом сценариев (<script language=”php”>). Убедитесь, что вы используете рекомендуемый тег <?php. Другие функции, которые ранее были устаревшие, также были удалены в PHP 7.

Расширение EREG (и все ereg_* функции) были устаревшими, начиная с PHP 5.3. Они должны быть заменено с расширением PCRE (preg_* функции), который предлагает гораздо больше возможностей. Расширение MySQL (и mysql_* функции) были устаревшими, начиная с PHP 5.5. Для прямого перехода, вы можете использовать MySQLi расширение и mysqli_* функции вместо них.

Единый синтаксис переменных

Единый синтаксис переменных призвана решить ряд несоответствий при оценке переменная-переменная выражений. Рассмотрим следующий код:

<?php
class Person
{
   public $name = 'Erika';
   public $job = 'Developer Advocate';
}
$person = new Person();
$property = [ 'first' => 'name', 'second' => 'info' ];
echo "\nMy name is " . $person->$property['first'] . "\n\n";

В PHP 5, выражение $person->$property['first'] оценивается как $person->{$property['first']}. В практическом плане это будет интерпретироваться как $person->name, давая вам результат «My name is Erika». Даже если это крайний случай, это показывает четкие несоответствия с нормальным порядком вычисления выражения, слева направо.

В PHP 7, выражение $person->$property['first'] оценивается как {$person->$property}['first']. Интерпретатор оценить $person->$property в первую очередь; следовательно, предыдущий пример кода не будет работать в PHP7, потому что $property массива и не может быть преобразован в строку.

Быстрый и простой способ, чтобы исправить эту проблему, явно определяющий порядок оценки с помощью фигурных скобок (например, $person->{$property['first']}), который будет гарантировать такое же поведение как на PHP 5 и PHP 7.
Благодаря новой форме слева на права переменной синтаксиса, многие выражения ранее обработанные некорректно теперь работают без проблем. Чтобы проиллюстрировать это новое поведение, рассмотрим следующий класс:

<?php
class Person
{
   public static $company = 'DigitalOcean';
   public function getFriends()
   {
       return [
           'erika' => function () {
               return 'Elephpants and Cats';
           },
           'sammy' => function () {
               return 'Sharks and Penguins';
           }
       ];
   }
   public function getFriendsOf($someone)
   {
       return $this->getFriends()[$someone];
   }
   public static function getNewPerson()
   {
       return new Person();
   }
}

С PHP 7, мы можем создать вложенные ассоциации и различные комбинации между операторами:

$person = new Person();
echo "\n" . $person->getFriends()['erika']() . "\n\n";
echo "\n" . $person->getFriendsOf('sammy')() . "\n\n";

Этот фрагмент даст нам сообщение об ошибке в PHP 5, но работает, как ожидалось в PHP 7.

Аналогично, вложенными статического доступа также возможно:

echo "\n" . $person::getNewPerson()::$company . "\n\n";

В PHP 5, это даст нам классическую ошибку синтаксиса T_PAAMAYIM_NEKUDOTAYIM.

Фатальная ошибка с множественным «default» классами

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

Исключения

Исключение предназначены для облегчения обработки ошибок в вашем приложении. Существующие фатальные и извлекаемые фатальные ошибки были заменены исключениями, что делает возможным для нас, отловить ошибки и принять меры – для их отображения в красивом виде, их регистрации, или выполнения процедуры восстановления.

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

<?php
set_error_handler(function ($code, $message) {
   echo "ERROR $code: " . $message . "\n\n";
});
function a(ArrayObject $b){
   return $b;
}
a("test");
echo "Hello World";

Этот код генерирует возмещаемую ошибку, вызванную несоответствием типа при вызове функции a(), используя строку в качестве параметра. В PHP 5, она генерирует E_RECOVERABLE и вы получите:

ERROR 4096: Argument 1 passed to a() must be an instance of ArrayObject, string given, called in /data/Projects/php7dev/tests/test04.php on line 12 and defined(...)
Hello World

Обратите внимание, что выполнение продолжается, потому что ошибка была обработана. В PHP 7, этот код генерирует исключение TypeError (не ошибка!), Так что обработчик ошибок не будет вызвана. Это вывод, который вы получите:

Fatal error: Uncaught TypeError: Argument 1 passed to a() must be an instance of ArrayObject, string given, called in /vagrant/tests/test04.php on line 12 and defined in /vagrant/tests/test04.php:7
Stack trace:
#0 /vagrant/tests/test04.php(12): a('test')
#1 {main}
  thrown in /vagrant/tests/test04.php on line 7

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

  • Throwable интерфейс
    • Исключение реализует Throwable
      • ErrorException распространяется исключение
      • RuntimeException распространяется исключение
    • Ошибка реализует Throwable
      • Ошибка типа распространяется Ошибка
      • ParseError распространяется Ошибка
      • AssertionError распространяется Ошибка

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

Новые возможности языка

Давайте поговорим о наиболее интересных новых функций, которые будут доступны при обновлении до PHP 7.

Новые операторы

PHP 7 поставляется с двумя блестящими новыми операторами: spaceship (или сочетание операторов сравнения) и нулевого сливания оператор.
Оператор spaceship (<=>), также известный как комбинированного оператора сравнения, может быть использованы, чтобы сделать ваши блоки сравнение более кратким. Рассмотрим следующее выражение:

$a <=> $b

Это выражение будет -1, если $a меньше, чем $b, 0, если $a равен $b, и 1, если $a больше, чем $b. Раньше это было бы:

($a < $b) ? -1 : (($a > $b) ? 1 : 0)

Оператор null coalesce(??) также работает в качестве ярлыка для общего пользования в случае: условного авторства, который проверяет, если значение установлено, прежде чем использовать его. В PHP 5, вы, как правило, что-то вроде этого:

$a = isset($b) ? $b : "default";

С новым оператором в PHP 7, мы можем просто использовать:

$a = $b ?? "default";

Скалярные type-hint

Одна из самых обсуждаемых новых возможностях в PHP 7: скалярные type-hint будут доступны как типы для функций и методов. По умолчанию, скалярные типа не являются ограничительными, что означает, что если вы передаете значение с плавающей точкой в целое параметра, это будет просто заставить его Int без создания каких-либо ошибок или предупреждений.
Это возможно, однако, в строгом режиме, который будет выдавать ошибки при неверном типе переданном в качестве аргумента. Рассмотрим следующий код:

<?php
function double(int $value)
{
   return 2 * $value;
}
$a = double("5");
var_dump($a);

Этот код не будет генерировать какие-либо ошибки, потому что мы не используем строгий режим. Единственное, что будет происходить в преобразование типа, так что строка «5» передается в качестве аргумента будет принудительно преобразовано к целому числу внутри функции.
Если мы хотим, что бы только целые числа могли быть переданы в функцию, мы можем включить строгий режим DECLARE (strict_types = 1) в качестве самой первой строке в нашем сценарии:

<?php
declare(strict_types = 1);
function double(int $value)
{
   return 2 * $value;
}
$a = double("5");
var_dump($a);

Этот код будет генерировать фатальную ошибку: TypeError: Uncaught Argument 1 passed to double() must be of the type integer, string given.

Возвращение type-hint

Еще одна важная новая функция идет с PHP 7 это возможность определить тип возвращаемого значения метода и функций:

<?php
function a() : bool
{
   return 1;
}
var_dump(a());

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

Fatal error: Uncaught TypeError: Return value of a() must be of the type boolean, integer returned

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

Что дальше?

PHP 7 планирует выпустить стабильную версию в конце ноября. Бета-версия уже доступна для тестов. Проверьте RFC все изменения идут с PHP 7 для получения дополнительной информации.

Обратите внимание, что, хотя никаких новых функций не будет включен, некоторые изменения могут произойти еще до финального релиза, так что, пожалуйста, не используйте PHP 7 в продакшене! Настоятельно рекомендуется тестировать приложения и сообщать о любых проблем.

Счастливые кодирования!

  • c01nd01r

    >Счастливые кодирования!
    :rofl:

  • sensor-dream

    Наконец то, $a $b -1,0,1 епт еще всю архетектуру компьютерную перенести на поддержку что моготь быть и -1