<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/migration74.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'ru',
  ),
  'this' => 
  array (
    0 => 'migration74.new-features.php',
    1 => 'Новые возможности',
    2 => 'Новые возможности',
  ),
  'up' => 
  array (
    0 => 'migration74.php',
    1 => 'Миграция с PHP 7.3.x на PHP 7.4.x',
  ),
  'prev' => 
  array (
    0 => 'migration74.php',
    1 => 'Миграция с PHP 7.3.x на PHP 7.4.x',
  ),
  'next' => 
  array (
    0 => 'migration74.new-classes.php',
    1 => 'Новые классы и интерфейсы',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ru',
    'path' => 'appendices/migration74/new-features.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="migration74.new-features" class="sect1">
 <h2 class="title">Новые возможности</h2>

 <div class="sect2" id="migration74.new-features.core">
  <h3 class="title">Ядро PHP</h3>

  <div class="sect3" id="migration74.new-features.core.typed-properties">
   <h4 class="title">Типизированные свойства</h4>

   <p class="para">
    Свойства класса теперь поддерживают объявления типов.
    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">class </span><span style="color: #0000BB">User<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">int $id</span><span style="color: #007700">;<br />    public </span><span style="color: #0000BB">string $name</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
    Приведённый пример показывает, что свойству <code class="literal">$user-&gt;id</code> получится
    присвоить только значения с типом <span class="type"><a href="language.types.integer.php" class="type int">int</a></span>, тогда как свойству <code class="literal">$user-&gt;name</code> —
    только значения с типом <span class="type"><a href="language.types.string.php" class="type string">string</a></span>.
   </p>
  </div>

  <div class="sect3" id="migration74.new-features.core.arrow-functions">
   <h4 class="title">Стрелочные функции</h4>

   <p class="para">
    <a href="functions.arrow.php" class="link">Стрелочные функции</a> — сокращённая запись для определения функций
    с неявной привязкой родительской области видимости по значению.
    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />$factor </span><span style="color: #007700">= </span><span style="color: #0000BB">10</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$nums </span><span style="color: #007700">= </span><span style="color: #0000BB">array_map</span><span style="color: #007700">(fn (</span><span style="color: #0000BB">$n</span><span style="color: #007700">) =&gt; </span><span style="color: #0000BB">$n </span><span style="color: #007700">* </span><span style="color: #0000BB">$factor</span><span style="color: #007700">, [</span><span style="color: #0000BB">1</span><span style="color: #007700">, </span><span style="color: #0000BB">2</span><span style="color: #007700">, </span><span style="color: #0000BB">3</span><span style="color: #007700">, </span><span style="color: #0000BB">4</span><span style="color: #007700">]);<br /></span><span style="color: #FF8000">// $nums = array(10, 20, 30, 40);<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
   </p>
  </div>

  <div class="sect3" id="migration74.new-features.core.type-variance">
   <h4 class="title">Ограниченная ковариация возвращаемого типа и контравариантность типа аргумента</h4>

   <p class="para">
    Следующий код теперь будет работать:
    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">class </span><span style="color: #0000BB">A </span><span style="color: #007700">{}<br />class </span><span style="color: #0000BB">B </span><span style="color: #007700">extends </span><span style="color: #0000BB">A </span><span style="color: #007700">{}<br /><br />class </span><span style="color: #0000BB">Producer<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">method</span><span style="color: #007700">(): </span><span style="color: #0000BB">A </span><span style="color: #007700">{}<br />}<br /><br />class </span><span style="color: #0000BB">ChildProducer </span><span style="color: #007700">extends </span><span style="color: #0000BB">Producer<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">method</span><span style="color: #007700">(): </span><span style="color: #0000BB">B </span><span style="color: #007700">{}<br />}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
    Полная поддержка вариантности доступна только при автозагрузке классов.
    Нельзя ссылаться на типы циклически внутри одного файла, поскольку при ссылке
    на класс, который пока недоступен, возникает фатальная ошибка.
    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #FF8000">/**<br /> * Класс удовлетворяет принципу подстановки Б. Ли́сков (англ. Liskov Substitution Principle, LSP),<br /> * поскольку класс C принадлежит подтипу A,<br /> * но при объявлении класса B класс C ещё недоступен<br /> */<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">A<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">method</span><span style="color: #007700">(): </span><span style="color: #0000BB">A </span><span style="color: #007700">{}<br />}<br /><br />class </span><span style="color: #0000BB">B </span><span style="color: #007700">extends </span><span style="color: #0000BB">A<br /></span><span style="color: #007700">{<br />    </span><span style="color: #FF8000">// Fatal error: Could not check compatibility between B::method():C and<br />    // A::method(): A, because class С is not available<br />    </span><span style="color: #007700">public function </span><span style="color: #0000BB">method</span><span style="color: #007700">(): </span><span style="color: #0000BB">С </span><span style="color: #007700">{}<br />}<br /><br />class </span><span style="color: #0000BB">C </span><span style="color: #007700">extends </span><span style="color: #0000BB">B </span><span style="color: #007700">{}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
   </p>
  </div>

  <div class="sect3" id="migration74.new-features.core.null-coalescing-assignment-operator">
   <h4 class="title">Присваивающий оператор объединения с null</h4>

   <p class="para">
    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />$array</span><span style="color: #007700">[</span><span style="color: #DD0000">'key'</span><span style="color: #007700">] ??= </span><span style="color: #0000BB">computeDefault</span><span style="color: #007700">();<br /><br /></span><span style="color: #FF8000">// Предыдущая проверка на null с присваиванием — примерно то же, что:<br /></span><span style="color: #007700">if (!isset(</span><span style="color: #0000BB">$array</span><span style="color: #007700">[</span><span style="color: #DD0000">'key'</span><span style="color: #007700">])) {<br />    </span><span style="color: #0000BB">$array</span><span style="color: #007700">[</span><span style="color: #DD0000">'key'</span><span style="color: #007700">] = </span><span style="color: #0000BB">computeDefault</span><span style="color: #007700">();<br />}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
   </p>
  </div>

  <div class="sect3" id="migration74.new-features.core.unpack-inside-array">
   <h4 class="title">Распаковка внутри массивов</h4>

   <p class="para">
    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />$parts </span><span style="color: #007700">= [</span><span style="color: #DD0000">'apple'</span><span style="color: #007700">, </span><span style="color: #DD0000">'pear'</span><span style="color: #007700">];<br /><br /></span><span style="color: #0000BB">$fruits </span><span style="color: #007700">= [</span><span style="color: #DD0000">'banana'</span><span style="color: #007700">, </span><span style="color: #DD0000">'orange'</span><span style="color: #007700">, ...</span><span style="color: #0000BB">$parts</span><span style="color: #007700">, </span><span style="color: #DD0000">'watermelon'</span><span style="color: #007700">];<br /></span><span style="color: #FF8000">// ['banana', 'orange', 'apple', 'pear', 'watermelon'];<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
   </p>
  </div>

  <div class="sect3" id="migration74.new-features.core.numeric-literal-separator">
   <h4 class="title">Разделитель в числовых литералах</h4>

   <p class="para">
    Между знаками числовых литералов теперь допускаются символы подчёркивания.
    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />6.674_083e-11</span><span style="color: #007700">; </span><span style="color: #FF8000">// число с плавающей точкой<br /></span><span style="color: #0000BB">299_792_458</span><span style="color: #007700">;   </span><span style="color: #FF8000">// десятичное число<br /></span><span style="color: #0000BB">0xCAFE_F00D</span><span style="color: #007700">;   </span><span style="color: #FF8000">// шестнадцатеричное число<br /></span><span style="color: #0000BB">0b0101_1111</span><span style="color: #007700">;   </span><span style="color: #FF8000">// двоичное число<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
   </p>
  </div>

  <div class="sect3" id="migration74.new-features.core.weakreference">
   <h4 class="title">Слабые ссылки</h4>

   <p class="para">
    <a href="class.weakreference.php" class="link">Слабые ссылки</a> разрешают программисту хранить ссылку на объект,
    которая не препятствует уничтожению объекта сборщиком мусора, когда ссылок на объект не осталось.
   </p>
  </div>

  <div class="sect3" id="migration74.new-features.core.tostring-exceptions">
   <h4 class="title">Исключения в магическом методе __toString()</h4>

   <p class="para">
    В магическом методе <a href="language.oop5.magic.php#object.tostring" class="link">__toString()</a> разрешили
    выбрасывать исключения. Раньше это вызывало фатальную ошибку. Существующие
    отлавливаемые фатальные ошибки при преобразовании объекта в строку преобразовали
    в исключения класса <span class="classname"><a href="class.error.php" class="classname">Error</a></span>.
   </p>
  </div>

 </div>

 <div class="sect2" id="migration74.new-features.curl">
  <h3 class="title">Модуль cURL</h3>

  <p class="para">
   В дополнение к станадртным названиям файлов класс <span class="classname"><a href="class.curlfile.php" class="classname">CURLFile</a></span> теперь поддерживает
   потоковые обёртки, если модуль собрали с библиотекой libcurl &gt;= 7.56.0.
  </p>
 </div>

 <div class="sect2" id="migration74.new-features.filter">
  <h3 class="title">Модуль Filter</h3>

  <p class="para">
   Фильтр <strong><code><a href="filter.constants.php#constant.filter-validate-float">FILTER_VALIDATE_FLOAT</a></code></strong> теперь поддерживает
   параметры <code class="literal">min_range</code> и <code class="literal">max_range</code>,
   с тем же смыслом, что и фильтр <strong><code><a href="filter.constants.php#constant.filter-validate-int">FILTER_VALIDATE_INT</a></code></strong>.
  </p>
 </div>

 <div class="sect2" id="migration74.new-features.ffi">
  <h3 class="title">Модуль FFI</h3>

  <p class="para">
   FFI — новый модуль, который предлагает простой способ вызова
   библиотечных функций, доступа к встроенным переменным
   и способ создавать или обращаться к структурам данных, которые определили в библиотеках на языке Си.
  </p>
 </div>

 <div class="sect2" id="migration74.new-features.gd">
  <h3 class="title">Модуль GD</h3>

  <p class="para">
   Добавили константу <strong><code><a href="image.constants.php#constant.img-filter-scatter">IMG_FILTER_SCATTER</a></code></strong> для применения рассеивающегося фильтра к изображениям.
  </p>
 </div>

 <div class="sect2" id="migration74.new-features.hash">
  <h3 class="title">Модуль Hash</h3>

  <p class="para">
   Добавили поддержку алгоритма <code class="literal">crc32c</code>, который вычисляет «хеш» на основе полинома Кастаноли.
   С этой реализацией алгоритма CRC32 работают системы хранения наподобие iSCSI, SCTP, Btrfs и ext4.
  </p>
 </div>

 <div class="sect2" id="migration74.new-features.mbstring">
  <h3 class="title">Многобайтовые строки</h3>

  <p class="para">
   Добавили функцию <span class="function"><a href="function.mb-str-split.php" class="function">mb_str_split()</a></span>, которая выполняет
   то же, что и функция <span class="function"><a href="function.str-split.php" class="function">str_split()</a></span>, но работает
   с кодовыми точками, а не с байтами.
  </p>
 </div>

 <div class="sect2" id="migration74.new-features.opcache">
  <h3 class="title">Модуль OPcache</h3>

  <p class="para">
   Добавили поддержку <a href="opcache.preloading.php" class="link">предварительной загрузки кода</a>.
  </p>
 </div>

 <div class="sect2" id="migration74.new-features.pcre">
  <h3 class="title">Регулярные выражения, совместимые с синтаксисом языка Perl</h3>

  <p class="para">
   Функции <span class="function"><a href="function.preg-replace-callback.php" class="function">preg_replace_callback()</a></span> и <span class="function"><a href="function.preg-replace-callback-array.php" class="function">preg_replace_callback_array()</a></span>
   теперь принимают дополнительный аргумент <code class="parameter">flags</code> с поддержкой флагов
   <strong><code><a href="pcre.constants.php#constant.preg-offset-capture">PREG_OFFSET_CAPTURE</a></code></strong> и <strong><code><a href="pcre.constants.php#constant.preg-unmatched-as-null">PREG_UNMATCHED_AS_NULL</a></code></strong>.
   Он повлияет на формат массива совпавших значений, передаваемого в callback-функцию.
  </p>
 </div>

 <div class="sect2" id="migration74.new-features.pdo">
  <h3 class="title">Модуль PDO</h3>

  <p class="para">
   Имя пользователя и пароль как часть DSN-строки разрешили указывать
   для драйверов mysql, mssql, sybase, dblib, firebird и oci. Раньше это поддерживалось
   только для драйвера pgsql. Конструктор будет приоритетнее,
   если имя пользователя с паролем указали и в конструкторе, и в DSN-строке.
  </p>
  <p class="para">
   В SQL-запросах разрешили экранировать вопросительные знаки, чтобы
   они не воспринимались как заполнители параметров.
   Запись <code class="literal">??</code> отправит один знак вопроса в базу данных,
   и разрешит, например при работе с СУБД PostgreSQL, указывать оператор <code class="literal">?</code>,
   чтобы проверить, содержит ли столбец JSON конкретный ключ.
  </p>
 </div>

 <div class="sect2" id="migration74.new-features.pdo_oci">
  <h3 class="title">Драйвер PDO_OCI</h3>

  <p class="para">
   Для драйвера теперь доступен метод <span class="methodname"><a href="pdostatement.getcolumnmeta.php" class="methodname">PDOStatement::getColumnMeta()</a></span>.
  </p>
 </div>

 <div class="sect2" id="migration74.new-features.pdo_sqlite">
  <h3 class="title">Драйвер PDO_SQLite</h3>

  <p class="para">
   Вызов <code class="literal">PDOStatement::getAttribute(PDO::SQLITE_ATTR_READONLY_STATEMENT)</code>
   проверит, доступен ли подготовленный запрос только для чтения,
   т. е. не изменяет ли запрос базу данных.
  </p>
  <p class="para">
   При установке <code class="literal">PDO::setAttribute(PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES, true)</code>
   методы <span class="function"><a href="pdo.errorinfo.php" class="function">PDO::errorInfo()</a></span> и <span class="function"><a href="pdostatement.errorinfo.php" class="function">PDOStatement::errorInfo()</a></span>
   возвращают расширенные коды ошибок СУБД SQLite3.
  </p>
 </div>

 <div class="sect2" id="migration74.new-features.sqlite3">
  <h3 class="title">SQLite3</h3>

  <p class="para">
   Добавили метод <span class="methodname"><strong>SQLite3::lastExtendedErrorCode()</strong></span>,
   который получает последний расширенный код ошибки.
  </p>
  <p class="para">
   Добавили метод <code class="literal">SQLite3::enableExtendedResultCodes($enable = true)</code>,
   который заставит метод <span class="methodname"><a href="sqlite3.lasterrorcode.php" class="methodname">SQLite3::lastErrorCode()</a></span>
   возвращать расширенные коды ошибок.
  </p>
 </div>

 <div class="sect2" id="migration74.new-features.standard">
  <h3 class="title">Стандартные функции языка</h3>

  <div class="sect3" id="migration74.new-features.standard.strip-tags">
   <h4 class="title">Функция strip_tags() с массивом имён тегов</h4>
   <p class="para">
    Функция <span class="function"><a href="function.strip-tags.php" class="function">strip_tags()</a></span> теперь также принимает массив разрешённых тегов:
    вместо <code class="literal">strip_tags($str, &#039;&lt;a&gt;&lt;p&gt;&#039;)</code>
    теперь можно написать <code class="literal">strip_tags($str, [&#039;a&#039;, &#039;p&#039;])</code>.
   </p>
  </div>

  <div class="sect3" id="migration74.new-features.standard.magic-serialize">
   <h4 class="title">Пользовательская сериализация объектов</h4>
   <p class="para">
    Добавили новый механизм сериализации пользовательских объектов
    через два новых магических метода: <code class="literal">__serialize</code>
    и <code class="literal">__unserialize</code>.
    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #FF8000">// Метод возвращает массив с данными для сохранения целостного состояния объекта<br /></span><span style="color: #007700">public function </span><span style="color: #0000BB">__serialize</span><span style="color: #007700">(): array {}<br /><br /></span><span style="color: #FF8000">// Восстанавливает состояние объекта из массива данных<br /></span><span style="color: #007700">public function </span><span style="color: #0000BB">__unserialize</span><span style="color: #007700">(array </span><span style="color: #0000BB">$data</span><span style="color: #007700">): </span><span style="color: #0000BB">void </span><span style="color: #007700">{}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
    Новый механизм сериализации заменяет интерфейс <span class="interfacename"><a href="class.serializable.php" class="interfacename">Serializable</a></span>,
    который в будущем объявят устаревшим.
   </p>
  </div>

  <div class="sect3" id="migration74.new-features.standard.array-merge-no-args">
   <h4 class="title">Функции слияния массивов без аргументов</h4>
   <p class="para">
    Функции <span class="function"><a href="function.array-merge.php" class="function">array_merge()</a></span> и <span class="function"><a href="function.array-merge-recursive.php" class="function">array_merge_recursive()</a></span>
    стали поддерживать вызов без аргументов. При вызове без аргументов функции возвращают пустой массив.
    Функции также полезно вызывать с распаковкой аргумента spread-оператором: <code class="literal">array_merge(...$arrays)</code>.
   </p>
  </div>

  <div class="sect3" id="migration74.new-features.standard.proc-open">
   <h4 class="title">Функция <span class="function"><a href="function.proc-open.php" class="function">proc_open()</a></span></h4>
   <p class="para">
    Функция <span class="function"><a href="function.proc-open.php" class="function">proc_open()</a></span> теперь принимает массив вместо
    строки для выполнения команды. При таком вызове процесс открывается
    напрямую, без командной оболочки, а PHP экранирует
    аргументы, если потребуется.
    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />proc_open</span><span style="color: #007700">([</span><span style="color: #DD0000">'php'</span><span style="color: #007700">, </span><span style="color: #DD0000">'-r'</span><span style="color: #007700">, </span><span style="color: #DD0000">'echo "Привет, мир\n";'</span><span style="color: #007700">], </span><span style="color: #0000BB">$descriptors</span><span style="color: #007700">, </span><span style="color: #0000BB">$pipes</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
   </p>
   <p class="para">
    Функция <span class="function"><a href="function.proc-open.php" class="function">proc_open()</a></span> теперь поддерживает
    дескрипторы <code class="literal">redirect</code> и <code class="literal">null</code>.
    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #FF8000">// То же самое, что и 2&gt;&amp;1 в командной оболочке<br /></span><span style="color: #0000BB">proc_open</span><span style="color: #007700">(</span><span style="color: #0000BB">$cmd</span><span style="color: #007700">, [</span><span style="color: #0000BB">1 </span><span style="color: #007700">=&gt; [</span><span style="color: #DD0000">'pipe'</span><span style="color: #007700">, </span><span style="color: #DD0000">'w'</span><span style="color: #007700">], </span><span style="color: #0000BB">2 </span><span style="color: #007700">=&gt; [</span><span style="color: #DD0000">'redirect'</span><span style="color: #007700">, </span><span style="color: #0000BB">1</span><span style="color: #007700">]], </span><span style="color: #0000BB">$pipes</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">// То же самое, что и 2&gt;/dev/null или 2&gt;nul в командной оболочке<br /></span><span style="color: #0000BB">proc_open</span><span style="color: #007700">(</span><span style="color: #0000BB">$cmd</span><span style="color: #007700">, [</span><span style="color: #0000BB">1 </span><span style="color: #007700">=&gt; [</span><span style="color: #DD0000">'pipe'</span><span style="color: #007700">, </span><span style="color: #DD0000">'w'</span><span style="color: #007700">], </span><span style="color: #0000BB">2 </span><span style="color: #007700">=&gt; [</span><span style="color: #DD0000">'null'</span><span style="color: #007700">]], </span><span style="color: #0000BB">$pipes</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
   </p>
  </div>

  <div class="sect3" id="migration74.new-features.standard.sodium-argon-hash">
   <h4 class="title">Алгоритмы Argon2i и argon2id без библиотеки libargon</h4>
   <p class="para">
    Функция <span class="function"><a href="function.password-hash.php" class="function">password_hash()</a></span> теперь поддерживает варианты хеширования argon2i и argon2id
    из модуля Sodium, если PHP собрали без библиотеки libargon.
   </p>
  </div>

 </div>

</div><?php manual_footer($setup); ?>