Эволюция PHP — от 5.6 до 8.0 (Часть 1)

Автор оригинала: Martynas Eskis
  • Перевод

Перевод статьи подготовлен в преддверии старта курса «Backend-разработчик на PHP».

Шпаргалка по изменениям в PHP v7.x

PHP_v8.0
PHP_v8.0

После релиза PHP версии 7.3 я решил уделить больше внимания развитию PHP: что собственно развивается и в каком направлении искать понимание потенциала и оптимизации этого невероятно популярного языка программирования.

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

За основу мы возьмем PHP 5.6 и рассмотрим, что было добавлено и изменено. Я также добавил везде где смог ссылки на официальную документацию по каждой из упомянутых фич, поэтому, если вам вдруг понадобится получить более подробную информацию - пожалуйста.

PHP 7.0

Поддержка анонимных классов

Анонимный класс может использоваться вместо именованного класса:

  • Когда класс не нужно документировать

  • Когда класс во время выполнения используется только один раз

new class($i) {
   public function __construct($i) {
       $this->i = $i;
   }
}

Функция целочисленного деления - безопасный способ деления (даже на 0).

Возвращает целочисленный результат деления первого операнда на второй. Если делитель (второй операнд) равен нулю, функция пробрасывает EWARNING и возвращает FALSE.

intdiv(int $numerator, int $divisor)

Добавлен новый оператор объединения с null - «??»

$x = NULL;
$y = NULL;
$z = 3;
vardump($x ?? $y ?? $z); // int(3)

$x = ["c" => "meaningfulvalue"];
vardump($x["a"] ?? $x["b"] ?? $x["c"]); // string(16) "meaningfulvalue"

Добавлен новый оператор - spaceship (космический корабль) (<=>)

Используется для оптимизации и упрощения операций сравнения.

// Прежде

function orderfunc($a, $b) {
   return ($a < $b) ? -1 : (($a > $b) ? 1 : 0);
}

// Используя оператор <=>

function orderfunc($a, $b) {
   return $a <=> $b;
}

Объявления скалярных типов

Это всего лишь первый шаг к реализации преимуществ более строго типизированного языка программирования в PHP - v0.5.

function add(float $a, float $b): float {
   return $a + $b;
}
add(1, 2); // float(3)

Объявления типов возвращаемых значений

Добавлена ​​возможность возвращать типы помимо скалярных - классы, включая наследование. Хех, упустив при этом возможность сделать это необязательным (что будет введено в v7.1 :))

interface A {
   static function make(): A;
}
class B implements A {
   static function make(): A {
       return new B();
   }
}

Групповые объявления use

// Явный use синтаксис:

use FooLibrary\Bar\Baz\ClassA;
use FooLibrary\Bar\Baz\ClassB;
use FooLibrary\Bar\Baz\ClassC;
use FooLibrary\Bar\Baz\ClassD as Fizbo;

// Групповой use синтаксис:
use FooLibrary\Bar\Baz{ ClassA, ClassB, ClassC, ClassD as Fizbo };

Делегация генератора

В теле функций генераторов разрешен следующий новый синтаксис:

yield from <expr>

Повышение производительности

PHP 7 почти вдвое быстрее, чем PHP 5.6.

Значительное сокращение использования памяти

Как видно из диаграмм, PHP 7.0 стал громадным шагом вперед с точки зрения производительности и использования памяти. Для страницы с запросами к базе данных версия 7.0.0 более чем в 3 раза быстрее, чем 5.6 с включенным opcache в 2.7 раза быстрее без opcache! С точки зрения использования памяти разница тоже существенная!

Интерфейс Throwable

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

Error и Exception теперь реализуют Throwable.

Иерархия Throwable:

interface Throwable
 |- Error implements Throwable
     |- ArithmeticError extends Error
         |- DivisionByZeroError extends ArithmeticError
     |- AssertionError extends Error
     |- ParseError extends Error
     |- TypeError extends Error
         |- ArgumentCountError extends TypeError
 |- Exception implements Throwable
     |- ClosedGeneratorException extends Exception
     |- DOMException extends Exception
     |- ErrorException extends Exception
     |- IntlException extends Exception
     |- LogicException extends Exception
         |- BadFunctionCallException extends LogicException
             |- BadMethodCallException extends BadFunctionCallException
         |- DomainException extends LogicException
         |- InvalidArgumentException extends LogicException
         |- LengthException extends LogicException
         |- OutOfRangeException extends LogicException
     |- PharException extends Exception
     |- ReflectionException extends Exception
     |- RuntimeException extends Exception
         |- OutOfBoundsException extends RuntimeException
         |- OverflowException extends RuntimeException
         |- PDOException extends RuntimeException
         |- RangeException extends RuntimeException
         |- UnderflowException extends RuntimeException
         |- UnexpectedValueException extends RuntimeException

