<?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 => 'en',
  ),
  'this' => 
  array (
    0 => 'migration74.incompatible.php',
    1 => 'Backward Incompatible Changes',
    2 => 'Backward Incompatible Changes',
  ),
  'up' => 
  array (
    0 => 'migration74.php',
    1 => 'Migrating from PHP 7.3.x to PHP 7.4.x',
  ),
  'prev' => 
  array (
    0 => 'migration74.constants.php',
    1 => 'New Global Constants',
  ),
  'next' => 
  array (
    0 => 'migration74.deprecated.php',
    1 => 'Deprecated Features',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'en',
    'path' => 'appendices/migration74/incompatible.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="migration74.incompatible" class="sect1">
 <h2 class="title">Backward Incompatible Changes</h2>

 <div class="sect2" id="migration74.incompatible.core">
  <h3 class="title">PHP Core</h3>

  <div class="sect3" id="migration74.incompatible.core.non-array-access">
   <h4 class="title">Array-style access of non-arrays</h4>

   <p class="para">
    Trying to use values of type <span class="type"><a href="language.types.null.php" class="type null">null</a></span>, <span class="type"><a href="language.types.boolean.php" class="type bool">bool</a></span>,
    <span class="type"><a href="language.types.integer.php" class="type int">int</a></span>, <span class="type"><a href="language.types.float.php" class="type float">float</a></span> or <span class="type"><a href="language.types.resource.php" class="type resource">resource</a></span> as an
    array (such as <code class="literal">$null[&quot;key&quot;]</code>) will now generate a notice.
   </p>
  </div>

  <div class="sect3" id="migration74.incompatible.core.get-declared-classes">
   <h4 class="title"><span class="function"><a href="function.get-declared-classes.php" class="function">get_declared_classes()</a></span> function</h4>

   <p class="para">
    The <span class="function"><a href="function.get-declared-classes.php" class="function">get_declared_classes()</a></span> function no longer
    returns anonymous classes that have not been instantiated yet.
   </p>
  </div>

  <div class="sect3" id="migration74.incompatible.core.fn">
   <h4 class="title"><code class="literal">fn</code> keyword</h4>

   <p class="para">
    <code class="literal">fn</code> is now a reserved keyword. In particular,
    it can no longer be used as a function or class name.
    It can still be used as a method or class constant name.
   </p>
  </div>

  <div class="sect3" id="migration74.incompatible.core.php-tag">
   <h4 class="title"><code class="literal">&lt;?php</code> tag at end of file</h4>

   <p class="para">
    <code class="literal">&lt;?php</code> at the end of the file (without trailing newline)
    will now be interpreted as an opening PHP tag. Previously it was interpreted
    either as a short opening tag followed by literal <code class="literal">php</code> and
    resulted in a syntax error (with <code class="literal">short_open_tag=1</code>)
    or was interpreted as a literal <code class="literal">&lt;?php</code> string
    (with <code class="literal">short_open_tag=0</code>).
   </p>
  </div>

  <div class="sect3" id="migration74.incompatible.core.stream-wrappers">
   <h4 class="title">Stream wrappers</h4>

   <p class="para">
    When using include/require on a stream,
    <span class="methodname"><a href="streamwrapper.stream-set-option.php" class="methodname">streamWrapper::stream_set_option()</a></span>
    will be invoked with the <strong><code><a href="stream.constants.php#constant.stream-option-read-buffer">STREAM_OPTION_READ_BUFFER</a></code></strong> option.
    Custom stream wrapper implementations may need to implement the
    <span class="methodname"><a href="streamwrapper.stream-set-option.php" class="methodname">streamWrapper::stream_set_option()</a></span> method to
    avoid a warning (always returning <strong><code><a href="reserved.constants.php#constant.false">false</a></code></strong> is a sufficient implementation).
   </p>
  </div>

  <div class="sect3" id="migration74.incompatible.core.serialization">
   <h4 class="title">Serialization</h4>

   <p class="para">
    The <code class="literal">o</code> serialization format has been removed.
    As it is never produced by PHP, this may only break unserialization of
    manually crafted strings.
   </p>
  </div>

  <div class="sect3" id="migration74.incompatible.core.password-algorithm-constants">
   <h4 class="title">Password algorithm constants</h4>

   <p class="para">
    Password hashing algorithm identifiers are now nullable strings rather
    than integers.
   </p>

   <ul class="itemizedlist">
    <li class="listitem">
     <span class="simpara">
      <strong><code><a href="password.constants.php#constant.password-default">PASSWORD_DEFAULT</a></code></strong> was int 1; now is string &#039;2y&#039; (in PHP 7.4.0, 7.4.1, and 7.4.2 it was <strong><code><a href="reserved.constants.php#constant.null">null</a></code></strong>)
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      <strong><code><a href="password.constants.php#constant.password-bcrypt">PASSWORD_BCRYPT</a></code></strong> was int 1; now is string &#039;2y&#039;
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      <strong><code><a href="password.constants.php#constant.password-argon2i">PASSWORD_ARGON2I</a></code></strong> was int 2; now is string &#039;argon2i&#039;
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      <strong><code><a href="password.constants.php#constant.password-argon2id">PASSWORD_ARGON2ID</a></code></strong> was int 3; now is string &#039;argon2id&#039;
     </span>
    </li>
   </ul>

   <p class="para">
    Applications correctly using the constants PASSWORD_DEFAULT,
    PASSWORD_BCRYPT, PASSWORD_ARGON2I, and PASSWORD_ARGON2ID will continue to
    function correctly.
   </p>
  </div>

  <div class="sect3" id="migration74.incompatible.core.htmlentities">
   <h4 class="title"><span class="function"><a href="function.htmlentities.php" class="function">htmlentities()</a></span> function</h4>

   <p class="para">
    <span class="function"><a href="function.htmlentities.php" class="function">htmlentities()</a></span> will now raise a notice
    (instead of a strict standards warning) if it is used with
    an encoding for which only basic entity substitution is supported,
    in which case it is equivalent to <span class="function"><a href="function.htmlspecialchars.php" class="function">htmlspecialchars()</a></span>.
   </p>
  </div>

  <div class="sect3" id="migration74.incompatible.core.fread-fwrite">
   <h4 class="title"><span class="function"><a href="function.fread.php" class="function">fread()</a></span> and <span class="function"><a href="function.fwrite.php" class="function">fwrite()</a></span> function</h4>

   <p class="para">
    <span class="function"><a href="function.fread.php" class="function">fread()</a></span> and <span class="function"><a href="function.fwrite.php" class="function">fwrite()</a></span> will now
    return <strong><code><a href="reserved.constants.php#constant.false">false</a></code></strong> if the operation failed.
    Previously an empty string or 0 was returned.
    EAGAIN/EWOULDBLOCK are not considered failures.
   </p>
   <p class="para">
    These functions now also raise a notice on failure,
    such as when trying to write to a read-only file resource.
   </p>
  </div>

 </div>

 <div class="sect2" id="migration74.incompatible.bcmath">
  <h3 class="title">BCMath Arbitrary Precision Mathematics</h3>

  <p class="para">
   BCMath functions will now warn if a non well-formed number is passed, such
   as <code class="literal">&quot;32foo&quot;</code>. The argument will be interpreted as zero, as before.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.curl">
  <h3 class="title">CURL</h3>

  <p class="para">
   Attempting to serialize a <span class="classname"><a href="class.curlfile.php" class="classname">CURLFile</a></span> class will now
   generate an exception. Previously the exception was only thrown on unserialization.
  </p>
  <p class="para">
   Using <strong><code><a href="curl.constants.php#constant.curlpipe-http1">CURLPIPE_HTTP1</a></code></strong> is deprecated, and is no longer
   supported as of cURL 7.62.0.
  </p>
  <p class="para">
   The <code class="literal">$version</code> parameter of <span class="function"><a href="function.curl-version.php" class="function">curl_version()</a></span>
   is deprecated. If any value not equal to the default <strong><code><a href="curl.constants.php#constant.curlversion-now">CURLVERSION_NOW</a></code></strong>
   is passed, a warning is raised and the parameter is ignored.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.datetime">
  <h3 class="title">Date and Time</h3>

  <p class="para">
   Calling <span class="function"><a href="function.var-dump.php" class="function">var_dump()</a></span> or similar on a
   <span class="classname"><a href="class.datetime.php" class="classname">DateTime</a></span> or <span class="classname"><a href="class.datetimeimmutable.php" class="classname">DateTimeImmutable</a></span>
   instance will no longer leave behind accessible properties on the object.
  </p>
  <p class="para">
   Comparison of <span class="classname"><a href="class.dateinterval.php" class="classname">DateInterval</a></span> objects
   (using <code class="literal">==</code>, <code class="literal">&lt;</code>, and so on) will now generate
   a warning and always return <strong><code><a href="reserved.constants.php#constant.false">false</a></code></strong>. Previously all <span class="classname"><a href="class.dateinterval.php" class="classname">DateInterval</a></span>
   objects were considered equal, unless they had properties.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.intl">
  <h3 class="title">Intl</h3>

  <p class="para">
   The default parameter value of <span class="function"><a href="function.idn-to-ascii.php" class="function">idn_to_ascii()</a></span> and
   <span class="function"><a href="function.idn-to-utf8.php" class="function">idn_to_utf8()</a></span> is now <strong><code><a href="intl.constants.php#constant.intl-idna-variant-uts46">INTL_IDNA_VARIANT_UTS46</a></code></strong>
   instead of the deprecated <strong><code><a href="intl.constants.php#constant.intl-idna-variant-2003">INTL_IDNA_VARIANT_2003</a></code></strong>.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.mysqli">
  <h3 class="title">MySQLi</h3>

  <p class="para">
   The embedded server functionality has been removed. It was broken since
   at least PHP 7.0.
  </p>
  <p class="para">
   The undocumented <code class="literal">mysqli::$stat</code> property has been removed
   in favor of <span class="methodname"><a href="mysqli.stat.php" class="methodname">mysqli::stat()</a></span>.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.openssl">
  <h3 class="title">OpenSSL</h3>

  <p class="para">
   The <span class="function"><a href="function.openssl-random-pseudo-bytes.php" class="function">openssl_random_pseudo_bytes()</a></span> function will now
   throw an exception in error situations, similar to <span class="function"><a href="function.random-bytes.php" class="function">random_bytes()</a></span>.
   In particular, an <span class="classname"><a href="class.error.php" class="classname">Error</a></span> is thrown if the number of
   requested bytes is less than or equal to zero, and an <span class="classname"><a href="class.exception.php" class="classname">Exception</a></span>
   is thrown if sufficient randomness cannot be gathered.
   The <code class="literal">$crypto_strong</code> output argument is guaranteed to always
   be <strong><code><a href="reserved.constants.php#constant.true">true</a></code></strong> if the function does not throw, so explicitly checking it is not necessary.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.pcre">
  <h3 class="title">Regular Expressions (Perl-Compatible)</h3>

  <p class="para">
   When <strong><code><a href="pcre.constants.php#constant.preg-unmatched-as-null">PREG_UNMATCHED_AS_NULL</a></code></strong> mode is used, trailing
   unmatched capturing groups will now also be set to <strong><code><a href="reserved.constants.php#constant.null">null</a></code></strong> (or
   <code class="literal">[null, -1]</code> if offset capture is enabled).
   This means that the size of the <code class="literal">$matches</code> will always be the same.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.pdo">
  <h3 class="title">PHP Data Objects</h3>

  <p class="para">
   Attempting to serialize a <span class="classname"><a href="class.pdo.php" class="classname">PDO</a></span> or
   <span class="classname"><a href="class.pdostatement.php" class="classname">PDOStatement</a></span> instance will now generate
   an <span class="classname"><a href="class.exception.php" class="classname">Exception</a></span> rather than a <span class="classname"><a href="class.pdoexception.php" class="classname">PDOException</a></span>,
   consistent with other internal classes which do not support serialization.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.reflection">
  <h3 class="title">Reflection</h3>

  <p class="para">
   Reflection objects will now generate an exception if an attempt is made
   to serialize them. Serialization for reflection objects was never
   supported and resulted in corrupted reflection objects. It has been
   explicitly prohibited now.
  </p>

  <p class="para">
   The values of the class constant of <span class="classname"><a href="class.reflectionclassconstant.php" class="classname">ReflectionClassConstant</a></span>,
   <span class="classname"><a href="class.reflectionmethod.php" class="classname">ReflectionMethod</a></span> and <span class="classname"><a href="class.reflectionproperty.php" class="classname">ReflectionProperty</a></span>
   have changed.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.spl">
  <h3 class="title">Standard PHP Library (SPL)</h3>

  <p class="para">
   Calling <span class="function"><a href="function.get-object-vars.php" class="function">get_object_vars()</a></span> on an <span class="classname"><a href="class.arrayobject.php" class="classname">ArrayObject</a></span>
   instance will now always return the properties of the <span class="classname"><a href="class.arrayobject.php" class="classname">ArrayObject</a></span>
   itself (or a subclass). Previously it returned the values of the wrapped
   array/object unless the <strong><code><a href="class.arrayobject.php#arrayobject.constants.std-prop-list">ArrayObject::STD_PROP_LIST</a></code></strong>
   flag was specified.
  </p>
  <p class="para">
   Other affected operations are:
  </p>
  <ul class="itemizedlist">
   <li class="listitem">
    <span class="simpara">
     <span class="methodname"><strong>ReflectionObject::getProperties()</strong></span>
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     <span class="function"><a href="function.reset.php" class="function">reset()</a></span>, <span class="function"><a href="function.current.php" class="function">current()</a></span>, etc.
     Use <span class="interfacename"><a href="class.iterator.php" class="interfacename">Iterator</a></span> methods instead.
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     Potentially others working on object properties as a list,
     e.g. <span class="function"><a href="function.array-walk.php" class="function">array_walk()</a></span>.
    </span>
   </li>
  </ul>
  <p class="para">
   <code class="literal">(array)</code> casts are not affected. They will continue to
   return either the wrapped array, or the <span class="classname"><a href="class.arrayobject.php" class="classname">ArrayObject</a></span>
   properties, depending on whether the <strong><code><a href="class.arrayobject.php#arrayobject.constants.std-prop-list">ArrayObject::STD_PROP_LIST</a></code></strong>
   flag is used.
  </p>
  <p class="para">
   <span class="methodname"><a href="splpriorityqueue.setextractflags.php" class="methodname">SplPriorityQueue::setExtractFlags()</a></span> will throw
   an exception if zero is passed. Previously this would generate a recoverable
   fatal error on the next extraction operation.
  </p>
  <p class="para">
   <span class="classname"><a href="class.arrayobject.php" class="classname">ArrayObject</a></span>, <span class="classname"><a href="class.arrayiterator.php" class="classname">ArrayIterator</a></span>,
   <span class="classname"><a href="class.spldoublylinkedlist.php" class="classname">SplDoublyLinkedList</a></span> and <span class="classname"><a href="class.splobjectstorage.php" class="classname">SplObjectStorage</a></span>
   now support the <code class="literal">__serialize()</code> and <code class="literal">__unserialize()</code>
   mechanism in addition to the <span class="interfacename"><a href="class.serializable.php" class="interfacename">Serializable</a></span> interface.
   This means that serialization payloads created on older PHP versions can still be
   unserialized, but new payloads created by PHP 7.4 will not be understood by older versions.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.tokenizer">
  <h3 class="title">Tokenizer</h3>

  <p class="para">
   <span class="function"><a href="function.token-get-all.php" class="function">token_get_all()</a></span> will now emit a
   <strong><code><a href="tokens.php#constant.t-bad-character">T_BAD_CHARACTER</a></code></strong> token for unexpected
   characters instead of leaving behind holes in the token stream.
  </p>
 </div>

 <div class="sect2" id="migration74.incompatible.cookie-decode">
  <h3 class="title">Incoming Cookies</h3>

  <p class="para">
   As of PHP 7.4.11, the <em>names</em> of incoming cookies are no
   longer url-decoded for security reasons.
  </p>
 </div>

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