Что нового в PHP 8, сравнение с PHP 7
07.01.2020 вышла новая стабильная версия PHP 8 (8.0.1). В этой статье мы расскажем о новых функциях и возможностях в сравнении с версией PHP 7.
PHP 8 стал еще более быстрым и надежным. По сравнению с версией PHP 7 появилось множество новых и полезных вещей, которые обязательно будут востребованы пользователями. Рассмотрим подробнее эти нововведения.
Типы Union 2.0 (Объединенные типы)
Существует множество случаев, когда использование типов объединения может быть полезным. Вместо аннотаций PHPDoc для объединенных типов теперь вы можете использовать объявления union type, которые проверяются сразу во время выполнения.
Union Types — это совокупность двух или более типов, которые указывают, что вы можете использовать любой из них.
JIT – компилятор
JIT (Just In Time — «в нужный момент») — это динамическая компиляция байт кода в машинный. JIT компилятор значительно улучшает производительность работы программ. Проверка на синтетических бенчмарках показывает улучшение производительности примерно в 3 раза и в 1,5–2 раза для некоторых долго работающих приложений.
В JIT код переводится сначала в промежуточное представление и только потом в машинный код. То есть, выполняется непосредственно на процессоре, а не на виртуальной машине Zend VM.
JIT реализован как независимая часть OPcache. Его можно включать / отключать во время компиляции или выполнения скрипта.

Использование ::class для объектов
В PHP 8 теперь вы можете использовать ::class для объектов вместо того, чтобы использовать get_class() как раньше. Работает точно так же, как и get_class().
Атрибуты
В PHP 8 теперь вместо аннотаций PHPDoc вы можете использовать структурные метаданные с нативным синтаксисом PHP.
Выражение Match
В PHP 8 новое выражение match похоже на оператор switch, но имеет свои особенности:
- Match — это выражение и его результат может быть сохранён в переменной или возвращён.
- Условия match поддерживают только однострочные выражения, для которых не требуется управляющая конструкция break;
- Выражение match использует строгое сравнение.
Оператор Nullsafe
В PHP 8 теперь вместо проверки на null вы можете использовать последовательность вызовов с новым оператором Nullsafe. Если один из элементов в последовательности возвращает null, то выполнение прерывается и вся последовательность возвращает null.
Улучшенное сравнение строк и чисел
Теперь при сравнении с числовой строкой PHP 8 использует сравнение чисел. В противном случае число преобразуется в строку и используется сравнение строк.
Ошибки согласованности типов для встроенных функций
В PHP 8 большинство внутренних функций теперь выбрасывают исключение Error, если при проверке параметра возникает ошибка.
Именованные аргументы
В PHP 8 теперь можно:
- Указывать только необходимые параметры и пропускать необязательные.
- Порядок аргументов не важен, аргументы самодокументируемы.
Объявление свойств в конструкторе
В новой версии PHP 8 теперь используется гораздо меньше шаблонного кода для определения и инициализации свойств.
Новый тип возврата static
Ранее в PHP уже были возвращаемые типы — self и parent, но static не был допустимым типом возврата для этого языка программирования. Теперь есть.
Throw-выражения
В PHP оператор throw не может создавать исключения там, где были разрешены только выражения, например стрелочные функции, оператор объединения и тернарный оператор.
В новом PHP 8 теперь вы можете преобразовывать инструкцию throw в выражение.
Weak maps
Weak maps — это набор объектов, на которые в коде слабо ссылаются ключи, что может привести к их удалению сборщиками мусора. В PHP 8 добавлен класс WeakMaps для создания сохранения ссылки на объект. При этом она не препятствует удалению самого объекта.
Завершающая запятая в списках параметров
Ранее при вызове функции в списках параметров отсутствовала поддержка запятой. В PHP 8 теперь это разрешено.
Новый Stringable интерфейс
В PHP 8 теперь вы можете использовать интерфейс Stringable для аннотации типов или имплементации метода __toString (). И больше нет необходимости реализовывать его вручную.
Новые функции в PHP 8
- get_debug_type() — возвращает тип переменной. В отличии от gettype() возвращает более полезный вывод для массивов, строк, анонимных классов и объектов.
- str_starts_with() — проверяет, начинается ли строка с определенной строки. Возвращает TRUE / FALSE.
- str_ends_with() — проверяет, заканчивается ли строка с определенной строки. Возвращает TRUE / FALSE.
- str_contains() — проверяет, содержит ли строка другую строку.
- fdiv() — эта функция похожа на fmod() и intdiv(), что позволяет делить на 0. Но вместо ошибок получаем INF, -INF или NAN, в зависимости от случая.
6. get_resource_id() — ранее ресурсам присваивается идентификатор, но для этого необходимо было преобразование ресурса в int. В PHP 8 добавлена функция get_resource_id(), что делает эту операцию более очевидной и безопасной для типов.
К сожалению многие CMS пока не поддерживают PHP 8, в частности и 1С-Битрикс. В любом случае поддержка PHP 8 скоро появится на всех тарифах нашего хостинга.
Подробнее ознакомиться с нововведениями можно на официальной странице проекта.
Php 8 что нового
PHP 8.1 — большое обновление языка PHP.
Оно содержит множество новых возможностей, включая перечисления, readonly-свойства, callback-функции как объекты первого класса, файберы, пересечение типов, улучшения производительности и многое другое.
Перечисления RFC Документация
class Status
const DRAFT = ‘draft’ ;
const PUBLISHED = ‘published’ ;
const ARCHIVED = ‘archived’ ;
>
function acceptStatus ( string $status ) <. >
enum Status
case Draft ;
case Published ;
case Archived ;
>
function acceptStatus ( Status $status )
Используйте перечисления вместо набора констант, чтобы валидировать их автоматически во время выполнения кода.
Readonly-свойства RFC Документация
class BlogData
private Status $status ;
public function __construct ( Status $status )
$this -> status = $status ;
>
public function getStatus (): Status
return $this -> status ;
>
>
class BlogData
public readonly Status $status ;
public function __construct ( Status $status )
$this -> status = $status ;
>
>
Readonly-свойства нельзя изменить после инициализации (т.е. когда им было присвоено значение).
Они будут крайне полезны при реализации объектов типа VO и DTO .
Callback-функции как объекты первого класса RFC Документация
$foo = [ $this , ‘foo’ ];
$fn = Closure :: fromCallable ( ‘strlen’ );
С помощью нового синтаксиса любая функция может выступать в качестве объекта первого класса. Тем самым она будет рассматриваться как обычное значение, которое можно, например, сохранить в переменную.
Расширенная инициализация объектов RFC
class Service
private Logger $logger ;
public function __construct (
? Logger $logger = null ,
) $this -> logger = $logger ?? new NullLogger ();
>
>
class Service
private Logger $logger ;
public function __construct (
Logger $logger = new NullLogger (),
) $this -> logger = $logger ;
>
>
Объекты теперь можно использовать в качестве значений параметров по умолчанию, статических переменных и глобальных констант, а также в аргументах атрибутов.
Таким образом появилась возможность использования вложенных атрибутов.
class User
/**
* @Assert\All( * @Assert\NotNull,
* @Assert\Length(min=5)
* >)
*/
public string $name = » ;
>
class User
#[ \Assert\All (
new \Assert\NotNull ,
new \Assert\Length ( min : 5 ))
]
public string $name = » ;
>
Пересечение типов RFC Документация
function count_and_iterate ( Iterator $value ) <
if (!( $value instanceof Countable )) <
throw new TypeError ( ‘value must be Countable’ );
>
foreach ( $value as $val ) echo $val ;
>
Теперь в объявлении типов параметров можно указать, что значение должно относиться к нескольким типам одновременно.
В данный момент пересечения типов нельзя использовать вместе с объединёнными типами, например, A&B|C .
Тип возвращаемого значения never RFC Документация
function redirect ( string $uri ) <
header ( ‘Location: ‘ . $uri );
exit();
>
function redirectToLoginPage () redirect ( ‘/login’ );
echo ‘Hello’ ; // >
function redirect ( string $uri ): never <
header ( ‘Location: ‘ . $uri );
exit();
>
function redirectToLoginPage (): never redirect ( ‘/login’ );
echo ‘Hello’ ; // >
Функция или метод, объявленные с типом never , указывают на то, что они не вернут значение и либо выбросят исключение, либо завершат выполнение скрипта с помощью вызова функции die() , exit() , trigger_error() или чем-то подобным.
Окончательные константы класса RFC Документация
class Foo
public const XX = «foo» ;
>
class Bar extends Foo
public const XX = «bar» ; // No error
>
class Foo
final public const XX = «foo» ;
>
class Bar extends Foo
public const XX = «bar» ; // Fatal error
>
Теперь константы класса можно объявить как окончательные (final), чтобы их нельзя было переопределить в дочерних классах.
Явное восьмеричное числовое обозначение RFC Документация
016 === 16 ; // false because `016` is octal for `14` and it’s confusing
016 === 14 ; // true
0o16 === 16 ; // false — not confusing with explicit notation
0o16 === 14 ; // true
Теперь можно записывать восьмеричные числа с явным префиксом 0o .
Файберы RFC Документация
$httpClient -> request ( ‘https://example.com/’ )
-> then (function ( Response $response ) return $response -> getBody ()-> buffer ();
>)
-> then (function ( string $responseBody ) print json_decode ( $responseBody )[ ‘code’ ];
>);
$response = $httpClient -> request ( ‘https://example.com/’ );
print json_decode ( $response -> getBody ()-> buffer ())[ ‘code’ ];
Файберы — это примитивы для реализации облегчённой невытесняющей конкурентности. Они являются средством создания блоков кода, которые можно приостанавливать и возобновлять, как генераторы, но из любой точки стека. Файберы сами по себе не предоставляют возможностей асинхронного выполнения задач, всё равно должен быть цикл обработки событий. Однако они позволяют блокирующим и неблокирующим реализациям использовать один и тот же API.
Файберы позволяют избавиться от шаблонного кода, который ранее использовался с помощью Promise::then() или корутин на основе генератора. Библиотеки обычно создают дополнительные абстракции вокруг файберов, поэтому нет необходимости взаимодействовать с ними напрямую.
Поддержка распаковки массивов со строковыми ключами RFC Документация
$arrayA = [ ‘a’ => 1 ];
$arrayB = [ ‘b’ => 2 ];
$result = array_merge ([ ‘a’ => 0 ], $arrayA , $arrayB );
Php 8 что нового
class PostsController
#[ Route ( «/api/posts/» , methods : [ «GET» ])]
public function get ( $id ) < /* . */ >
>
Вместо аннотаций PHPDoc вы можете использовать структурные метаданные с нативным синтаксисом PHP.
Объявление свойств в конструкторе RFC Документация
class Point <
public float $x ;
public float $y ;
public float $z ;
public function __construct (
float $x = 0.0 ,
float $y = 0.0 ,
float $z = 0.0
) $this -> x = $x ;
$this -> y = $y ;
$this -> z = $z ;
>
>
class Point <
public function __construct (
public float $x = 0.0 ,
public float $y = 0.0 ,
public float $z = 0.0 ,
) <>
>
Меньше шаблонного кода для определения и инициализации свойств.
Тип Union RFC Документация
class Number <
/** @var int|float */
private $number ;
/**
* @param float|int $number
*/
public function __construct ( $number ) $this -> number = $number ;
>
>
new Number ( ‘NaN’ ); // Нет ошибки
class Number <
public function __construct (
private int | float $number
) <>
>
new Number ( ‘NaN’ ); // TypeError
Вместо аннотаций PHPDoc для объединённых типов вы можете использовать объявления типа union, которые проверяются во время выполнения.
Выражение Match RFC Документация
switch ( 8.0 ) <
case ‘8.0’ :
$result = «О нет!» ;
break;
case 8.0 :
$result = «То, что я и ожидал» ;
break;
>
echo $result ;
//> О нет!
echo match ( 8.0 ) <
‘8.0’ => «О нет!» ,
8.0 => «То, что я и ожидал» ,
>;
//> То, что я и ожидал
Новое выражение match похоже на оператор switch со следующими особенностями:
- Match — это выражение, его результат может быть сохранён в переменной или возвращён.
- Условия match поддерживают только однострочные выражения, для которых не требуется управляющая конструкция break;.
- Выражение match использует строгое сравнение.
Оператор Nullsafe RFC
if ( $session !== null ) $user = $session -> user ;
if ( $user !== null ) $address = $user -> getAddress ();
if ( $address !== null ) $country = $address -> country ;
>
>
>
$country = $session ?-> user ?-> getAddress ()?-> country ;
Вместо проверки на null вы можете использовать последовательность вызовов с новым оператором Nullsafe. Когда один из элементов в последовательности возвращает null, выполнение прерывается и вся последовательность возвращает null.
Улучшенное сравнение строк и чисел RFC
0 == ‘foobar’ // true
0 == ‘foobar’ // false
При сравнении с числовой строкой PHP 8 использует сравнение чисел. В противном случае число преобразуется в строку и используется сравнение строк.
Ошибки согласованности типов для встроенных функций RFC
strlen ([]); // Warning: strlen() expects parameter 1 to be string, array given
array_chunk ([], — 1 ); // Warning: array_chunk(): Size parameter expected to be greater than 0
strlen ([]); // TypeError: strlen(): Argument #1 ($str) must be of type string, array given
array_chunk ([], — 1 ); // ValueError: array_chunk(): Argument #2 ($length) must be greater than 0
Большинство внутренних функций теперь выбрасывают исключение Error, если при проверке параметра возникает ошибка.
Компиляция Just-In-Time
PHP 8 представляет два механизма JIT-компиляции. Трассировка JIT, наиболее перспективная из них, на синтетических бенчмарках показывает улучшение производительности примерно в 3 раза и в 1,5–2 раза на некоторых долго работающих приложениях. Стандартная производительность приложения находится на одном уровне с PHP 7.4.
Относительный вклад JIT в производительность PHP 8
Улучшения в системе типов и обработке ошибок
- Более строгие проверки типов для арифметических/побитовых операторов RFC
- Проверка методов абстрактных трейтов RFC
- Правильные сигнатуры магических методов RFC
- Реклассификация предупреждений движка RFC
- Фатальная ошибка при несовместимости сигнатур методов RFC
- Оператор @ больше не подавляет фатальные ошибки.
- Наследование с private методами RFC
- Новый тип mixed RFC
- Возвращаемый тип static RFC
- Типы для стандартных функций E-mail Тема
- Непрозрачные объекты вместо ресурсов для Curl, Gd, Sockets, OpenSSL, XMLWriter, e XML расширения
Прочие улучшения синтаксиса
- Разрешена запятая в конце списка параметров RFC и в списке use замыканий RFC
- Блок catch без указания переменной RFC
- Изменения синтаксиса переменных RFC
- Имена в пространстве имен рассматриваются как единый токен RFC
- Выражение Throw RFC
- Добавление ::class для объектов RFC
Новые классы, интерфейсы и функции
- Класс Weak Map
- Интерфейс Stringable
- str_contains(), str_starts_with(), str_ends_with()
- fdiv()
- get_debug_type()
- get_resource_id()
- Объектно-ориентированная функция token_get_all()
- Новые API для обходения и обработки DOM
Выше производительность, лучше синтаксис, надежнее система типов.
Для загрузки исходного кода PHP 8 посетите страницу downloads. Бинарные файлы Windows находятся на сайте PHP для Windows. Список изменений представлен в ChangeLog.
Руководство по миграции доступно в разделе документации. Пожалуйста, изучите его для получения подробного списка новых возможностей и обратно несовместимых изменений.
- Copyright © 2001-2024 The PHP Group
- My PHP.net
- Contact
- Other PHP.net sites
- Privacy policy
- View Source
PHP 8 — что нового в 8-ой версии php
Оглавления для удобной навигации по новым PHP 8.0 фичам (клик для перехода):

1. Новые нативные функции для работы со строками
str_contains — для проверки есть ли подстрока в строке.
str_contains(string $haystack, string $needle): bool
str_starts_with, str_ends_with — функции для проверки «начинается ли строка с» и «заканчивается ли строка на»
str_starts_with(string $haystack, string $needle): bool
str_ends_with (string $haystack, string $needle): bool
2. Named arguments
Теперь можно использовать именованные аргументы. Это может быть полезно, например, когда функция имеет много необязательных аргументов, но нам они не важны и нам важно передать только последний из аргументов.
function namedArgExample(string $arg1, array $arg2 = [], array $arg3 = [], bool $arg4 = false); namedArgExample('string', arg4: true);
namedArgExample('string', [], [], true)
3. «Constructor property promotion» или просто «Constructor promotion»
Для меня, это одна из самых полезных фичей новой версии, которая позволяет экономить время разработки и рефакторинга.
Прямо в конструкторе можно указать модификтор доступа любого аргумента будь то private / protected / public , тогда property с таким именем можно нужно не объявлять вовсе. Как можно заметить, никакое присваивание в теле конструктора тоже не нужно, наличие модификатора доступа в конструкторе PHP 8.0 — автоматически создает проперти с именем, равным именем переменной и присваивает параметр в property.
class A < public function __construct( private B $b, private RouterInterface $router ) < >>
class A < private B $b; private RouterInterface $router; public function __construct( private B $b, private RouterInterface $router ) < $this->b = $b; $this->router = $router; > >
Используя DI, autowiring и constructor promotion — теперь сплошное удовольствие при подстановке зависимостей в сервис.
4. match expression
Match expression (см. https://www.php.net/manual/en/control-structures.match.php) — более емкий и читаемый вариант для оператора switch . Есть и отличие от switch : match всегда использует строгое сравнение. Отпадает необходимость в break.
$var = 2; echo match ($var) < 2 =>'two', 3 => 'three', default => 'none', >;
Итого про match:
не любой switch можно заменить на match . Вместо простых switch можно использовать более читаемый и емкий match .
5. Union types
class UnionTypeExample
В этом случае в проперти $this->city можно будет присовить только типы false, null или объект City.
То, что раньше описывали c помощью phpdoc /** @var false|null */ теперь можно легально описать языковой конструкцией.
Кроме types properties, Union types можно использовать как в аргументах, так и в возвращаемых значениях.
Лучше не увлекаться Union types в PHP, так как все таки это не однозначность в типах.
6. Attributes PHP 8.0 feature
Аттрибуты — фича, которая позволяет использовать языковую конструкцию для добавления мета-данных к классу, функции, проперти. Проблема, которую решают аттрибуты — зависимость кода от PHPDoc комментариев, что очень широко используется в doctrine, symfony и тд. Теперь выполнение кода может зависеть от аттрибутов:) которые являются языковой конструкцией, то есть это более «стандартизированный» подход.
Аттрибуты в PHP объявляются с помощью символов #[ и ]
/** * @Route(path="/", methods=, name="main") */ public function indexAction(): Response
#[Route('/', methods: ['GET'], name: 'main'] public function indexAction(): Response
По поводу синтаксиса аттрибутов было много споров. В PHP все что начинается с # является комментарием. Это значит, что синтаксис аттрибутов #[ не будет вызывать синтаксическую ошибку на более ранних версиях PHP (до PHP 8.0). То есть код с аттрибутами запустится и на более ранних версиях языка, чем когда аттрибуты стали поддерживаться (с PHP 8.0). Другой вопрос, станет ли код на ранних версиях работать ожидаемо:)
PHP 8.0: Nullsafe operator feature
Проверка на null при вызове методов может быть осуществлена прямо в вызове с помощью добавления знака ? (вопрос): ?->
Если один из объектов в цепочке вызов выше будет null , то в переменную запишется null
Может быть интересно: