[doc-en] master: PHP 8.6 migration guide (#5900)

From: Date: Tue, 13 Oct 2026 17:01:09 +0000
Subject: [doc-en] master: PHP 8.6 migration guide (#5900)
Groups: php.doc.cvs 
Request: Send a blank email to doc-cvs+get-23841@lists.php.net to get a copy of this message
Author: Jordi Kroon (jordikroon) Committer: GitHub (web-flow) Pusher: jordikroon Date: 2026-10-13T19:01:05+02:00 Commit: https://github.com/php/doc-en/commit/894fa67ba030cd241a56d898869852c7b1a59c0a Raw diff: https://github.com/php/doc-en/commit/894fa67ba030cd241a56d898869852c7b1a59c0a.diff PHP 8.6 migration guide (#5900) * Added initial files for 8.6 migration * Document new classes & functions * Document deprecations * Document Windows changes * Document Constant changes * Document new features * Document php-src#c01c9d009c1db68a87dabd45b128f544913a63f2 Changed paths: A appendices/migration86.xml A appendices/migration86/constants.xml A appendices/migration86/deprecated.xml A appendices/migration86/incompatible.xml A appendices/migration86/new-classes.xml A appendices/migration86/new-features.xml A appendices/migration86/new-functions.xml A appendices/migration86/other-changes.xml A appendices/migration86/windows-support.xml M manual.xml Diff: diff --git a/appendices/migration86.xml b/appendices/migration86.xml new file mode 100644 index 000000000000..89cdef36774f --- /dev/null +++ b/appendices/migration86.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<appendix xml:id="migration86" xmlns="http://docbook.org/ns/docbook"> + <title>Migrating from PHP 8.5.x to PHP 8.6.x</title> + + <simpara> + This new minor version brings with it a number of + <link linkend="migration86.new-features">new features</link> and a + <link linkend="migration86.incompatible">few incompatibilities</link> + that should be tested for before switching PHP versions in production + environments. + </simpara> + + <simpara> + &manual.migration.seealso; + <link linkend="migration71">7.1.x</link>, + <link linkend="migration72">7.2.x</link>, + <link linkend="migration73">7.3.x</link>, + <link linkend="migration74">7.4.x</link>, + <link linkend="migration80">8.0.x</link>, + <link linkend="migration81">8.1.x</link>, + <link linkend="migration82">8.2.x</link>, + <link linkend="migration83">8.3.x</link>, + <link linkend="migration84">8.4.x</link>, + <link linkend="migration85">8.5.x</link>. + </simpara> + + &appendices.migration86.new-features; + &appendices.migration86.new-classes; + &appendices.migration86.new-functions; + &appendices.migration86.constants; + &appendices.migration86.incompatible; + &appendices.migration86.deprecated; + &appendices.migration86.other-changes; + &appendices.migration86.windows-support; + +</appendix> +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:t +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +indent-tabs-mode:nil +sgml-parent-document:nil +sgml-default-dtd-file:"~/.phpdoc/manual.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +End: +vim600: syn=xml fen fdm=syntax fdl=2 si +vim: et tw=78 syn=sgml +vi: ts=1 sw=1 +--> diff --git a/appendices/migration86/constants.xml b/appendices/migration86/constants.xml new file mode 100644 index 000000000000..c3d4ced715a0 --- /dev/null +++ b/appendices/migration86/constants.xml @@ -0,0 +1,187 @@ +<?xml version="1.0" encoding="utf-8"?> +<sect1 xml:id="migration86.constants"> + <title>New Global Constants</title> + + <sect2 xml:id="migration86.constants.core"> + <title>Core</title> + + <simplelist> + <member> + <constant>ARRAY_FILTER_USE_VALUE</constant> + </member> + <member> + <constant>STREAM_CRYPTO_STATUS_NONE</constant> + </member> + <member> + <constant>STREAM_CRYPTO_STATUS_WANT_READ</constant> + </member> + <member> + <constant>STREAM_CRYPTO_STATUS_WANT_WRITE</constant> + </member> + </simplelist> + </sect2> + + <sect2 xml:id="migration86.constants.curl"> + <title>cURL</title> + + <simplelist> + <member> + <constant>CURLINFO_SIZE_DELIVERED</constant> (libcurl >= 8.20.0) + </member> + <member> + <constant>CURLOPT_SEEKFUNCTION</constant> + </member> + <member> + <constant>CURL_SEEKFUNC_OK</constant> + </member> + <member> + <constant>CURL_SEEKFUNC_FAIL</constant> + </member> + <member> + <constant>CURL_SEEKFUNC_CANTSEEK</constant> + </member> + <member> + <constant>CURL_READFUNC_ABORT</constant> + </member> + </simplelist> + </sect2> + + <sect2 xml:id="migration86.constants.mysqli"> + <title>MySQLi</title> + + <simplelist> + <member> + <constant>MYSQLI_OPT_COMPRESS</constant> + </member> + </simplelist> + </sect2> + + <sect2 xml:id="migration86.constants.openssl"> + <title>OpenSSL</title> + + <simplelist> + <member><constant>OPENSSL_RSA_PSS_SALTLEN_DIGEST</constant></member> + <member><constant>OPENSSL_RSA_PSS_SALTLEN_AUTO</constant></member> + <member><constant>OPENSSL_RSA_PSS_SALTLEN_MAX</constant></member> + </simplelist> + </sect2> + + <sect2 xml:id="migration86.constants.sockets"> + <title>Sockets</title> + + <simplelist> + <member> + <constant>TCP_USER_TIMEOUT</constant> (Linux only) + </member> + <member> + <constant>AF_UNSPEC</constant> + </member> + <member> + <constant>EAI_BADFLAGS</constant> + </member> + <member> + <constant>EAI_NONAME</constant> + </member> + <member> + <constant>EAI_AGAIN</constant> + </member> + <member> + <constant>EAI_FAIL</constant> + </member> + <member> + <constant>EAI_NODATA</constant> + </member> + <member> + <constant>EAI_FAMILY</constant> + </member> + <member> + <constant>EAI_SOCKTYPE</constant> + </member> + <member> + <constant>EAI_SERVICE</constant> + </member> + <member> + <constant>EAI_ADDRFAMILY</constant> + </member> + <member> + <constant>EAI_SYSTEM</constant> + </member> + <member> + <constant>EAI_OVERFLOW</constant> + </member> + <member> + <constant>EAI_INPROGRESS</constant> + </member> + <member> + <constant>EAI_CANCELED</constant> + </member> + <member> + <constant>EAI_NOTCANCELED</constant> + </member> + <member> + <constant>EAI_ALLDONE</constant> + </member> + <member> + <constant>EAI_INTR</constant> + </member> + <member> + <constant>EAI_IDN_ENCODE</constant> + </member> + <member> + <constant>SO_DETACH_REUSEPORT_BPF</constant> (Linux only) + </member> + </simplelist> + </sect2> + + <sect2 xml:id="migration86.constants.sodium"> + <title>Sodium</title> + + <simplelist> + <member><constant>SODIUM_CRYPTO_IPCRYPT_BYTES</constant></member> + <member><constant>SODIUM_CRYPTO_IPCRYPT_KEYBYTES</constant></member> + <member><constant>SODIUM_CRYPTO_IPCRYPT_ND_KEYBYTES</constant></member> + <member><constant>SODIUM_CRYPTO_IPCRYPT_ND_TWEAKBYTES</constant></member> + <member><constant>SODIUM_CRYPTO_IPCRYPT_ND_INPUTBYTES</constant></member> + <member><constant>SODIUM_CRYPTO_IPCRYPT_ND_OUTPUTBYTES</constant></member> + <member><constant>SODIUM_CRYPTO_IPCRYPT_NDX_KEYBYTES</constant></member> + <member><constant>SODIUM_CRYPTO_IPCRYPT_NDX_TWEAKBYTES</constant></member> + <member><constant>SODIUM_CRYPTO_IPCRYPT_NDX_INPUTBYTES</constant></member> + <member><constant>SODIUM_CRYPTO_IPCRYPT_NDX_OUTPUTBYTES</constant></member> + <member><constant>SODIUM_CRYPTO_IPCRYPT_PFX_KEYBYTES</constant></member> + <member><constant>SODIUM_CRYPTO_IPCRYPT_PFX_BYTES</constant></member> + <member><constant>SODIUM_CRYPTO_KEM_PUBLICKEYBYTES</constant> (libsodium >= 1.0.22)</member> + <member><constant>SODIUM_CRYPTO_KEM_SECRETKEYBYTES</constant> (libsodium >= 1.0.22)</member> + <member><constant>SODIUM_CRYPTO_KEM_CIPHERTEXTBYTES</constant> (libsodium >= 1.0.22)</member> + <member><constant>SODIUM_CRYPTO_KEM_SHAREDSECRETBYTES</constant> (libsodium >= 1.0.22)</member> + <member><constant>SODIUM_CRYPTO_KEM_SEEDBYTES</constant> (libsodium >= 1.0.22)</member> + <member><constant>SODIUM_CRYPTO_KEM_KEYPAIRBYTES</constant> (libsodium >= 1.0.22)</member> + <member><constant>SODIUM_CRYPTO_KEM_MLKEM768_PUBLICKEYBYTES</constant> (libsodium >= 1.0.22)</member> + <member><constant>SODIUM_CRYPTO_KEM_MLKEM768_SECRETKEYBYTES</constant> (libsodium >= 1.0.22)</member> + <member><constant>SODIUM_CRYPTO_KEM_MLKEM768_CIPHERTEXTBYTES</constant> (libsodium >= 1.0.22)</member> + <member><constant>SODIUM_CRYPTO_KEM_MLKEM768_SHAREDSECRETBYTES</constant> (libsodium >= 1.0.22)</member> + <member><constant>SODIUM_CRYPTO_KEM_MLKEM768_SEEDBYTES</constant> (libsodium >= 1.0.22)</member> + <member><constant>SODIUM_CRYPTO_KEM_MLKEM768_KEYPAIRBYTES</constant> (libsodium >= 1.0.22)</member> + </simplelist> + </sect2> + +</sect1> +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:t +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +indent-tabs-mode:nil +sgml-parent-document:nil +sgml-default-dtd-file:"~/.phpdoc/manual.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +End: +vim600: syn=xml fen fdm=syntax fdl=2 si +vim: et tw=78 syn=sgml +vi: ts=1 sw=1 +--> diff --git a/appendices/migration86/deprecated.xml b/appendices/migration86/deprecated.xml new file mode 100644 index 000000000000..2ce6ce2a5322 --- /dev/null +++ b/appendices/migration86/deprecated.xml @@ -0,0 +1,612 @@ +<?xml version="1.0" encoding="utf-8"?> +<sect1 xml:id="migration86.deprecated"> + <title>Deprecated Features</title> + + <sect2 xml:id="migration86.deprecated.core"> + <title>PHP Core</title> + + <sect3 xml:id="migration86.deprecated.core.namespace-as-class-constant-name"> + <title>Using "namespace" as a class constant name</title> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_using_namespace_as_a_class_constant_name --> + + <simpara> + Declaring a <link linkend="language.oop5.constants">class constant</link> + named <literal>namespace</literal> is now deprecated. + <literal>namespace</literal> is a semi-reserved keyword, and the name is + being reserved for possible future syntax such as a + <literal>::namespace</literal> pseudo-constant analogous to + <literal>::class</literal>. + Methods and static properties named <literal>namespace</literal> are + not affected. + Rename the constant, for example to <literal>NAMESPACE_NAME</literal>. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.deprecated.core.return-in-finally"> + <title>Returning from a finally block</title> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_returning_from_a_finally_block --> + + <simpara> + Using the <literal>return</literal> statement inside a &finally; block + is now deprecated, and emits a compile-time deprecation notice. + Such a <literal>return</literal> silently discards an exception thrown + by, or overwrites the value returned from, the associated + <literal>try</literal> or <literal>catch</literal> block, so failures + vanish without a trace. + Move the <literal>return</literal> out of the <literal>finally</literal> + block instead; the same result can always be expressed without it. + </simpara> + + <informalexample> + <programlisting role="php"> +<![CDATA[ +<?php +function getConfig(): array +{ + try { + return loadConfig(); // throws if the file is missing + } finally { + return []; // Deprecated: the exception is gone, the caller just gets [] + } +} +]]> + </programlisting> + </informalexample> + + </sect3> + + <sect3 xml:id="migration86.deprecated.core.nullable-debuginfo-return-type"> + <title>Nullable return type for __debugInfo()</title> + + <simpara> + Declaring a return type of + <type class="union"><type>array</type><type>null</type></type> for + <link linkend="language.oop5.magic.debuginfo">__debugInfo()</link> is now + deprecated. + Returning &null; from this method was + <link linkend="migration85.deprecated.core.return-null-from-debuginfo">already + deprecated in PHP 8.5</link>, so the nullable return type no longer + describes valid behaviour. + Declare <type>array</type> instead. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.deprecated.core.return-value-from-constructor"> + <title>Returning values from __construct() and __destruct()</title> + <!-- RFC: https://wiki.php.net/rfc/deprecate-return-value-from-construct --> + + <simpara> + Returning a value from + <link linkend="language.oop5.decon.constructor">__construct()</link> or + <link linkend="language.oop5.decon.destructor">__destruct()</link> is now + deprecated, and emits a compile-time deprecation notice. + These methods cannot declare a return type, and their return value can + never be observed during normal use, which made returning a value + confusing at best. + Using <literal>return;</literal> without a value to skip the remaining + logic is still allowed, as is calling these methods manually. + </simpara> + + <simpara> + For the same reason, using <literal>yield</literal> to make + <link linkend="language.oop5.decon.constructor">__construct()</link> or + <link linkend="language.oop5.decon.destructor">__destruct()</link> a + <link linkend="language.generators">generator</link> is now deprecated. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.deprecated.core.function-named-readonly"> + <title>Naming a function readonly</title> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_the_possibility_to_name_a_function_readonly --> + + <simpara> + Declaring a function named <literal>readonly</literal> is now deprecated. + <link linkend="language.oop5.properties.readonly-properties">readonly</link> + is a reserved keyword; a lexer exception was added in PHP 8.1 solely to + keep an existing WordPress function of that name working, and no other + keyword in PHP receives such special treatment. + Rename the function. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.deprecated.core.reserved-identifiers"> + <title>Using let, is, or _ as an identifier</title> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_using_let_as_an_identifier --> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_using_is_as_an_identifier --> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_using_as_a_constant_and_compile_time_alias --> + <!-- Not listed in UPGRADING; implemented in php-src commits 0beb2a99d3 and 938a3110bf on the PHP-8.6 branch --> + + <simpara> + Using <literal>let</literal> or <literal>is</literal> as the name of a + class, interface, trait, enum, function, or constant (including via + <function>define</function>) is now deprecated, as is using either as + the alias in a <function>class_alias</function> call or in a + <literal>use</literal>, <literal>use function</literal>, or + <literal>use const</literal> declaration. + The names are being reserved as keywords for potential future features: + <literal>let</literal> for block scoping and <literal>is</literal> for + pattern matching. + Rename the affected symbols. + </simpara> + + <simpara> + The + <link linkend="migration84.deprecated.core.underscore-class-name">deprecation + of <literal>_</literal> as a class name in PHP 8.4</link> is extended to + constants: declaring a constant named <literal>_</literal> with + <literal>const</literal> or <function>define</function>, and aliasing a + class or constant to <literal>_</literal> in a <literal>use</literal> + declaration, are now deprecated. + Functions named <literal>_</literal>, including the + <function>_</function> alias of <function>gettext</function>, are not + affected. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.deprecated.core.define-case-insensitive"> + <title>Third argument to define()</title> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_define_with_case_insensitive_being_specified --> + + <simpara> + Passing the <parameter>case_insensitive</parameter> argument to + <function>define</function> is now deprecated. + Case-insensitive constants were removed in PHP 8.0, since when the + argument has been ignored. + Explicitly passing &false; now emits a deprecation notice. + Passing &true; continues to emit a warning, whose message now states + that this will become an error in PHP 9.0. + Omit the argument. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.deprecated.core.is-a-with-string"> + <title>is_a() and is_subclass_of() with a string when allow_string is false</title> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_is_a_with_string_when_allow_string_is_false --> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_is_subclass_of_with_string_when_allow_string_is_false --> + + <simpara> + Calling <function>is_a</function> or <function>is_subclass_of</function> + with a string as the first argument while + <parameter>allow_string</parameter> is &false; is now deprecated. + In that case the functions always return &false;, even when the class + is already loaded, so such a call indicates a bug. + To avoid triggering autoloading, check <function>class_exists</function> + with autoloading disabled first, and then call the function with + <parameter>allow_string</parameter> set to &true;. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.deprecated.core.metaphone"> + <title>metaphone()</title> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_metaphone_function --> + + <simpara> + The <function>metaphone</function> function is now deprecated. + It implements the original 1990 Metaphone algorithm, which is limited to + English pronunciation rules and has long been superseded by Double + Metaphone and Metaphone 3. + Phonetic algorithms are language-specific and frequently updated, so + they are better served by a userland library; use one instead. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.deprecated.core.php-filter-max-filter-count"> + <title>More than 16 filters in a php://filter URL</title> + <!-- RFC: https://wiki.php.net/rfc/limit-maximum-number-of-filter-chains --> + + <simpara> + Using more than 16 filters in a + <link linkend="wrappers.php">php://filter</link> URL without configuring + the <literal>filter.max_filter_count</literal> stream context option now + emits a deprecation notice. + Long filter chains have no known legitimate use, but are the basis of + a class of attacks that turn a local file inclusion or an arbitrary file + read into remote code execution. + When <literal>filter.max_filter_count</literal> is set explicitly, + exceeding it is already an error: opening the stream fails with a + warning. + </simpara> + + <simpara> + Code that needs more filters should either add them with + <function>stream_filter_append</function> or + <function>stream_filter_prepend</function>, which are not limited, or + raise the limit through the context option, for example globally with + <function>stream_context_set_default</function>. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.deprecated.core.passing-objects-as-arrays"> + <title>Passing objects to array_walk(), array_walk_recursive(), and http_build_query()</title> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_for_array_parameter_of_array_walk_and_array_walk_recursive --> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_for_data_parameter_of_http_build_query --> + + <simpara> + Passing an object as the <parameter>array</parameter> argument to + <function>array_walk</function> or + <function>array_walk_recursive</function> is now deprecated. + A small number of functions silently interpret an object as the array + of its visible properties. + Modifying such properties through a by-reference callback violates + <link linkend="language.oop5.properties.readonly-properties">readonly</link> + semantics and can corrupt enum cases, and + <function>array_walk_recursive</function> does not recurse into nested + objects anyway. + Call <function>get_object_vars</function> on the object first and pass + the resulting array. + </simpara> + + <simpara> + Passing an object as the <parameter>data</parameter> argument to + <function>http_build_query</function> is now deprecated. + Objects encountered as values within <parameter>data</parameter> now + also emit a deprecation notice when they are interpreted as arrays. + Treating objects as arrays has been a recurring source of confusion, + in particular for <interfacename>Stringable</interfacename> objects, + which users expect to be converted to a string instead. + Convert objects to arrays with <function>get_object_vars</function>, + recursively if necessary, before calling the function. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.deprecated.core.type-function-aliases"> + <title>is_double(), is_long(), is_integer(), and doubleval()</title> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_is_double --> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_is_integer --> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_is_long --> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_doubleval --> + + <para> + Following the + <link linkend="migration85.deprecated.core.non-canonical-cast-names">deprecation + of the non-canonical cast names in PHP 8.5</link>, the function aliases + that carry the same outdated type names are now deprecated. + They behave identically to their canonical counterparts, which should + be used instead: + + <simplelist> + <member><function>is_double</function> => <function>is_float</function></member> + <member><function>is_long</function> => <function>is_int</function></member> + <member><function>is_integer</function> => <function>is_int</function></member> + <member><function>doubleval</function> => <function>floatval</function></member> + </simplelist> + </para> + + </sect3> + + <sect3 xml:id="migration86.deprecated.core.locale-string-comparison"> + <title>strcoll() and SORT_LOCALE_STRING</title> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_strcoll --> + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_sort_locale_string_flag_for_sort_functions --> + + <simpara> + The <function>strcoll</function> function is now deprecated. + It compares strings according to the <literal>LC_COLLATE</literal> + setting of the current locale, which is global process state set via + <function>setlocale</function> that any library can change, it is not + binary safe unlike every other string comparison function, and some + locales do not implement correct collation rules. + Use <methodname>Collator::compare</methodname> from the + <link linkend="book.intl">intl</link> extension instead, which is + accurate and has up-to-date collation rules. + </simpara> + + <para> + The <constant>SORT_LOCALE_STRING</constant> flag of the sort functions + is now deprecated for the same reasons, as it sorts using + <function>strcoll</function>. + Use one of the following methods of the + <classname>Collator</classname> class instead: + + <simplelist> + <member><methodname>Collator::sort</methodname></member> + <member><methodname>Collator::asort</methodname></member> + <member><methodname>Collator::sortWithSortKeys</methodname></member> + </simplelist> + </para> + + </sect3> + + </sect2> + + <sect2 xml:id="migration86.deprecated.bzip2"> + <title>Bzip2</title> + + <simpara> + Passing an object as the parameters of the + <link linkend="filters.compression">bzip2.compress and + bzip2.decompress</link> stream filters is now deprecated, as only an + associative array is documented and supported. + Call <function>get_object_vars</function> on the object first and pass + the resulting array. + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_as_parameters_to_the_bzip2decompress_and_bzip2compress_stream_filters --> + </simpara> + + </sect2> + + <sect2 xml:id="migration86.deprecated.gmp"> + <title>GMP</title> + + <simpara> + The shift (<literal>&lt;&lt;</literal>, <literal>&gt;&gt;</literal>) and + exponentiation (<literal>**</literal>) operators on + <classname>GMP</classname> objects now emit a deprecation notice when the + right operand is a <type>float</type> whose conversion to + <type>int</type> loses precision, consistent with the deprecation of + implicit lossy float to int conversions elsewhere in the language. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.deprecated.mbstring"> + <title>MBString</title> + + <para> + The mbregex functions have been deprecated, because the underlying + Oniguruma library is no longer maintained; its maintenance ended in + April 2025. + The functions will be removed in PHP 9.0. + For most use cases the <link linkend="book.pcre">PCRE</link> functions + with the <literal>u</literal> modifier are a suitable replacement. + The affected functions are: + <!-- RFC: https://wiki.php.net/rfc/eol-oniguruma --> + + <simplelist> + <member><function>mb_ereg</function></member> + <member><function>mb_ereg_match</function></member> + <member><function>mb_ereg_replace</function></member> + <member><function>mb_ereg_replace_callback</function></member> + <member><function>mb_ereg_search</function></member> + <member><function>mb_ereg_search_getpos</function></member> + <member><function>mb_ereg_search_getregs</function></member> + <member><function>mb_ereg_search_init</function></member> + <member><function>mb_ereg_search_pos</function></member> + <member><function>mb_ereg_search_regs</function></member> + <member><function>mb_ereg_search_setpos</function></member> + <member><function>mb_eregi</function></member> + <member><function>mb_eregi_replace</function></member> + <member><function>mb_regex_encoding</function></member> + <member><function>mb_regex_set_options</function></member> + <member><function>mb_split</function></member> + </simplelist> + </para> + + <simpara> + The <constant>MB_ONIGURUMA_VERSION</constant> constant and the + <link linkend="ini.mbstring.regex-retry-limit">mbstring.regex_retry_limit</link> + and + <link linkend="ini.mbstring.regex-stack-limit">mbstring.regex_stack_limit</link> + INI directives are deprecated along with them. + </simpara> + + <simpara> + Passing an object as the <parameter>vars</parameter> argument to + <function>mb_convert_variables</function> is now deprecated, as objects + are silently interpreted as the array of their visible properties. + Call <function>get_object_vars</function> on the object first, or use + <function>mb_convert_encoding</function>, which converts arrays + recursively and returns the result instead of modifying its argument + in place. + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_for_vars_parameter_of_mb_convert_variables --> + </simpara> + + </sect2> + + <sect2 xml:id="migration86.deprecated.mysqli"> + <title>MySQLi</title> + + <simpara> + The <function>mysqli_get_charset</function> function and the + <methodname>mysqli::get_charset</methodname> method are now deprecated, + without replacement. + They expose internal implementation details of the character set that + have been meaningless since the switch to mysqlnd; in particular the + reported collation does not correspond to the collation defined by the + server. + To get the name of the current character set, use + <function>mysqli_character_set_name</function> or + <methodname>mysqli::character_set_name</methodname>. + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_mysqli_get_charset --> + </simpara> + + <simpara> + The <function>mysqli_stmt_init</function> function and the + <methodname>mysqli::stmt_init</methodname> method are now deprecated. + They create an empty statement object that still has to be prepared + before use, and are a source of statement objects left in an + inconsistent state. + Use <function>mysqli_prepare</function> or + <methodname>mysqli::prepare</methodname> instead, which prepare the + statement in one step. + For the same reason, calling the + <methodname>mysqli_stmt::__construct</methodname> constructor without the + <parameter>query</parameter> parameter is now deprecated; pass the query + to the constructor instead. + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_mysqlistmt_init --> + </simpara> + + </sect2> + + <sect2 xml:id="migration86.deprecated.reflection"> + <title>Reflection</title> + + <simpara> + Calling <methodname>ReflectionProperty::setValue</methodname> or + <methodname>ReflectionProperty::setRawValue</methodname> with an object + that is not an instance of the class on which the property was declared + is now deprecated. + Unlike the other <classname>ReflectionProperty</classname> methods, which + throw for such objects, these methods silently set a property on the + unrelated object, which is no better than a normal assignment and + conceptually wrong. + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_reflectionpropertysetvalue_and_reflectionpropertysetrawvalue_with_wrong_types --> + </simpara> + + <simpara> + Passing an object to <methodname>ReflectionMethod::invoke</methodname> or + <methodname>ReflectionMethod::invokeArgs</methodname> when invoking a + static method is now deprecated. + Static methods have no <varname>$this</varname>, so the object was + ignored entirely and never validated. + Pass &null; instead. + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_reflectionmethodinvoke_and_reflectionmethodinvokeargs_with_objects_for_static_methods --> + </simpara> + + </sect2> + + <sect2 xml:id="migration86.deprecated.session"> + <title>Session</title> + + <simpara> + Passing an object that does not implement both the + <methodname>SessionIdInterface::create_sid</methodname> and + <methodname>SessionUpdateTimestampHandlerInterface::validateId</methodname> + methods to <function>session_set_save_handler</function> is now + deprecated, regardless of which interfaces the object declares. + These methods are required for a save handler to behave correctly under + <link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>, + which is + <link linkend="migration86.incompatible.session">enabled by default as of + PHP 8.6</link> and mitigates session fixation. + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_passing_a_sessionhandler_object_to_session_set_save_handler_which_does_not_contain_the_create_sid_and_validateid --> + </simpara> + + <simpara> + Accordingly, a deprecation notice is now emitted when a class implements + <interfacename>SessionHandlerInterface</interfacename> without defining + the <methodname>SessionIdInterface::create_sid</methodname> or + <methodname>SessionUpdateTimestampHandlerInterface::validateId</methodname> + methods. + In PHP 9.0 these methods will be moved from + <interfacename>SessionIdInterface</interfacename> and + <interfacename>SessionUpdateTimestampHandlerInterface</interfacename> into + <interfacename>SessionHandlerInterface</interfacename>, where they will be + required. + Implement both methods on custom save handlers now. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.deprecated.spl"> + <title>SPL</title> + + <simpara> + The <function>spl_classes</function> function is now deprecated. + No other extension exposes such a function, and the Reflection extension + is always available. + Use <methodname>ReflectionExtension::getClassNames</methodname> instead. + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_spl_classes --> + </simpara> + + <simpara> + The <function>spl_object_hash</function> function is now deprecated. + Since PHP 8.1 its return value has been nothing more than a reformatted + <function>spl_object_id</function>, and the name is misleading as the + value is not derived from the contents of the object. + The string form is also error-prone: two hashes can compare loosely equal + because both are numeric strings. + Use <function>spl_object_id</function> instead. + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_spl_object_hash --> + </simpara> + + <para> + The following <classname>ArrayIterator</classname> methods are now + deprecated. + They only exist because <classname>ArrayIterator</classname> historically + shared its implementation with <classname>ArrayObject</classname>; most + of them make little sense on an iterator and prevent optimizing its + implementation. + The corresponding <classname>ArrayObject</classname> methods are not + deprecated. + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_arrayiterator_methods_that_inherit_arrayobject_implementation --> + + <simplelist> + <member><methodname>ArrayIterator::getFlags</methodname></member> + <member><methodname>ArrayIterator::setFlags</methodname></member> + <member><methodname>ArrayIterator::asort</methodname></member> + <member><methodname>ArrayIterator::ksort</methodname></member> + <member><methodname>ArrayIterator::uasort</methodname></member> + <member><methodname>ArrayIterator::uksort</methodname></member> + <member><methodname>ArrayIterator::natsort</methodname></member> + <member><methodname>ArrayIterator::natcasesort</methodname></member> + <member><methodname>ArrayIterator::unserialize</methodname></member> + <member><methodname>ArrayIterator::serialize</methodname></member> + </simplelist> + </para> + + <para> + The CSV methods of <classname>SplFileObject</classname> are now + deprecated. + Their historical design inconsistencies, further exposed by named + arguments, have made them increasingly difficult to maintain, and CSV + handling does not naturally belong in <classname>SplFileObject</classname>. + Use <function>fgetcsv</function> and <function>fputcsv</function> on a + stream instead. + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_splfileobject_csv_methods --> + + <simplelist> + <member><methodname>SplFileObject::fgetcsv</methodname></member> + <member><methodname>SplFileObject::fputcsv</methodname></member> + <member><methodname>SplFileObject::setCsvControl</methodname></member> + <member><methodname>SplFileObject::getCsvControl</methodname></member> + </simplelist> + </para> + + </sect2> + + <sect2 xml:id="migration86.deprecated.zlib"> + <title>Zlib</title> + + <simpara> + Passing an object as the parameters of the + <link linkend="filters.compression">zlib.deflate and zlib.inflate</link> + stream filters is now deprecated, as only an associative array is + documented and supported. + Call <function>get_object_vars</function> on the object first and pass + the resulting array. + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_as_parameters_to_the_zlibinflate_and_zlibdeflate_stream_filters --> + </simpara> + + <simpara> + Passing an object as the <parameter>options</parameter> argument to + <function>deflate_init</function> or <function>inflate_init</function> + is now deprecated, as objects are silently interpreted as the array of + their visible properties. + Call <function>get_object_vars</function> on the object first and pass + the resulting array. + <!-- RFC: https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_for_options_parameter_of_deflate_init_and_inflate_init --> + </simpara> + + </sect2> + +</sect1> +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:t +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +indent-tabs-mode:nil +sgml-parent-document:nil +sgml-default-dtd-file:"~/.phpdoc/manual.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +End: +vim600: syn=xml fen fdm=syntax fdl=2 si +vim: et tw=78 syn=sgml +vi: ts=1 sw=1 +--> diff --git a/appendices/migration86/incompatible.xml b/appendices/migration86/incompatible.xml new file mode 100644 index 000000000000..bb64e35ce4cf --- /dev/null +++ b/appendices/migration86/incompatible.xml @@ -0,0 +1,893 @@ +<?xml version="1.0" encoding="utf-8"?> +<sect1 xml:id="migration86.incompatible" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>Backward Incompatible Changes</title> + + <sect2 xml:id="migration86.incompatible.core"> + <title>PHP Core</title> + + <sect3 xml:id="migration86.incompatible.core.foreach-by-reference"> + <title>By-reference foreach after array compaction</title> + + <simpara> + By-reference <link linkend="control-structures.foreach">foreach</link> + loops may now visit previously + skipped elements after array compaction. + Internal pointers on deleted elements now move to the next surviving + element during copy-on-write. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.incompatible.core.magic-property-isset"> + <title>Null coalescing and <function>empty</function> on magic properties</title> + + <simpara> + <literal>??</literal> and <function>empty</function> on a magic property + no longer call <link linkend="object.get">__get()</link> when + <link linkend="object.isset">__isset()</link> has materialized the + property by writing into the property table. + The freshly-written value is returned directly. + <function>isset</function> applied directly to the property is unaffected; + nested forms such as <literal>isset($o-&gt;p['k'])</literal> follow the same + path as <literal>??</literal>. + </simpara> + + <informalexample> + <programlisting role="php"> +<![CDATA[ +<?php +#[\AllowDynamicProperties] +class Example +{ + public function __isset(string $name): bool + { + $this->$name = 'from __isset()'; + return true; + } + + public function __get(string $name): string + { + return 'from __get()'; + } +} + +$example = new Example(); +var_dump($example->foo ?? 'default'); +// As of PHP 8.6.0: string(14) "from __isset()" +// Prior to PHP 8.6.0: string(12) "from __get()" +]]> + </programlisting> + </informalexample> + + </sect3> + + <sect3 xml:id="migration86.incompatible.core.array-intersect"> + <title>String conversion in <function>array_intersect</function></title> + + <simpara> + <function>array_intersect</function> with at least two arrays now converts + values to strings while scanning its inputs instead of during sort + comparisons. + This can change the number and order of conversion warnings and + <link linkend="object.tostring">__toString()</link> calls, which conversion + exception is reached, and the result for stateful + <link linkend="object.tostring">__toString()</link> implementations. + Argument types are validated before checking for empty arrays or + converting values, so an invalid later argument can suppress conversion + side effects from earlier arrays. + Values are not converted if any input array is empty. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.incompatible.core.trim-form-feed"> + <title>Form feed trimmed by default</title> + + <simpara> + Form feed (<literal>\f</literal>) is now added to the default trimmed + characters of <function>trim</function>, <function>rtrim</function> and + <function>ltrim</function>. + <!-- RFC: https://wiki.php.net/rfc/trim_form_feed --> + </simpara> + + <informalexample> + <programlisting role="php"> +<![CDATA[ +<?php +var_dump(trim("\f hello \f")); +// As of PHP 8.6.0: string(5) "hello" +// Prior to PHP 8.6.0: string(9) "\f hello \f" +]]> + </programlisting> + </informalexample> + + </sect3> + + <sect3 xml:id="migration86.incompatible.core.new-value-errors"> + <title>New errors for invalid arguments</title> + + <para> + The following functions now raise a + <exceptionname>ValueError</exceptionname> when an invalid flag or mode + value is passed: + + <simplelist> + <member><function>array_filter</function> (<parameter>mode</parameter>)</member> + <member><function>array_change_key_case</function> (<parameter>case</parameter>)</member> + <member><function>pathinfo</function> (<parameter>flags</parameter>)</member> + <member><function>scandir</function> (<parameter>sorting_order</parameter>)</member> + </simplelist> + </para> + + <para> + The following functions now raise a + <exceptionname>ValueError</exceptionname> when the given argument contains + <literal>NUL</literal> bytes: + + <simplelist> + <member><function>getenv</function> and <function>putenv</function> (first argument)</member> + <member><function>dl</function> (<parameter>extension_filename</parameter>)</member> + <member><function>openlog</function> (<parameter>prefix</parameter>)</member> + <member><function>parse_str</function> (<parameter>string</parameter>)</member> + <member><function>proc_open</function> (<parameter>cwd</parameter>)</member> + </simplelist> + </para> + + <para> + The following functions now raise a + <exceptionname>ValueError</exceptionname> for out-of-range values instead + of silently clamping them or allowing them to overflow: + + <simplelist> + <member> + <function>number_format</function>, when <parameter>decimals</parameter> + is outside the integer range. + </member> + <member> + <function>sleep</function>, when <parameter>seconds</parameter> is + greater than <literal>UINT_MAX</literal>, or + <literal>UINT_MAX / 1000</literal> on Windows. + </member> + <member> + <function>usleep</function>, when <parameter>microseconds</parameter> is + greater than <literal>UINT_MAX</literal>. + </member> + </simplelist> + </para> + + <simpara> + <function>linkinfo</function> now raises a + <exceptionname>ValueError</exceptionname> when the + <parameter>path</parameter> argument is empty. + </simpara> + + <simpara> + <function>setlocale</function> now raises a + <exceptionname>ValueError</exceptionname> when a locale name contains + <literal>NUL</literal> bytes, instead of silently truncating it. + Arrays are now accepted only for the <parameter>locales</parameter> + argument. + Passing an array as a later variadic locale argument now throws a + <exceptionname>TypeError</exceptionname>. + Passing any additional locale arguments when + <parameter>locales</parameter> is an array now throws an + <exceptionname>ArgumentCountError</exceptionname>. + </simpara> + + <para> + The following functions now raise a + <exceptionname>ValueError</exceptionname> when the + <parameter>filename</parameter> argument contains <literal>NUL</literal> + bytes: + + <simplelist> + <member><function>fileperms</function></member> + <member><function>fileinode</function></member> + <member><function>filesize</function></member> + <member><function>fileowner</function></member> + <member><function>filegroup</function></member> + <member><function>fileatime</function></member> + <member><function>filemtime</function></member> + <member><function>filectime</function></member> + <member><function>filetype</function></member> + <member><function>is_writable</function></member> + <member><function>is_readable</function></member> + <member><function>is_executable</function></member> + <member><function>is_file</function></member> + <member><function>is_dir</function></member> + <member><function>is_link</function></member> + <member><function>file_exists</function></member> + <member><function>lstat</function></member> + <member><function>stat</function></member> + </simplelist> + </para> + + </sect3> + + <sect3 xml:id="migration86.incompatible.core.imprecise-number-conversion"> + <title>Notice on imprecise number conversion</title> + + <simpara> + <function>base_convert</function>, <function>bindec</function>, + <function>hexdec</function> and <function>octdec</function> now raise a + notice when they cannot precisely convert the given number. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.incompatible.core.unpack-endianness"> + <title>Endianness modifiers in <function>unpack</function> format names</title> + + <simpara> + <function>unpack</function> now reads a <literal>&lt;</literal> or + <literal>&gt;</literal> immediately following a format code as an + endianness modifier rather than as the first character of the element + name. + Formats such as <literal>"s&lt;value"</literal> now produce the key + <literal>"value"</literal> instead of <literal>"&lt;value"</literal>, and + <literal>"C&gt;name"</literal> raises a + <exceptionname>ValueError</exceptionname> because the <literal>C</literal> + format code accepts no endianness modifier. + A name starting with these characters is unaffected when a repeater + precedes it, as in <literal>"s1&lt;value"</literal>. + See also the + <link linkend="migration86.new-features.core.pack-unpack-endianness">new + endianness modifiers</link>. + <!-- RFC: https://wiki.php.net/rfc/pack-unpack-endianness-signed-integers-support --> + </simpara> + + <informalexample> + <programlisting role="php"> +<![CDATA[ +<?php +var_dump(unpack('s<value', "\x01\x00")); +// As of PHP 8.6.0: ["value" => 1] +// Prior to PHP 8.6.0: ["<value" => 1] +]]> + </programlisting> + </informalexample> + + </sect3> + + </sect2> + + <sect2 xml:id="migration86.incompatible.com"> + <title>COM</title> + + <simpara> + It is no longer possible to clone <classname>variant</classname> objects, + because the cloning behavior was ill-defined. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.curl"> + <title>cURL</title> + + <simpara> + The callback registered with <constant>CURLOPT_READFUNCTION</constant> now + throws a <exceptionname>ValueError</exceptionname> when returning an + integer other than <literal>0</literal>, + <constant>CURL_READFUNC_ABORT</constant> or + <constant>CURL_READFUNC_PAUSE</constant>. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.dom"> + <title>DOM</title> + + <simpara> + Properties previously documented as read-only (e.g. + <property>DOMNode::$nodeType</property>, + <property>DOMDocument::$xmlEncoding</property>, + <property>DOMEntity::$actualEncoding</property>, + <property>DOMEntity::$encoding</property>, + <property>DOMEntity::$version</property>) are now declared with + <link linkend="language.oop5.visibility-members-aviz">asymmetric + visibility</link> (<code>public private(set)</code>). + Attempts to write to them from outside the class now raise + <quote>Cannot modify private(set) property <replaceable>class</replaceable>::$<replaceable>prop</replaceable> from global scope</quote> + instead of the prior readonly modification error. + <methodname>ReflectionProperty::isWritable</methodname> also reports these + properties accurately. + </simpara> + + <simpara> + Array access on <classname>Dom\DtdNamedNodeMap</classname> objects now + returns &null; for negative integer indexes instead of returning the first + node, and raises a <exceptionname>ValueError</exceptionname> when the + integer index is greater than <constant>PHP_INT_MAX</constant> instead of + overflowing to a smaller index. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.ftp"> + <title>FTP</title> + + <simpara> + <function>ftp_nb_fget</function>, <function>ftp_nb_fput</function>, + <function>ftp_nb_get</function> and <function>ftp_nb_put</function> now + throw an <exceptionname>Error</exceptionname> when the connection is + already transferring, instead of emitting a warning and returning &false;. + <function>ftp_close</function> already throws on the same condition. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.gd"> + <title>GD</title> + + <simpara> + <function>imagesetstyle</function>, <function>imagefilter</function> and + <function>imagecrop</function> filter the types and values of their array + arguments and raise a <exceptionname>TypeError</exceptionname> or + <exceptionname>ValueError</exceptionname> accordingly. + </simpara> + + <simpara> + <function>imageaffinematrixget</function> now enforces the documented + <type class="union"><type>array</type><type>float</type></type> type for + the <parameter>options</parameter> parameter, including the corresponding + weak and strict typing behavior. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.gmp"> + <title>GMP</title> + + <simpara> + <function>gmp_fact</function> now throws a + <exceptionname>ValueError</exceptionname> if <parameter>num</parameter> + does not fit into an unsigned long. + </simpara> + + <simpara> + <function>gmp_pow</function>, <function>gmp_binomial</function>, + <function>gmp_root</function> and <function>gmp_rootrem</function> now + throw a <exceptionname>ValueError</exceptionname> if their second argument + does not fit into an unsigned long. + </simpara> + + <simpara> + The shift (<literal>&lt;&lt;</literal>, <literal>&gt;&gt;</literal>) and + exponentiation (<literal>**</literal>) operators on + <classname>GMP</classname> objects now throw a + <exceptionname>ValueError</exceptionname> when <classname>GMP</classname> + right operands are outside the unsigned long range, instead of silently + truncating them. + </simpara> + + <simpara> + <classname>GMP</classname> integer string parsing now throws a + <exceptionname>ValueError</exceptionname> for strings containing + <literal>NUL</literal> bytes, instead of silently truncating them. + </simpara> + + <simpara> + The message of the <exceptionname>DivisionByZeroError</exceptionname> + raised by <function>gmp_powm</function> on modulo by zero now includes the + function name and argument index (<parameter>modulus</parameter>). + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.intl"> + <title>Intl</title> + + <simpara> + Passing a non-stringable object as a time zone to Intl + <acronym>API</acronym>s that accept time zone objects or strings now + raises a <exceptionname>TypeError</exceptionname> instead of an + <exceptionname>Error</exceptionname>. + </simpara> + + <simpara> + <methodname>IntlIterator::current</methodname> now returns &null; when + called before the iterator is positioned, or after the iterator becomes + invalid, instead of exposing an undefined value. + </simpara> + + <simpara> + <methodname>IntlBreakIterator::getLocale</methodname> now raises a + <exceptionname>ValueError</exceptionname> when the type is neither + <constant>Locale::ACTUAL_LOCALE</constant> nor + <constant>Locale::VALID_LOCALE</constant> instead of returning &false;. + </simpara> + + <simpara> + <methodname>MessageFormatter::parse</methodname> and + <methodname>MessageFormatter::parseMessage</methodname> now return + <constant>PHP_INT_MIN</constant> as <type>int</type>, rather than + <type>float</type>, on 64-bit platforms when parsing integer values. + </simpara> + + <simpara> + The <parameter>type</parameter> parameter of + <methodname>IntlBreakIterator::getPartsIterator</methodname> has been + changed from <type>string</type> to <type>int</type> to match the + underlying implementation. + </simpara> + + <simpara> + <methodname>UConverter::transcode</methodname> now rejects + <literal>from_subst</literal> and <literal>to_subst</literal> option values + longer than 127 bytes instead of silently truncating the length before + passing it to <acronym>ICU</acronym>. + </simpara> + + <simpara> + <methodname>ResourceBundle::get</methodname> and + <function>resourcebundle_get</function> now report fallback-disabled + resource lookups with + <quote>without fallback to <replaceable>locale</replaceable></quote> + instead of the malformed + <quote>without fallback from to <replaceable>locale</replaceable></quote>. + </simpara> + + <simpara> + <methodname>IntlDateFormatter::parse</methodname>/<function>datefmt_parse</function> + and + <methodname>IntlDateFormatter::localtime</methodname>/<function>datefmt_localtime</function> + now raise a <exceptionname>TypeError</exceptionname> when the + <parameter>offset</parameter> argument is not of type <type>int</type> + instead of silently converting the value. + </simpara> + + <simpara> + <methodname>Collator::sort</methodname>, + <function>collator_sort</function>, + <methodname>Collator::asort</methodname>, and + <function>collator_asort</function> now report <acronym>UTF-8</acronym>/<acronym>UTF-16</acronym> conversion + failures during comparison through the intl error mechanism and return + &false;. + With <link linkend="ini.intl.use-exceptions">intl.use_exceptions</link> + enabled, these failures throw an <exceptionname>IntlException</exceptionname>. + Previously, these paths emitted a warning and compared the value as an + empty string. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.mbstring"> + <title>MBString</title> + + <simpara> + Unicode data tables have been updated to Unicode 18.0. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.pcntl"> + <title>PCNTL</title> + + <simpara> + <function>pcntl_alarm</function> now raises a + <exceptionname>ValueError</exceptionname> if the + <parameter>seconds</parameter> argument is lower than zero or greater + than the platform's <literal>UINT_MAX</literal>. + </simpara> + + <simpara> + <function>pcntl_exec</function> now raises a + <exceptionname>ValueError</exceptionname> if the + <parameter>args</parameter> argument is not a list array. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.pcre"> + <title>PCRE</title> + + <simpara> + <function>preg_grep</function> now returns &false; instead of a partial + array when a <acronym>PCRE</acronym> execution error occurs (e.g. malformed + <acronym>UTF-8</acronym> input with + the <literal>u</literal> modifier). + This is consistent with the other <literal>preg_*</literal> functions. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.pgsql"> + <title>PGSQL</title> + + <simpara> + When <function>pg_fetch_object</function> is given a non-empty + <parameter>constructor_args</parameter> for a class without a constructor, + the <exceptionname>ValueError</exceptionname> now refers to the + <parameter>constructor_args</parameter> argument instead of + <parameter>class</parameter>. + Errors raised when the requested class is not instantiable (abstract, + interface, enum) now surface before the row is fetched. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.phar"> + <title>Phar</title> + + <simpara> + <methodname>Phar::mungServer</methodname> now raises a + <exceptionname>ValueError</exceptionname> when an invalid argument value + is passed instead of being silently ignored. + </simpara> + + <simpara> + <methodname>Phar::addEmptyDir</methodname> now rejects + <literal>"/.phar"</literal> paths in addition to <literal>".phar"</literal> + paths, and raises the same + <exceptionname>BadMethodCallException</exceptionname> for attempts to + create the reserved magic <literal>".phar"</literal> directory through + that form. + Non-magic names that merely share the <literal>".phar"</literal> prefix + are now treated as ordinary directories. + </simpara> + + <simpara> + Files are only automatically interpreted as Phar archives when included if + <literal>".phar"</literal> occurs as an extension in the filename component + of their paths. + Previously, it could occur in a directory name or as part of an extension + such as <literal>".pharma"</literal>. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.session"> + <title>Session</title> + + <simpara> + Setting <link linkend="ini.session.cookie-path">session.cookie_path</link>, + <link linkend="ini.session.cookie-domain">session.cookie_domain</link>, or + <link linkend="ini.session.cache-limiter">session.cache_limiter</link> to a + value containing <literal>NUL</literal> bytes now emits a warning and + leaves the setting unchanged. + Previously, <literal>NUL</literal> bytes were silently accepted: for + <literal>cookie_path</literal> and <literal>cookie_domain</literal> this + caused the <acronym>SAPI</acronym> to drop the + <literal>Set-Cookie</literal> header; for <literal>cache_limiter</literal> + the value was silently truncated at the <literal>NUL</literal> byte. + </simpara> + + <simpara> + <function>session_module_name</function> now throws a + <exceptionname>ValueError</exceptionname> if <parameter>name</parameter> + is a string containing <literal>NUL</literal> bytes. + </simpara> + + <simpara> + <function>session_encode</function> now returns an empty string instead of + &false; for empty sessions. + It only returns &false; now when the session data could not be encoded. + This mainly happens with the default serialization handler if a key + contains the pipe (<literal>|</literal>) character. + </simpara> + + <simpara> + When <link linkend="ini.session.lazy-write">session.lazy_write</link> is + enabled and a session handler implements + <interfacename>SessionUpdateTimestampHandlerInterface</interfacename>, + sessions that were read as empty and remain empty at write time will now + trigger <methodname>SessionUpdateTimestampHandlerInterface::updateTimestamp</methodname> + instead of <methodname>SessionHandlerInterface::write</methodname>. + Previously, <methodname>SessionHandlerInterface::write</methodname> was + always called for empty sessions because + <function>session_encode</function> returned &false;, bypassing the + lazy_write comparison. + Custom session handlers that rely on + <methodname>SessionHandlerInterface::write</methodname> being called with + empty data (e.g. to destroy the session) should implement the same logic + in their <methodname>SessionUpdateTimestampHandlerInterface::updateTimestamp</methodname> + method. + </simpara> + + <para> + The defaults of three session INI settings have changed to provide secure + behavior out of the box: + <!-- RFC: https://wiki.php.net/rfc/session_security_defaults --> + + <simplelist> + <member> + <link linkend="ini.session.use-strict-mode">session.use_strict_mode</link> + is now <literal>1</literal> (was <literal>0</literal>). + Strict mode rejects uninitialized session IDs, mitigating session + fixation. + Custom session handlers that previously relied on accepting externally + supplied IDs without a corresponding storage entry must either implement + <methodname>SessionUpdateTimestampHandlerInterface::validateId</methodname> + and <methodname>SessionIdInterface::create_sid</methodname>, or + explicitly set this to <literal>0</literal>. + </member> + <member> + <link linkend="ini.session.cookie-httponly">session.cookie_httponly</link> + is now <literal>1</literal> (was <literal>0</literal>). + Session cookies are no longer accessible to JavaScript via + <literal>document.cookie</literal>. + Applications that read the session cookie from JavaScript must + explicitly set this to <literal>0</literal>. + </member> + <member> + <link linkend="ini.session.cookie-samesite">session.cookie_samesite</link> + is now <literal>"Lax"</literal> (was unset). + Session cookies are no longer sent on cross-site requests other than + top-level navigations using safe <acronym>HTTP</acronym> methods. + Applications that depend on session cookies being sent on cross-site + POST submissions must explicitly set this to <literal>"None"</literal> + (and also set + <link linkend="ini.session.cookie-secure">session.cookie_secure</link> + to <literal>1</literal>). + </member> + </simplelist> + </para> + + <simpara> + <methodname>SessionHandler::validateId</methodname> has been added and + delegates to the configured save handler. + A subclass that declares <methodname>SessionHandler::validateId</methodname> + without a return type now emits a deprecation notice for the tentative + <type>bool</type> return type. + A subclass that overrides <methodname>SessionHandler::open</methodname> + without calling <code>parent::open()</code> keeps its previous behavior + and emits a warning when an ID is validated. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.shmop"> + <title>Shmop</title> + + <simpara> + <function>shmop_open</function> now raises a + <exceptionname>ValueError</exceptionname> when the + <parameter>key</parameter> argument is outside the platform's + <literal>key_t</literal> range instead of passing a truncated key to the + operating system. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.simplexml"> + <title>SimpleXML</title> + + <simpara> + <methodname>SimpleXMLElement::__construct</methodname> now raises a + <exceptionname>ValueError</exceptionname> when the + <parameter>data</parameter> argument contains <literal>NUL</literal> + bytes, matching <function>simplexml_load_file</function>. + With <parameter>dataIsURL</parameter> set, it previously truncated the + path at the first <literal>NUL</literal> byte. + Without it, the string went to libxml, which with default options rejects + a <literal>NUL</literal> on current versions but accepts the truncated + document on older ones and under <constant>LIBXML_RECOVER</constant>. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.soap"> + <title>SOAP</title> + + <simpara> + The <literal>"classmap"</literal> option of + <classname>SoapClient</classname> and <classname>SoapServer</classname> + now rejects arrays containing integer keys. + Previously, sparse integer-keyed and mixed-keyed arrays could be accepted. + <classname>SoapClient</classname> now throws a + <exceptionname>TypeError</exceptionname> for non-array + <literal>"classmap"</literal> options and a + <exceptionname>ValueError</exceptionname> for arrays containing integer + keys, also when the <literal>"exceptions"</literal> option is disabled. + </simpara> + + <simpara> + <acronym>WSDL</acronym>/<acronym>XML</acronym> Schema parsing now rejects out-of-range integer values for + occurrence constraints and integer restriction facets. + Negative <literal>minOccurs</literal> and <literal>maxOccurs</literal> + values are rejected as well. + </simpara> + + <simpara> + SOAP encoding errors now report the affected type or failing operation in + the error message instead of the generic + <quote>Encoding: Violation of encoding rules</quote> message. + Code that compares the exact message may need to be updated. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.sockets"> + <title>Sockets</title> + + <simpara> + <function>socket_set_option</function> with + <constant>SO_ATTACH_REUSEPORT_CBPF</constant> now requires an + <type>int</type> <parameter>value</parameter> and a + <parameter>level</parameter> of <constant>SOL_SOCKET</constant>. + Any other value type throws a <exceptionname>TypeError</exceptionname> + instead of being coerced, and any other level raises a warning and + returns &false;. + </simpara> + + <simpara> + <function>socket_set_option</function> with + <constant>SO_ATTACH_REUSEPORT_CBPF</constant> and a + <parameter>value</parameter> of <literal>0</literal> now detaches the + reuseport filter through <constant>SO_DETACH_REUSEPORT_BPF</constant>. + It previously used <constant>SO_DETACH_BPF</constant>, an alias of + <constant>SO_DETACH_FILTER</constant>, which left the reuseport program + attached. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.sodium"> + <title>Sodium</title> + + <simpara> + The password-hashing functions <function>sodium_crypto_pwhash</function>, + <function>sodium_crypto_pwhash_str</function>, + <function>sodium_crypto_pwhash_scryptsalsa208sha256</function> and + <function>sodium_crypto_pwhash_scryptsalsa208sha256_str</function> now + throw a <exceptionname>ValueError</exceptionname> instead of a + <exceptionname>SodiumException</exceptionname> when an argument is out of + range, such as an <parameter>opslimit</parameter> or + <parameter>memlimit</parameter> below the documented minimum. + <exceptionname>SodiumException</exceptionname> is still thrown for + internal libsodium failures. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.spl"> + <title>SPL</title> + + <simpara> + <methodname>SplObjectStorage::getHash</methodname> implementations may no + longer mutate any <classname>SplObjectStorage</classname> instance. + Attempting to do so now throws an <exceptionname>Error</exceptionname>. + </simpara> + + <simpara> + <methodname>SplFileObject::next</methodname> now advances the stream when + no prior <methodname>SplFileObject::current</methodname> call has cached a + line. + A subsequent <methodname>SplFileObject::current</methodname> call returns + the new line rather than the previous one. + </simpara> + + <simpara> + <methodname>SplFileObject::fgets</methodname> no longer caches the returned + line for subsequent <methodname>SplFileObject::current</methodname> calls. + <methodname>SplFileObject::current</methodname> now re-reads from the + current stream position instead of returning the line + <methodname>SplFileObject::fgets</methodname> just returned. + </simpara> + + <simpara> + <methodname>SplFileObject::next</methodname> past <acronym>EOF</acronym> no longer increments + <methodname>SplFileObject::key</methodname> without bound. + <methodname>SplFileObject::seek</methodname> past <acronym>EOF</acronym> now produces the same + <methodname>SplFileObject::key</methodname> value as + <classname>SplTempFileObject</classname>; the two previously returned + different values. + </simpara> + + <simpara> + <methodname>DirectoryIterator::key</methodname> now returns + <type class="union"><type>int</type><type>string</type></type>, and + <methodname>DirectoryIterator::current</methodname> returns + <type class="union"><type>string</type><type>SplFileInfo</type><type>static</type></type>. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.sysvshm"> + <title>Sysvshm</title> + + <simpara> + <function>shm_attach</function> now raises a + <exceptionname>ValueError</exceptionname> when the + <parameter>key</parameter> argument is outside the platform's + <literal>key_t</literal> range instead of passing a truncated key to the + operating system. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.uri"> + <title>URI</title> + + <simpara> + <methodname>Uri\WhatWg\Url::__construct</methodname> now sets + <parameter>softErrors</parameter> to an empty array when URL processing + throws an exception, instead of preserving its value. + URL validation errors remain available in the + <property>Uri\WhatWg\InvalidUrlException::$errors</property> property. + </simpara> + + <simpara> + <methodname>Uri\WhatWg\Url::__construct</methodname>, + <methodname>Uri\WhatWg\Url::parse</methodname>, the + <literal>Uri\WhatWg\Url::with*()</literal> methods, and + <methodname>Uri\WhatWg\UrlBuilder::build</methodname> now report + validation errors in the order in which they are detected. + This reverses the order of multiple errors compared to PHP 8.5. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.zip"> + <title>Zip</title> + + <simpara> + <methodname>ZipArchive::extractTo</methodname> now raises a + <exceptionname>TypeError</exceptionname> for the + <parameter>files</parameter> argument if one or more of the entries is not + a string. + </simpara> + + <simpara> + <methodname>ZipArchive::addGlob</methodname> and + <methodname>ZipArchive::addPattern</methodname> now raise a + <exceptionname>TypeError</exceptionname> when the + <literal>"remove_all_path"</literal> option is not of type + <type>bool</type>, or when the <literal>"comp_method"</literal>, + <literal>"comp_flags"</literal>, or <literal>"enc_method"</literal> + options are not of type <type>int</type> (numeric strings are coerced), + instead of emitting a warning. + </simpara> + + <simpara> + Serializing or unserializing a <classname>ZipArchive</classname> now + throws an <exceptionname>Exception</exceptionname>. + A subclass can override + <link linkend="object.serialize">__serialize()</link> and + <link linkend="object.unserialize">__unserialize()</link> to round-trip through + <methodname>ZipArchive::closeString</methodname> and + <methodname>ZipArchive::openString</methodname>. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.incompatible.zlib"> + <title>Zlib</title> + + <simpara> + <function>deflate_init</function> now raises a + <exceptionname>TypeError</exceptionname> when the value for option + <literal>"level"</literal>, <literal>"memory"</literal>, + <literal>"window"</literal>, or <literal>"strategy"</literal> is not of + type <type>int</type>. + </simpara> + + <simpara> + <function>inflate_init</function> now raises a + <exceptionname>TypeError</exceptionname> when the value for option + <literal>"window"</literal> is not of type <type>int</type>. + </simpara> + + </sect2> + +</sect1> +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:t +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +indent-tabs-mode:nil +sgml-parent-document:nil +sgml-default-dtd-file:"~/.phpdoc/manual.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +End: +vim600: syn=xml fen fdm=syntax fdl=2 si +vim: et tw=78 syn=sgml +vi: ts=1 sw=1 +--> diff --git a/appendices/migration86/new-classes.xml b/appendices/migration86/new-classes.xml new file mode 100644 index 000000000000..6467a582d4b2 --- /dev/null +++ b/appendices/migration86/new-classes.xml @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="utf-8"?> +<sect1 xml:id="migration86.new-classes" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>New Classes and Interfaces</title> + + <sect2 xml:id="migration86.new-classes.core"> + <title>Core</title> + <simplelist> + <member><enumname>SortDirection</enumname></member> + <member><exceptionname>StreamError</exceptionname></member> + <member><exceptionname>StreamException</exceptionname></member> + <member><enumname>StreamErrorStore</enumname></member> + <member><enumname>StreamErrorMode</enumname></member> + <member><enumname>StreamErrorCode</enumname></member> + <member><exceptionname>Io\IoException</exceptionname></member> + <member><classname>Io\Poll\Context</classname></member> + <member><classname>Io\Poll\Watcher</classname></member> + <member><enumname>Io\Poll\Backend</enumname></member> + <member><enumname>Io\Poll\Event</enumname></member> + <member><interfacename>Io\Poll\Handle</interfacename></member> + <member><exceptionname>Io\Poll\PollException</exceptionname></member> + <member><exceptionname>Io\Poll\FailedPollOperationException</exceptionname></member> + <member><exceptionname>Io\Poll\FailedContextInitializationException</exceptionname></member> + <member><exceptionname>Io\Poll\FailedHandleAddException</exceptionname></member> + <member><exceptionname>Io\Poll\FailedWatcherModificationException</exceptionname></member> + <member><exceptionname>Io\Poll\FailedPollWaitException</exceptionname></member> + <member><exceptionname>Io\Poll\BackendUnavailableException</exceptionname></member> + <member><exceptionname>Io\Poll\InactiveWatcherException</exceptionname></member> + <member><exceptionname>Io\Poll\HandleAlreadyWatchedException</exceptionname></member> + <member><exceptionname>Io\Poll\InvalidHandleException</exceptionname></member> + <member><classname>StreamPollHandle</classname></member> + </simplelist> + <!-- RFC: https://wiki.php.net/rfc/sort_direction_enum --> + <!-- RFC: https://wiki.php.net/rfc/stream_errors --> + <!-- RFC: https://wiki.php.net/rfc/poll_api --> + </sect2> + + <sect2 xml:id="migration86.new-classes.date"> + <title>Date</title> + <simplelist> + <member><classname>Time\Duration</classname></member> + <member><exceptionname>Time\TimeException</exceptionname></member> + </simplelist> + <!-- RFC: https://wiki.php.net/rfc/duration_class --> + </sect2> + + <sect2 xml:id="migration86.new-classes.intl"> + <title>Intl</title> + <simplelist> + <member><classname>IntlNumberRangeFormatter</classname></member> + </simplelist> + </sect2> + + <sect2 xml:id="migration86.new-classes.openssl"> + <title>OpenSSL</title> + <simplelist> + <member><exceptionname>Openssl\OpensslException</exceptionname></member> + <member><classname>Openssl\Session</classname></member> + <member><classname>Openssl\Psk</classname></member> + </simplelist> + <!-- RFC: https://wiki.php.net/rfc/tls_session_resumption --> + </sect2> + + <sect2 xml:id="migration86.new-classes.snmp"> + <title>SNMP</title> + <simplelist> + <member><enumname>Snmp\Mib</enumname></member> + <member><enumname>Snmp\OidOutput</enumname></member> + <member><enumname>Snmp\Output</enumname></member> + <member><enumname>Snmp\StringOutput</enumname></member> + </simplelist> + <!-- RFC: https://wiki.php.net/rfc/snmp_improvements_2026 --> + </sect2> + + <sect2 xml:id="migration86.new-classes.uri"> + <title>URI</title> + <simplelist> + <member><classname>Uri\Rfc3986\UriBuilder</classname></member> + <member><classname>Uri\WhatWg\UrlBuilder</classname></member> + <member><enumname>Uri\WhatWg\UrlPercentEncodingMode</enumname></member> + </simplelist> + <!-- RFC: https://wiki.php.net/rfc/uri_followup#uri_building --> + <!-- RFC: https://wiki.php.net/rfc/uri_followup#percent-encoding_support --> + </sect2> + +</sect1> +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:t +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +indent-tabs-mode:nil +sgml-parent-document:nil +sgml-default-dtd-file:"~/.phpdoc/manual.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +End: +vim600: syn=xml fen fdm=syntax fdl=2 si +vim: et tw=78 syn=sgml +vi: ts=1 sw=1 +--> diff --git a/appendices/migration86/new-features.xml b/appendices/migration86/new-features.xml new file mode 100644 index 000000000000..ab2bdb8034bd --- /dev/null +++ b/appendices/migration86/new-features.xml @@ -0,0 +1,635 @@ +<?xml version="1.0" encoding="utf-8"?> +<sect1 xml:id="migration86.new-features" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>New Features</title> + + <sect2 xml:id="migration86.new-features.core"> + <title>PHP Core</title> + + <sect3 xml:id="migration86.new-features.core.readonly-property-defaults"> + <title>Default values for readonly properties</title> + + <simpara> + <link linkend="language.oop5.properties.readonly-properties">Readonly + properties</link> may now declare default values. + <!-- RFC: https://wiki.php.net/rfc/readonly_property_defaults --> + </simpara> + + <informalexample> + <programlisting role="php"> +<![CDATA[ +<?php +class Config +{ + public readonly int $timeout = 30; +} + +$config = new Config(); +var_dump($config->timeout); // int(30) +]]> + </programlisting> + </informalexample> + + </sect3> + + <sect3 xml:id="migration86.new-features.core.weakmap-reference-assignment"> + <title>Reference assignment on WeakMap</title> + + <simpara> + It is now possible to use reference assignment on a + <classname>WeakMap</classname> without the key needing to be present + beforehand. + </simpara> + + <informalexample> + <programlisting role="php"> +<![CDATA[ +<?php +$obj = new stdClass(); +$map = new WeakMap(); +$count = 0; + +// Previously: Error: "Object stdClass#1 not contained in WeakMap" +$map[$obj] = &$count; +$count++; + +var_dump($map[$obj]); // int(1) +]]> + </programlisting> + </informalexample> + + </sect3> + + <sect3 xml:id="migration86.new-features.core.debuginfo-on-enums"> + <title><methodname>__debugInfo</methodname> on enums</title> + + <simpara> + It is now possible to define the + <link linkend="language.oop5.magic.debuginfo">__debugInfo()</link> + magic method on <link linkend="language.enumerations">enums</link>. + Previously, this resulted in a fatal error. + <!-- RFC: https://wiki.php.net/rfc/debugable-enums --> + </simpara> + + <informalexample> + <programlisting role="php"> +<![CDATA[ +<?php +enum Suit: string +{ + case Hearts = 'H'; + case Spades = 'S'; + + public function __debugInfo(): array + { + return ['suit' => $this->name, 'symbol' => $this->value]; + } +} + +var_dump(Suit::Hearts); +]]> + </programlisting> + &example.outputs; + <screen> +<![CDATA[ +enum(Suit::Hearts) (2) { + ["suit"]=> + string(6) "Hearts" + ["symbol"]=> + string(1) "H" +} +]]> + </screen> + </informalexample> + + </sect3> + + <sect3 xml:id="migration86.new-features.core.override-for-constants"> + <title><code>#[\Override]</code> for class constants</title> + + <simpara> + The <classname>Override</classname> attribute can now be applied to + class constants, including enum cases. + As with methods and properties, a compile-time error is raised if no + matching constant exists in a parent class or implemented interface. + <!-- RFC: https://wiki.php.net/rfc/override_constants --> + </simpara> + + <informalexample> + <programlisting role="php"> +<![CDATA[ +<?php +interface HasVersion +{ + const VERSION = '1.0'; +} + +class Package implements HasVersion +{ + #[\Override] + const VERSION = '2.0'; + + // Fatal error: Package::NAME has #[\Override] attribute, + // but no matching parent constant exists + // #[\Override] + // const NAME = 'package'; +} +]]> + </programlisting> + </informalexample> + + </sect3> + + <sect3 xml:id="migration86.new-features.core.partial-function-application"> + <title>Partial function application</title> + + <simpara> + Added support for partial function application. A call in which one or + more arguments are replaced by the <literal>?</literal> placeholder, or + the remaining arguments by the <literal>...</literal> placeholder, + creates a <classname>Closure</classname> that accepts the missing + arguments. + <!-- RFC: https://wiki.php.net/rfc/partial_function_application_v2 --> + </simpara> + + <informalexample> + <programlisting role="php"> +<![CDATA[ +<?php +function add(int $a, int $b, int $c = 0): int +{ + return $a + $b + $c; +} + +// "?" replaces exactly one argument +$addOne = add(1, ?); +var_dump($addOne(5)); // int(6) + +// "..." replaces all remaining arguments +$addToOne = add(1, ...); +var_dump($addToOne(2, 3)); // int(6) + +// Works with any callable, including internal functions +$stripSpaces = str_replace(' ', '', ?); +var_dump($stripSpaces('a b c')); // string(3) "abc" +]]> + </programlisting> + </informalexample> + + </sect3> + + <sect3 xml:id="migration86.new-features.core.const-object-property-write"> + <title>Mutating objects stored in constants</title> + + <simpara> + Objects stored in constants or class constants can now be mutated + directly via <code>OBJ->prop = $val</code>. + <!-- RFC: https://wiki.php.net/rfc/const_object_property_write --> + </simpara> + + <informalexample> + <programlisting role="php"> +<![CDATA[ +<?php +const CONFIG = new stdClass(); + +// Previously: "Fatal error: Cannot use temporary expression in write context" +CONFIG->debug = true; + +var_dump(CONFIG->debug); // bool(true) +]]> + </programlisting> + </informalexample> + + </sect3> + + <sect3 xml:id="migration86.new-features.core.pack-unpack-endianness"> + <title>Endianness modifiers for pack() and unpack()</title> + + <simpara> + <function>pack</function> and <function>unpack</function> now accept the + <literal>&lt;</literal> (little-endian) and <literal>&gt;</literal> + (big-endian) modifiers after the <literal>s</literal>, <literal>S</literal>, + <literal>l</literal>, <literal>L</literal>, <literal>q</literal> and + <literal>Q</literal> integer format codes, and after the + <literal>f</literal> and <literal>d</literal> float and double format codes. + <!-- RFC: https://wiki.php.net/rfc/pack-unpack-endianness-signed-integers-support --> + <!-- RFC: https://wiki.php.net/rfc/pack-unpack-float-endianness-modifier --> + </simpara> + + <informalexample> + <programlisting role="php"> +<![CDATA[ +<?php +echo bin2hex(pack('l>', 1)), PHP_EOL; // Prints "00000001" +echo bin2hex(pack('l<', 1)), PHP_EOL; // Prints "01000000" +echo bin2hex(pack('f>', 1.5)), PHP_EOL; // Prints "3fc00000" + +var_dump(unpack('s>value', "\xff\xfe")); // ["value" => int(-2)] +]]> + </programlisting> + </informalexample> + + </sect3> + + </sect2> + + <sect2 xml:id="migration86.new-features.curl"> + <title>cURL</title> + + <simpara> + The array returned by <function>curl_getinfo</function> now includes a new + <literal>"size_delivered"</literal> key, which indicates the total number of + bytes passed to the download write callback. + This value can also be obtained by passing + <constant>CURLINFO_SIZE_DELIVERED</constant> as the + <parameter>option</parameter> parameter. + Requires libcurl 8.20.0 or later. + </simpara> + + <simpara> + Added <constant>CURLOPT_SEEKFUNCTION</constant> to register a callback that + repositions a streamed request body, so libcurl can rewind and resend it on + a redirect, multi-pass authentication, or a retried reused connection + instead of failing with <constant>CURLE_SEND_FAIL_REWIND</constant>. + The callback receives the <classname>CurlHandle</classname>, offset and + origin, and must return one of <constant>CURL_SEEKFUNC_OK</constant>, + <constant>CURL_SEEKFUNC_FAIL</constant> or + <constant>CURL_SEEKFUNC_CANTSEEK</constant>. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.new-features.date"> + <title>Date</title> + + <simpara> + Added the <classname>Time\Duration</classname> class. + <!-- RFC: https://wiki.php.net/rfc/duration_class --> + </simpara> + + </sect2> + + <sect2 xml:id="migration86.new-features.fileinfo"> + <title>FileInfo</title> + + <simpara> + <function>finfo_file</function> now works with remote streams. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.new-features.gmp"> + <title>GMP</title> + + <simpara> + Added <function>gmp_powm_sec</function> for side-channel quiet modular + exponentiation. + Requires GNU MP 5.0.0 or later; it is not available on official Windows + builds using MPIR. + </simpara> + + <simpara> + Added <function>gmp_prevprime</function> to get the largest prime smaller + than the given number. + The optional <parameter>definitely_prime</parameter> output parameter + indicates whether the returned number is definitely prime, as opposed to + probably prime. + A <exceptionname>ValueError</exceptionname> is thrown if no such prime + exists. + This function is only available when PHP is built against GNU MP 6.3.0 or + later; it is not available on official Windows builds using MPIR. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.new-features.intl"> + <title>Intl</title> + + <simpara> + Added the static methods + <methodname>IntlDatePatternGenerator::getSkeleton</methodname> and + <methodname>IntlDatePatternGenerator::getBaseSkeleton</methodname> to + generate the unique skeleton and base skeleton for a date/time pattern. + </simpara> + + <simpara> + Added <methodname>Locale::getDisplayKeyword</methodname> and + <methodname>Locale::getDisplayKeywordValue</methodname>, with the aliases + <function>locale_get_display_keyword</function> and + <function>locale_get_display_keyword_value</function>, respectively. + <!-- RFC: https://wiki.php.net/rfc/getdisplaykeyword_and_getdisplaykeywordvalue --> + </simpara> + + <para> + Added the <classname>IntlNumberRangeFormatter</classname> class to format + an interval of two numbers with a given skeleton and locale. + It is supported as of <acronym>ICU</acronym> 63. + The collapse behavior is one of: + <simplelist> + <member><constant>IntlNumberRangeFormatter::COLLAPSE_AUTO</constant></member> + <member><constant>IntlNumberRangeFormatter::COLLAPSE_NONE</constant></member> + <member><constant>IntlNumberRangeFormatter::COLLAPSE_UNIT</constant></member> + <member><constant>IntlNumberRangeFormatter::COLLAPSE_ALL</constant></member> + </simplelist> + The identity fallback is one of: + <simplelist> + <member><constant>IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE</constant></member> + <member><constant>IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE</constant></member> + <member><constant>IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY</constant></member> + <member><constant>IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE</constant></member> + </simplelist> + </para> + + <simpara> + Added <methodname>SpoofChecker::areBidiConfusable</methodname> to check + whether two strings are confusable for a given text direction, along with + the <constant>SpoofChecker::LTR</constant> and + <constant>SpoofChecker::RTL</constant> direction constants. + It is supported as of <acronym>ICU</acronym> 74. + </simpara> + + <simpara> + Added <methodname>SpoofChecker::getBidiSkeleton</methodname> to generate a + confusable skeleton for a given text direction. + It is supported as of <acronym>ICU</acronym> 74. + </simpara> + + <simpara> + Added <methodname>SpoofChecker::getSkeleton</methodname> to generate a + confusable skeleton for a given string. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.new-features.io"> + <title>IO</title> + + <para> + Added a new polling <acronym>API</acronym>, consisting of: + <simplelist> + <member>The <classname>Io\Poll\Context</classname> and <classname>Io\Poll\Watcher</classname> classes</member> + <member>The <enumname>Io\Poll\Backend</enumname> and <enumname>Io\Poll\Event</enumname> enums</member> + <member>The <interfacename>Io\Poll\Handle</interfacename> interface</member> + <member>The <classname>StreamPollHandle</classname> class to watch streams</member> + </simplelist> + <!-- RFC: https://wiki.php.net/rfc/poll_api --> + </para> + + </sect2> + + <sect2 xml:id="migration86.new-features.json"> + <title>JSON</title> + + <simpara> + Added extra information about the error location to the error messages + returned by <function>json_last_error_msg</function> and to the message of + <exceptionname>JsonException</exceptionname>. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.new-features.openssl"> + <title>OpenSSL</title> + + <para> + Added <acronym>TLS</acronym> session resumption support for streams. + This allows saving and restoring client sessions across requests, + implementing custom server-side session storage, and controlling session + cache behavior, using the following new + <link linkend="context.ssl">SSL context</link> options: + <simplelist> + <member><literal>session_data</literal></member> + <member><literal>session_new_cb</literal></member> + <member><literal>session_cache</literal></member> + <member><literal>session_cache_size</literal></member> + <member><literal>session_timeout</literal></member> + <member><literal>session_id_context</literal></member> + <member><literal>session_get_cb</literal></member> + <member><literal>session_remove_cb</literal></member> + <member><literal>num_tickets</literal></member> + </simplelist> + <!-- RFC: https://wiki.php.net/rfc/tls_session_resumption --> + </para> + + <simpara> + Added <acronym>TLS</acronym> external <acronym>PSK</acronym> support for + streams with the new <link linkend="context.ssl">SSL context</link> + options <literal>psk_client_cb</literal> and + <literal>psk_server_cb</literal>. + This allows setting and receiving pre-shared keys. + </simpara> + + <simpara> + Added <acronym>TLS</acronym> 1.3 early data (0-RTT) support for streams. + Clients send early data with the <literal>early_data</literal> + <link linkend="context.ssl">SSL context</link> option; servers accept it + with <literal>max_early_data</literal> and receive it through the + <literal>early_data_cb</literal> callback. + The outcome is reported as <literal>"accepted"</literal>, + <literal>"rejected"</literal> or <literal>"not_sent"</literal> in the + <literal>"early_data"</literal> key of the <literal>"crypto"</literal> + entry of the <function>stream_get_meta_data</function> array. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.new-features.pdo-pgsql"> + <title>PDO_PGSQL</title> + + <simpara> + Added <constant>Pdo\Pgsql::ATTR_CHUNK_SIZE</constant>, the number of rows a + statement fetches per chunk. + A value of 1 or more enters the lazy fetch mode of + <code>PDO::ATTR_PREFETCH => 0</code>. + Setting <constant>PDO::ATTR_PREFETCH</constant> replaces the chunk size. + Statements that are prepared with neither it nor + <constant>PDO::ATTR_PREFETCH</constant> fall back to the value set on the + connection. + Requires libpq 17 or later. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.new-features.phar"> + <title>Phar</title> + + <simpara> + Overriding the <methodname>SplFileInfo::getMTime</methodname> and + <methodname>SplFileInfo::getPathname</methodname> methods now influences + the result of the <methodname>Phar::buildFromDirectory</methodname> and + <methodname>Phar::buildFromIterator</methodname> family of methods. + This makes it possible to override the timestamp and names of files. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.new-features.snmp"> + <title>SNMP</title> + + <simpara> + It is now possible to use <literal>AES192</literal>, + <literal>AES192C</literal>, <literal>AES256</literal>, and + <literal>AES256C</literal> as SNMPv3 security protocols if the underlying + library supports them. + <!-- RFC: https://wiki.php.net/rfc/snmp_improvements_2026#increase_the_number_of_snmpv3_security_protocols_supported --> + </simpara> + + <simpara> + It is now possible to reset the <acronym>MIB</acronym> tree using the new + <function>snmp_init_mib</function> function. + <!-- RFC: https://wiki.php.net/rfc/snmp_improvements_2026#allow_the_snmp_mib_to_be_reset --> + </simpara> + + <para> + Additional <acronym>MIB</acronym> parsing and output control functionality + has been exposed via: + <simplelist> + <member><function>snmp_set_mib_option</function></member> + <member><function>snmp_set_output_option</function></member> + <member><function>snmp_set_string_output_format</function></member> + <member><property>SNMP::$numeric_index</property></member> + <member><property>SNMP::$numeric_timeticks</property></member> + <member><property>SNMP::$extended_index</property></member> + <member><property>SNMP::$dont_print_units</property></member> + <member><property>SNMP::$escape_quotes</property></member> + <member><property>SNMP::$print_hex_text</property></member> + <member><methodname>SNMP::setOidOutputFormat</methodname></member> + <member><methodname>SNMP::setStringOutputFormat</methodname></member> + </simplelist> + <!-- RFC: https://wiki.php.net/rfc/snmp_improvements_2026#implement_more_mib_parsing_and_value_output_controls --> + </para> + + </sect2> + + <sect2 xml:id="migration86.new-features.streams"> + <title>Streams</title> + + <para> + Added a new stream errors <acronym>API</acronym>, consisting of: + <simplelist> + <member>The <exceptionname>StreamError</exceptionname> and <exceptionname>StreamException</exceptionname> classes</member> + <member>The <enumname>StreamErrorStore</enumname>, <enumname>StreamErrorMode</enumname>, and <enumname>StreamErrorCode</enumname> enums</member> + <member>The <function>stream_last_errors</function> and <function>stream_clear_errors</function> functions</member> + </simplelist> + It is controlled using the <literal>error_mode</literal>, + <literal>error_store</literal> and <literal>error_handler</literal> + stream context options. + <!-- RFC: https://wiki.php.net/rfc/stream_errors --> + </para> + + <simpara> + Added the <literal>filter.max_filter_count</literal> stream context option + for <link linkend="wrappers.php">php://filter</link> URLs. + When set, opening the stream fails with a warning if the URL would add more + filters than the configured value. + Negative values disable the check. + <!-- RFC: https://wiki.php.net/rfc/limit-maximum-number-of-filter-chains --> + </simpara> + + <simpara> + Added the <link linkend="context.socket">socket context</link> option + <literal>so_reuseaddr</literal> that allows disabling address reuse + (<literal>SO_REUSEADDR</literal>) and explicitly uses + <literal>SO_EXCLUSIVEADDRUSE</literal> on Windows. + </simpara> + + <simpara> + Added the <link linkend="context.socket">socket context</link> options + <literal>so_keepalive</literal>, <literal>tcp_keepidle</literal>, + <literal>tcp_keepintvl</literal> and <literal>tcp_keepcnt</literal> that + allow setting socket keepalive options. + </simpara> + + <simpara> + Added the <link linkend="context.socket">socket context</link> option + <literal>so_linger</literal> that sets <literal>SO_LINGER</literal> on + <acronym>TCP</acronym> sockets. + A positive value enables lingering for that many seconds, zero or a + negative value disables it. + Values above 65535 are clamped as the linger time is limited to an + unsigned short on some platforms. + </simpara> + + <simpara> + Added the <link linkend="context.socket">socket context</link> options + <literal>so_rcvbuf</literal> and <literal>so_sndbuf</literal> that set the + socket receive and send buffer sizes in bytes + (<literal>SO_RCVBUF</literal> and <literal>SO_SNDBUF</literal>) on + <acronym>TCP</acronym> and <acronym>UDP</acronym> sockets. + The value must be an integer between 1 and 2147483647, any other value + makes the stream creation fail. + The operating system may round, cap or otherwise adjust the requested size, + and may stop sizing that buffer automatically, so the size read back can + differ from the one requested. + </simpara> + + <simpara> + Filtered streams can now be cast to file descriptors for use with + <function>stream_select</function>. + </simpara> + + <para> + Added the <literal>"write_seek_mode"</literal> filter parameter for the + bz2, iconv, zlib, and <link linkend="filters.convert">convert</link> stream + filters. + This parameter must be set via an associative array where the key is + <literal>"write_seek_mode"</literal> and the value is one of the following + strings: + <simplelist> + <member><literal>"preserve"</literal></member> + <member><literal>"reset"</literal></member> + <member><literal>"strict"</literal></member> + </simplelist> + </para> + + </sect2> + + <sect2 xml:id="migration86.new-features.uri"> + <title>URI</title> + + <simpara> + Added <methodname>Uri\Rfc3986\Uri::getUriType</methodname> and + <methodname>Uri\WhatWg\Url::isSpecialScheme</methodname>. + <!-- RFC: https://wiki.php.net/rfc/uri_followup#uri_type_detection --> + </simpara> + + <simpara> + Added <methodname>Uri\Rfc3986\Uri::getHostType</methodname> and + <methodname>Uri\WhatWg\Url::getHostType</methodname>. + <!-- RFC: https://wiki.php.net/rfc/uri_followup#host_type_detection --> + </simpara> + + <simpara> + Added the <classname>Uri\Rfc3986\UriBuilder</classname> and + <classname>Uri\WhatWg\UrlBuilder</classname> classes. + <!-- RFC: https://wiki.php.net/rfc/uri_followup#uri_building --> + </simpara> + + <simpara> + Added <function>Uri\WhatWg\url_percent_encode</function>. + <!-- RFC: https://wiki.php.net/rfc/uri_followup#percent-encoding_support --> + </simpara> + + </sect2> + +</sect1> +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:t +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +indent-tabs-mode:nil +sgml-parent-document:nil +sgml-default-dtd-file:"~/.phpdoc/manual.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +End: +vim600: syn=xml fen fdm=syntax fdl=2 si +vim: et tw=78 syn=sgml +vi: ts=1 sw=1 +--> diff --git a/appendices/migration86/new-functions.xml b/appendices/migration86/new-functions.xml new file mode 100644 index 000000000000..a20e69c629a1 --- /dev/null +++ b/appendices/migration86/new-functions.xml @@ -0,0 +1,230 @@ +<?xml version="1.0" encoding="utf-8"?> +<sect1 xml:id="migration86.new-functions"> + <title>New Functions</title> + + <sect2 xml:id="migration86.new-functions.core"> + <title>Core</title> + + <simplelist> + <!-- RFC: https://wiki.php.net/rfc/clamp_v2 --> + <member> + <function>clamp</function> returns the given value if in range, else + returns the nearest bound. + </member> + <!-- RFC: https://wiki.php.net/rfc/stream_errors --> + <member><function>stream_last_errors</function></member> + <member><function>stream_clear_errors</function></member> + <member><function>stream_socket_get_crypto_status</function></member> + </simplelist> + </sect2> + + <sect2 xml:id="migration86.new-functions.gmp"> + <title>GMP</title> + + <simplelist> + <member><function>gmp_powm_sec</function></member> + <member><function>gmp_prevprime</function></member> + </simplelist> + </sect2> + + <sect2 xml:id="migration86.new-functions.intl"> + <title>Intl</title> + + <simplelist> + <!-- RFC: https://wiki.php.net/rfc/grapheme_strrev --> + <member><function>grapheme_strrev</function></member> + <member> + <methodname>IntlDatePatternGenerator::getSkeleton</methodname> + </member> + <member> + <methodname>IntlDatePatternGenerator::getBaseSkeleton</methodname> + </member> + <!-- RFC: https://wiki.php.net/rfc/getdisplaykeyword_and_getdisplaykeywordvalue --> + <member> + <methodname>Locale::getDisplayKeyword</methodname> + </member> + <member><function>locale_get_display_keyword</function></member> + <member> + <methodname>Locale::getDisplayKeywordValue</methodname> + </member> + <member><function>locale_get_display_keyword_value</function></member> + <member> + <methodname>SpoofChecker::areBidiConfusable</methodname> + </member> + <member> + <methodname>SpoofChecker::getBidiSkeleton</methodname> + </member> + <member> + <methodname>SpoofChecker::getSkeleton</methodname> + </member> + </simplelist> + </sect2> + + <sect2 xml:id="migration86.new-functions.mysqli"> + <title>MySQLi</title> + + <simplelist> + <!-- RFC: https://wiki.php.net/rfc/mysqli_quote_string --> + <member> + <methodname>mysqli::quote_string</methodname> + </member> + <member><function>mysqli_quote_string</function></member> + </simplelist> + </sect2> + + <sect2 xml:id="migration86.new-functions.reflection"> + <title>Reflection</title> + + <simplelist> + <member> + <methodname>ReflectionAttribute::inNamespace</methodname> + </member> + <member> + <methodname>ReflectionAttribute::getNamespaceName</methodname> + </member> + <member> + <methodname>ReflectionAttribute::getShortName</methodname> + </member> + <member> + <methodname>ReflectionConstant::inNamespace</methodname> + </member> + <!-- RFC: https://wiki.php.net/rfc/parameter-doccomments --> + <member> + <methodname>ReflectionParameter::getDocComment</methodname> + </member> + <!-- RFC: https://wiki.php.net/rfc/isreadable-iswriteable --> + <member> + <methodname>ReflectionProperty::isReadable</methodname> + </member> + <member> + <methodname>ReflectionProperty::isWritable</methodname> + </member> + </simplelist> + </sect2> + + <sect2 xml:id="migration86.new-functions.snmp"> + <title>SNMP</title> + + <simplelist> + <!-- RFC: https://wiki.php.net/rfc/snmp_improvements_2026 --> + <member><function>snmp_init_mib</function></member> + <member><function>snmp_set_mib_option</function></member> + <member><function>snmp_set_output_option</function></member> + <member><function>snmp_set_string_output_format</function></member> + <member> + <methodname>SNMP::setOidOutputFormat</methodname> + </member> + <member> + <methodname>SNMP::setStringOutputFormat</methodname> + </member> + </simplelist> + </sect2> + + <sect2 xml:id="migration86.new-functions.sodium"> + <title>Sodium</title> + + <simplelist> + <member><function>sodium_crypto_ipcrypt_keygen</function></member> + <member><function>sodium_crypto_ipcrypt_encrypt</function></member> + <member><function>sodium_crypto_ipcrypt_decrypt</function></member> + <member><function>sodium_crypto_ipcrypt_nd_keygen</function></member> + <member><function>sodium_crypto_ipcrypt_nd_encrypt</function></member> + <member><function>sodium_crypto_ipcrypt_nd_decrypt</function></member> + <member><function>sodium_crypto_ipcrypt_ndx_keygen</function></member> + <member><function>sodium_crypto_ipcrypt_ndx_encrypt</function></member> + <member><function>sodium_crypto_ipcrypt_ndx_decrypt</function></member> + <member><function>sodium_crypto_ipcrypt_pfx_keygen</function></member> + <member><function>sodium_crypto_ipcrypt_pfx_encrypt</function></member> + <member><function>sodium_crypto_ipcrypt_pfx_decrypt</function></member> + <member><function>sodium_bin2ip</function></member> + <member><function>sodium_ip2bin</function></member> + </simplelist> + + <para> + The following functions expose the X-Wing <acronym>KEM</acronym> + (hybrid ML-KEM768+X25519, libsodium's recommended <acronym>KEM</acronym>). + They are available when PHP is built against libsodium 1.0.22 or later. + + <simplelist> + <member><function>sodium_crypto_kem_keypair</function></member> + <member><function>sodium_crypto_kem_seed_keypair</function></member> + <member><function>sodium_crypto_kem_secretkey</function></member> + <member><function>sodium_crypto_kem_publickey</function></member> + <member><function>sodium_crypto_kem_enc</function></member> + <member><function>sodium_crypto_kem_dec</function></member> + </simplelist> + </para> + + <para> + The following functions expose the ML-KEM768 (FIPS 203) + <acronym>KEM</acronym>. + They are available when PHP is built against libsodium 1.0.22 or later. + + <simplelist> + <member><function>sodium_crypto_kem_mlkem768_keypair</function></member> + <member><function>sodium_crypto_kem_mlkem768_seed_keypair</function></member> + <member><function>sodium_crypto_kem_mlkem768_secretkey</function></member> + <member><function>sodium_crypto_kem_mlkem768_publickey</function></member> + <member><function>sodium_crypto_kem_mlkem768_enc</function></member> + <member><function>sodium_crypto_kem_mlkem768_dec</function></member> + </simplelist> + </para> + </sect2> + + <sect2 xml:id="migration86.new-functions.uri"> + <title>URI</title> + + <simplelist> + <!-- RFC: https://wiki.php.net/rfc/uri_followup#uri_type_detection --> + <member> + <methodname>Uri\Rfc3986\Uri::getUriType</methodname> + </member> + <member> + <methodname>Uri\WhatWg\Url::isSpecialScheme</methodname> + </member> + <!-- RFC: https://wiki.php.net/rfc/uri_followup#host_type_detection --> + <member> + <methodname>Uri\Rfc3986\Uri::getHostType</methodname> + </member> + <member> + <methodname>Uri\WhatWg\Url::getHostType</methodname> + </member> + <!-- RFC: https://wiki.php.net/rfc/uri_followup#percent-encoding_support --> + <member><function>Uri\WhatWg\url_percent_encode</function></member> + </simplelist> + </sect2> + + <sect2 xml:id="migration86.new-functions.zip"> + <title>Zip</title> + + <simplelist> + <member> + <methodname>ZipArchive::openString</methodname> + </member> + <member> + <methodname>ZipArchive::closeString</methodname> + </member> + </simplelist> + </sect2> + +</sect1> +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:t +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +indent-tabs-mode:nil +sgml-parent-document:nil +sgml-default-dtd-file:"~/.phpdoc/manual.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +End: +vim600: syn=xml fen fdm=syntax fdl=2 si +vim: et tw=78 syn=sgml +vi: ts=1 sw=1 +--> diff --git a/appendices/migration86/other-changes.xml b/appendices/migration86/other-changes.xml new file mode 100644 index 000000000000..3cb6af61bd59 --- /dev/null +++ b/appendices/migration86/other-changes.xml @@ -0,0 +1,585 @@ +<?xml version="1.0" encoding="utf-8"?> +<sect1 xml:id="migration86.other-changes"> + <title>Other Changes</title> + + <sect2 xml:id="migration86.other-changes.core"> + <title>Core changes</title> + + <sect3 xml:id="migration86.other-changes.core.core"> + <title>Core</title> + + <simpara> + In case of a hard <acronym>OOM</acronym> (out of memory) condition, PHP + now calls <literal>abort()</literal> instead of <literal>exit(1)</literal>, + changing the exit code to 134 and possibly creating a core dump. + </simpara> + + <simpara> + The <constant>PHP_OS_FAMILY</constant> constant has an + <literal>AIX</literal> value for when running on AIX or IBM i via PASE. + </simpara> + + </sect3> + + </sect2> + + <sect2 xml:id="migration86.other-changes.sapi"> + <title>Changes in SAPI Modules</title> + + <sect3 xml:id="migration86.other-changes.sapi.cli"> + <title>CLI</title> + + <simpara> + The <link linkend="features.commandline.webserver">built-in development + server</link> now accepts requests using the <acronym>HTTP</acronym> + <literal>QUERY</literal> + method instead of returning <literal>501 Not Implemented</literal>. + </simpara> + + <simpara> + The <link linkend="features.commandline.webserver">built-in development + server</link> no longer reflects the <literal>Host</literal> header from + requests. + </simpara> + + </sect3> + + </sect2> + + <sect2 xml:id="migration86.other-changes.functions"> + <title>Changed Functions</title> + + <sect3 xml:id="migration86.other-changes.functions.core"> + <title>Core</title> + + <simpara> + <function>header_register_callback</function> now declares + <type>true</type> as its return type. + It has not been able to return &false; since PHP 8.0.0, when passing an + invalid callback started throwing a + <exceptionname>TypeError</exceptionname> instead. + </simpara> + + <simpara> + <function>register_tick_function</function> now declares + <type>true</type> as its return type. + It has always returned &true; on success; an invalid callback throws a + <exceptionname>TypeError</exceptionname> during argument parsing before + the function body is reached. + </simpara> + + <simpara> + <function>ini_get_all</function> now includes a + <literal>"builtin_default_value"</literal> element for each directive + when <parameter>details</parameter> is &true;. + It holds the built-in default value of the directive (or &null; if it + has none), independent of values set in &php.ini;, on the command line, + or at runtime. + </simpara> + + <simpara> + <function>fclose</function>, <function>file_put_contents</function> and + <function>copy</function> now return &false; when flushing or closing the + stream fails. + Previously such failures were silently ignored. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.functions.date"> + <title>Date</title> + + <para> + The following methods now have tentative <type>static</type> return + types: + + <simplelist> + <member><methodname>DateTime::createFromInterface</methodname></member> + <member><methodname>DateTimeImmutable::__set_state</methodname></member> + <member><methodname>DateTimeImmutable::modify</methodname></member> + <member><methodname>DateTimeImmutable::add</methodname></member> + <member><methodname>DateTimeImmutable::sub</methodname></member> + <member><methodname>DateTimeImmutable::setTimezone</methodname></member> + <member><methodname>DateTimeImmutable::setTime</methodname></member> + <member><methodname>DateTimeImmutable::setDate</methodname></member> + <member><methodname>DateTimeImmutable::setISODate</methodname></member> + <member><methodname>DateTimeImmutable::setTimestamp</methodname></member> + <member><methodname>DateTimeImmutable::createFromInterface</methodname></member> + <member><methodname>DateTimeZone::__set_state</methodname></member> + <member><methodname>DateInterval::__set_state</methodname></member> + <member><methodname>DatePeriod::__set_state</methodname></member> + </simplelist> + </para> + + </sect3> + + <sect3 xml:id="migration86.other-changes.functions.filter"> + <title>Filter</title> + + <simpara> + The return type of <function>filter_var_array</function> has been + narrowed from + <type class="union"><type>array</type><type>false</type><type>null</type></type> + to <type class="union"><type>array</type><type>false</type></type>. + The function always establishes an array before filtering, so &null; was + never returned. + <function>filter_input_array</function> is unaffected: it still returns + &null; when the requested superglobal does not exist. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.functions.ldap"> + <title>LDAP</title> + + <simpara> + The return type of <function>ldap_free_result</function> has been + narrowed from <type>bool</type> to <type>true</type>. + The function already always returned &true;. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.functions.mysqli"> + <title>MySQLi</title> + + <simpara> + The return structure of <function>mysqli_get_charset</function> no longer + contains the undocumented <literal>"comment"</literal> element. + The value of <literal>"charsetnr"</literal> is now set to a constant + <literal>0</literal> as this number was an implementation detail that + should not have been exposed to the public. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.functions.openssl"> + <title>OpenSSL</title> + + <simpara> + The output of <function>openssl_x509_parse</function> now contains a + <literal>"criticalExtensions"</literal> entry listing all critical + certificate extensions. + </simpara> + + <simpara> + <function>openssl_sign</function> and <function>openssl_verify</function> + now have an additional optional <parameter>salt_length</parameter> + argument that allows controlling the <acronym>RSA</acronym>-PSS salt + length when + <constant>OPENSSL_PKCS1_PSS_PADDING</constant> is used. + It accepts an explicit length or one of the new + <constant>OPENSSL_RSA_PSS_SALTLEN_<replaceable>*</replaceable></constant> + constants. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.functions.pdo-dblib"> + <title>PDO_DBLIB</title> + + <simpara> + When using persistent connections, there is now a liveness check in + <methodname>PDO::__construct</methodname>. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.functions.phar"> + <title>Phar</title> + + <simpara> + <methodname>Phar::mungServer</methodname> now supports reference values. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.functions.readline"> + <title>Readline</title> + + <simpara> + <function>readline_completion_function</function> now declares + <type>true</type> as its return type. + It has always returned &true; on success; an invalid callback throws a + <exceptionname>TypeError</exceptionname> during argument parsing before + the function body is reached. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.functions.reflection"> + <title>Reflection</title> + + <simpara> + The outputs of + <methodname>ReflectionClassConstant::__toString</methodname> and + <methodname>ReflectionConstant::__toString</methodname> now print + <type>bool</type> constant values as <literal>true</literal> and + <literal>false</literal> rather than <literal>1</literal> and an empty + string. + This also affects other ways of printing class constants, e.g. + <methodname>ReflectionClass::__toString</methodname>. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.functions.sockets"> + <title>Sockets</title> + + <simpara> + <function>socket_addrinfo_lookup</function> now has an additional + optional <parameter>error_code</parameter> argument that, when not + &null;, receives the error code on failure (one of the + <constant>EAI_<replaceable>*</replaceable></constant> constants). + </simpara> + + <simpara> + The return type of <function>socket_cmsg_space</function> has been + narrowed from <type class="union"><type>int</type><type>null</type></type> + to <type>int</type>. + Every failure path has thrown a + <exceptionname>ValueError</exceptionname> since PHP 8.0.0, so &null; was + never returned. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.functions.zip"> + <title>Zip</title> + + <simpara> + The return type of <function>zip_entry_close</function> has been narrowed + from <type>bool</type> to <type>true</type>. + The function already always returned &true;. + </simpara> + + </sect3> + + </sect2> + + <sect2 xml:id="migration86.other-changes.extensions"> + <title>Other Changes to Extensions</title> + + <sect3 xml:id="migration86.other-changes.extensions.fileinfo"> + <title>Fileinfo</title> + + <simpara> + Upgraded to file 5.48. + Custom compiled magic databases from older file versions must be + regenerated. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.extensions.hash"> + <title>Hash</title> + + <simpara> + The bundled version of xxHash was upgraded to 0.8.2. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.extensions.mysqli"> + <title>MySQLi</title> + + <simpara> + Added the new constant <constant>MYSQLI_OPT_COMPRESS</constant>. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.extensions.opcache"> + <title>Opcache</title> + + <simpara> + <acronym>JIT</acronym> is now supported for <acronym>ZTS</acronym> builds + on Apple Silicon. + </simpara> + + </sect3> + + </sect2> + + <sect2 xml:id="migration86.other-changes.ini"> + <title>Changes to INI File Handling</title> + + <sect3 xml:id="migration86.other-changes.ini.core"> + <title>Core</title> + + <simpara> + The <!-- <link linkend="ini.error-include-args"> -->error_include_args<!-- </link> --> + INI option has been added to make the display of function arguments + consistent in errors; it is off by default. + Previously, whether a function showed a parameter in the error was up to + each call to the internal error function. + Now, all parameters as they were actually passed to the function will be + displayed. + This uses the same infrastructure as stack traces, so sensitive + parameters will not be displayed, and strings will be truncated + according to + <link linkend="ini.zend.exception-string-param-max-len">zend.exception_string_param_max_len</link>. + <!-- RFC: https://wiki.php.net/rfc/display_error_function_args --> + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.ini.mbstring"> + <title>MBString</title> + + <simpara> + The <link linkend="ini.mbstring.detect-order">mbstring.detect_order</link> + INI directive now updates the internal detection order when changed at + runtime via <function>ini_set</function>. + Previously, runtime changes using <function>ini_set</function> did not + take effect for <function>mb_detect_order</function>. + Setting the directive to &null; or an empty string at runtime now leaves + the previously configured detection order unchanged. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.ini.mysqli"> + <title>MySQLi</title> + + <simpara> + <link linkend="ini.mysqli.default-port">mysqli.default_port</link> now + checks the validity of the value, which should be between + <literal>0</literal> and <literal>65535</literal> inclusive. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.ini.opcache"> + <title>Opcache</title> + + <simpara> + <link linkend="ini.opcache.jit-debug">opcache.jit_debug</link> accepts a + new flag: <literal>ZEND_JIT_DEBUG_TRACE_EXIT_INFO_SRC</literal>. + When used along with <literal>ZEND_JIT_DEBUG_TRACE_EXIT_INFO</literal>, + the source of exit points is printed in the exit info output, in debug + builds. + </simpara> + + </sect3> + + </sect2> + + <sect2 xml:id="migration86.other-changes.performance"> + <title>Performance</title> + + <sect3 xml:id="migration86.other-changes.performance.core"> + <title>Core</title> + + <simpara> + <function>printf</function> using only <literal>%s</literal> and + <literal>%d</literal> will be compiled into the equivalent string + interpolation, avoiding the overhead of a function call and repeatedly + parsing the format string. + </simpara> + + <simpara> + Arguments are now passed more efficiently to known constructors (e.g. + when using <code>new self()</code>). + </simpara> + + <simpara> + <function>array_map</function> using a + <link linkend="functions.first_class_callable_syntax">first-class + callable</link> or + <link linkend="migration86.new-features.core.partial-function-application">partial + function application</link> callback will be compiled into the equivalent + <link linkend="control-structures.foreach">foreach</link> loop, avoiding the + creation of intermediate <classname>Closure</classname>s, the overhead of + calling userland callbacks from internal functions and providing for + better insight for the <acronym>JIT</acronym>. + </simpara> + + <simpara> + The performance of the TAILCALL <acronym>VM</acronym> has been improved, + and it is now enabled on Windows when compiling with Clang 19 or later on + x86_64. + </simpara> + + <simpara> + The performance of <acronym>ZTS</acronym> builds has been improved. + </simpara> + + <simpara> + Added a stateless closure cache. + <!-- RFC: https://wiki.php.net/rfc/closure-optimizations#stateless_closure_caching --> + </simpara> + + <simpara> + Deeply recursive code that causes the VM to allocate new stack pages + should now be faster. + </simpara> + + <simpara> + Improved performance of sorting single-element arrays. + </simpara> + + <para> + Improved performance of the following functions: + + <simplelist> + <member><function>addcslashes</function>, when generating octal escapes</member> + <member><function>array_fill_keys</function></member> + <member><function>array_intersect</function></member> + <member><function>array_map</function>, with multiple arrays passed</member> + <member><function>array_product</function> and <function>array_sum</function>, for integer-only arrays</member> + <member><function>array_unshift</function></member> + <member><function>array_walk</function></member> + <member><function>intval</function>, for <code>intval('0b...', 2)</code> and <code>intval('+0b...', 2)</code></member> + <member><function>pathinfo</function>, when requesting a single component</member> + <member><function>str_pad</function></member> + <member><function>str_repeat</function>, when the multiplier is <literal>1</literal></member> + <member><function>str_split</function></member> + </simplelist> + </para> + + </sect3> + + <sect3 xml:id="migration86.other-changes.performance.dom"> + <title>DOM</title> + + <simpara> + Made <methodname>DOMText::splitText</methodname> and + <methodname>Dom\Text::splitText</methodname> faster and consume less + memory. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.performance.gd"> + <title>GD</title> + + <simpara> + <function>imagebmp</function>, <function>imagewbmp</function>, + <function>imagegd</function>, and <function>imagegd2</function> now + buffer output when writing to PHP streams, significantly improving + performance when writing images to files. + </simpara> + + <simpara> + Improved performance of <function>imagegrabscreen</function> and + <function>imagegrabwindow</function> on Windows. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.performance.intl"> + <title>Intl</title> + + <simpara> + Improved performance of + <methodname>IntlCalendar::getAvailableLocales</methodname> and + <methodname>IntlDateFormatter::localtime</methodname>/<function>datefmt_localtime</function> + by pre-allocating their returned arrays. + </simpara> + + <simpara> + Improved performance of <function>transliterator_list_ids</function> and + <function>resourcebundle_locales</function> by pre-allocating their + returned arrays. + </simpara> + + <simpara> + Optimized callback invocation in + <methodname>IntlChar::enumCharTypes</methodname>. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.performance.json"> + <title>JSON</title> + + <simpara> + Improved performance of encoding arrays and objects. + </simpara> + + <simpara> + Improved performance of indentation generation in + <function>json_encode</function> when using + <constant>JSON_PRETTY_PRINT</constant>. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.performance.mbstring"> + <title>MBString</title> + + <simpara> + Improved performance of <function>mb_str_pad</function>. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.performance.phar"> + <title>Phar</title> + + <simpara> + Reduced temporary allocations when iterating Phar directories. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.performance.uri"> + <title>URI</title> + + <simpara> + Improved performance of <methodname>Uri\WhatWg\Url::parse</methodname> + when collecting validation errors by pre-allocating the error array. + </simpara> + + <simpara> + Reduced allocations when reading IPv6/IPvFuture hosts and paths with + <classname>Uri\Rfc3986\Uri</classname>. + </simpara> + + <simpara> + Improved performance and memory consumption when using normalizing + (non-raw) getters on already-normalized URIs with + <classname>Uri\Rfc3986\Uri</classname>. + </simpara> + + </sect3> + + <sect3 xml:id="migration86.other-changes.performance.zip"> + <title>Zip</title> + + <simpara> + Improved performance of <methodname>ZipArchive::addGlob</methodname> and + <methodname>ZipArchive::addPattern</methodname> by pre-allocating their + returned arrays. + </simpara> + + <simpara> + Avoid string copies in <methodname>ZipArchive::addFromString</methodname>. + </simpara> + + </sect3> + + </sect2> + +</sect1> +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:t +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +indent-tabs-mode:nil +sgml-parent-document:nil +sgml-default-dtd-file:"~/.phpdoc/manual.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +End: +vim600: syn=xml fen fdm=syntax fdl=2 si +vim: et tw=78 syn=sgml +vi: ts=1 sw=1 +--> diff --git a/appendices/migration86/windows-support.xml b/appendices/migration86/windows-support.xml new file mode 100644 index 000000000000..ee6aea1774bf --- /dev/null +++ b/appendices/migration86/windows-support.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?> +<sect1 xml:id="migration86.windows-support"> + <title>Windows Support</title> + + <sect2 xml:id="migration86.windows-support.core"> + <title>Core</title> + + <simpara> + The official Windows builds now use Visual Studio 2026 (VS18). + </simpara> + + </sect2> + + <sect2 xml:id="migration86.windows-support.libxml"> + <title>LibXML</title> + + <simpara> + The libxml2 library used by the official Windows builds has been upgraded + to version 2.15.3. + As a result, <property>DOMDocument::$documentURI</property> for documents + loaded from a local file now contains a native filesystem path instead of + a file <acronym>URI</acronym>. + </simpara> + + </sect2> + + <sect2 xml:id="migration86.windows-support.openssl"> + <title>OpenSSL</title> + + <simpara> + The OpenSSL library used by the official Windows builds has been upgraded + to OpenSSL 4. + </simpara> + + </sect2> + +</sect1> +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:t +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +indent-tabs-mode:nil +sgml-parent-document:nil +sgml-default-dtd-file:"~/.phpdoc/manual.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:nil +sgml-local-ecat-files:nil +End: +vim600: syn=xml fen fdm=syntax fdl=2 si +vim: et tw=78 syn=sgml +vi: ts=1 sw=1 +--> diff --git a/manual.xml b/manual.xml index f393b9f67120..d9302073d28d 100644 --- a/manual.xml +++ b/manual.xml @@ -412,6 +412,7 @@ <title>&Appendices;</title> &appendices.history; &appendices.examples; + &appendices.migration86; &appendices.migration85; &appendices.migration84; &appendices.migration83;

« previous php.doc.cvs (#23841) next »