⚠ Внимание! Вы можете реализовать Throwable только через Error и Exception.

Синтаксис кодирования Unicode — “\u{xxxxx}”

echo "\u{202E}Reversed text"; // выводит ‮Reversed text

echo "mañana"; // "ma\u{00F1}ana"
echo "mañana"; // "man\u{0303}ana" "n" комбинирована с символом ~ (U+0303)

Чувствительный к контексту лексер

С этим нововведением глобально зарезервированные слова стали полу-зарезервированными:

callable  class  trait  extends  implements  static  abstract  final  public  protected  private  const
enddeclare  endfor  endforeach  endif  endwhile  and  global  goto  instanceof  insteadof  interface
namespace  new  or  xor  try  use  var  exit  list  clone  include  includeonce  throw  array
print  echo  require  requireonce  return  else  elseif  default  break  continue  switch  yield
function  if  endswitch  finally  for  foreach  declare  case  do  while  as  catch  die  self parent

За исключением того, что по-прежнему запрещено определять константу класса с именем class из-за разрешения имени класса ::class.

Выражения return в генераторах

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

Поддержка уровня вложенности для функции dirname()

PHP 7.1

Обнуляемые типы

function answer(): ?int  {
   return null; // ок
}

function answer(): ?int  {
   return 42; // ок
}

function answer(): ?int {
   return new stdclass(); // ошибка
}

function say(?string $msg) {
   if ($msg) {
       echo $msg;

   }

}

say('hello'); // ок - выводит hello
say(null); // ок - ничего не выводит
say(); // ошибка - отсутствует параметр
say(new stdclass); // ошибка - не подходящий тип

Ничего не возвращающие функции

function shouldreturnnothing(): void {
   return 1; // Fatal error: A void function must not return a value
}

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

Функция с типом возврата void или void функция может либо возвращать неявно, либо иметь оператор возврата без значения:

function lacksreturn(): void {
  // валидно
}

Псевдотип Iterable

Обычно функция принимает или возвращает array или объект, реализующий Traversable, который используется с foreach. Однако, поскольку array является примитивным типом, а Traversable - интерфейсом, в настоящее время нет способа использовать объявление типа для параметра или возвращаемого типа, чтобы указать, что значение является итерируемым.

function foo(iterable $iterable) {
   foreach ($iterable as $value) {
       // …
   }
}

iterable также может использоваться в качестве возвращаемого типа, чтобы указать, что функция вернет итерируемое значение. Если возвращаемое значение не является массивом или экземпляром Traversable, будет проброшена TypeError.

function bar(): iterable {
   return [1, 2, 3];
}

Параметры, объявленные как iterable могут использовать null или массив в качестве значения по умолчанию.

function foo(iterable $iterable = []) {
   // …
}

Closure из callable

class Closure {
   …
   public static function fromCallable(callable $callable) : Closure {…}
   …
}

Синтаксис квадратных скобок для деструктуририрующего присваивания в массиве

$array = [1, 2, 3];

// Присваивает $a, $b и $c значения соответствующих элементов массива $array с ключами, пронумерованными от нуля
[$a, $b, $c] = $array;

// Присваивает $a, $b и $c значения элементов массива $array с ключами "a", "b" и "c" соответственно
["a" => $a, "b" => $b, "c" => $c] = $array;

Синтаксис квадратных скобок для list()

$powersOfTwo = [1 => 2, 2 => 4, 3 => 8];
list(1 => $oneBit, 2 => $twoBit, 3 => $threeBit) = $powersOfTwo;

Видимость констант класса

class Token {
    // Константы по умолчанию public
   const PUBLICCONST = 0;

       // Константы также могут иметь определенную пользователем видимость
       private const PRIVATECONST = 0;
       protected const PROTECTEDCONST = 0;
       public const PUBLICCONSTTWO = 0;

      // Константы могут иметь только один список объявлений видимости
       private const FOO = 1, BAR = 2;
}

Перехват нескольких типов исключений

try {
  // Какой-то код…
} catch (ExceptionType1 | ExceptionType2 $e) {
 // Код обработки исключения
} catch (\Exception $e) {
  // …
}

Читать вторую часть

Читать ещё:

OTUS. Онлайн-образование
Цифровые навыки от ведущих экспертов

Похожие публикации

Комментарии 5

    +1
    Возможно стоит в дополнении оформить в виде репозитория, наподобие webcoder-club/php-whats-new
      0
      Об функции intdiv не слышал, хоть и пытаюсь ухватить все нужные нововведения. Протестировал функцию, она выбрасывает исключение DivisionByZeroError || ArithmeticError, но не возвращает false.
        0

        Вы тестировали на PHP7.0?

          0
          Тестировал на 7.4 (не обратил внимание на раздел 7.0)
        0
        В вашем примере
        say("0");

        не вернёт ничего. Отличный пример того, почему не надо пользоваться неявными сравнениями.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое