[doc-en] master: Document the PHP 8.5 backward incompatible changes (#5837)

From: Date: Thu, 10 Sep 2026 13:36:50 +0000
Subject: [doc-en] master: Document the PHP 8.5 backward incompatible changes (#5837)
Groups: php.doc.cvs 
Request: Send a blank email to doc-cvs+get-23737@lists.php.net to get a copy of this message
Author: Louis-Arnaud (lacatoire) Committer: GitHub (web-flow) Pusher: lacatoire Date: 2026-09-10T15:36:47+02:00 Commit: https://github.com/php/doc-en/commit/4fc9f9ea7ba36a383613ede343a0820f5cc46aa2 Raw diff: https://github.com/php/doc-en/commit/4fc9f9ea7ba36a383613ede343a0820f5cc46aa2.diff Document the PHP 8.5 backward incompatible changes (#5837) * Document the PHP 8.5 backward incompatible changes Cover the integer cast warnings, the non-array destructuring warning and the #[\Attribute] target error, plus the trait binding order, the static return type substitution in final classes, the loose comparison of uncomparable objects, the tick handler deactivation, and the SPL ArrayObject and ArrayIterator changes. * Add some links * Add the errors sections and name E_WARNING explicitly The InvalidArgumentException was only recorded in the changelog tables of the two constructors, which say when the behaviour changed, not what the constructor throws; describe it in an errors section on both pages. Name E_WARNING rather than writing "a warning", which the manual states in too many different ways already. Changed paths: M language/oop5/changelog.xml M language/oop5/traits.xml M language/oop5/variance.xml M language/operators/comparison.xml M language/predefined/attributes/attribute.xml M language/types/integer.xml M reference/array/functions/list.xml M reference/funchand/functions/register-tick-function.xml M reference/spl/arrayiterator/construct.xml M reference/spl/arrayobject/construct.xml Diff: diff --git a/language/oop5/changelog.xml b/language/oop5/changelog.xml index 00dd1bb97d99..9580aecbd184 100644 --- a/language/oop5/changelog.xml +++ b/language/oop5/changelog.xml @@ -16,6 +16,22 @@ </row> </thead> <tbody> + <row> + <entry>8.5.0</entry> + <entry> + Changed: A method that returns <type>static</type> may now be overridden + in a <modifier>final</modifier> class to declare <type>self</type> or the + class's own type as its return type, as these are equivalent to + <type>static</type> in a class that cannot be extended further. + </entry> + </row> + <row> + <entry>8.5.0</entry> + <entry> + Changed: <link linkend="language.oop5.traits">Traits</link> are now bound + to a class before its parent class. + </entry> + </row> <row> <entry>8.4.0</entry> <entry> diff --git a/language/oop5/traits.xml b/language/oop5/traits.xml index b9866d6e2b4d..a0582d85e2bb 100644 --- a/language/oop5/traits.xml +++ b/language/oop5/traits.xml @@ -71,6 +71,19 @@ Hello World! by a Trait. The precedence order is that members from the current class override Trait methods, which in turn override inherited methods. </para> + <note> + <simpara> + As of PHP 8.5.0, traits are bound to a class before its parent class; + previously they were bound after. This more closely reflects the copy and + paste semantics of traits. In particular, when a trait and the parent class + both declare a property or constant of the same name, the trait's + definition now takes precedence over the inherited one, whereas earlier + versions raised a fatal error about an incompatible composition. Method + resolution is unaffected. See + <link linkend="migration85.incompatible.core.trait-binding">the migration + guide</link> for details. + </simpara> + </note> <example xml:id="language.oop5.traits.precedence.examples.ex1"> <title>Precedence Order Example</title> <para> diff --git a/language/oop5/variance.xml b/language/oop5/variance.xml index 22cfd92b529a..f5238da577ce 100644 --- a/language/oop5/variance.xml +++ b/language/oop5/variance.xml @@ -136,6 +136,17 @@ Mavrick barks ]]> </screen> </informalexample> + <note> + <simpara> + As of PHP 8.5.0, when a parent method declares <type>static</type> as its + return type, an overriding method in a <modifier>final</modifier> class may + declare <type>self</type> or the class's own type as its return type + instead, since these are equivalent to <type>static</type> in a class that + cannot be extended further. See + <link linkend="migration85.incompatible.core.substitute-final-subclasses">the + migration guide</link> for details. + </simpara> + </note> </sect2> <sect2 xml:id="language.oop5.variance.contravariance"> diff --git a/language/operators/comparison.xml b/language/operators/comparison.xml index b8f8a061d44d..4e89a9156d0f 100644 --- a/language/operators/comparison.xml +++ b/language/operators/comparison.xml @@ -347,6 +347,21 @@ function standard_array_compare($op1, $op2) applied to comparable values. The result of comparing incomparable values is undefined, and should not be relied upon. </simpara> + <note> + <simpara> + As of PHP 8.5.0, loosely comparing an <type>object</type> that is not + comparable (such as an enum, <classname>CurlHandle</classname>, or another + internal class) against a <type>bool</type> using <literal>==</literal> or + <literal>!=</literal> consistently evaluates as if the object were cast to + <type>bool</type>, that is <literal>(bool) $object</literal>. Because such an + object always casts to &true;, it is equal to &true; and not equal to + &false;. Prior to PHP 8.5.0, this only applied when comparing against a + boolean literal (<literal>$object == true</literal>); comparing against a + boolean value held in a variable always returned &false;. See + <link linkend="migration85.incompatible.core.loosely-comparing-object">the + migration guide</link> for details. + </simpara> + </note> </sect2> <sect2 role="seealso"> diff --git a/language/predefined/attributes/attribute.xml b/language/predefined/attributes/attribute.xml index 2e650fc2863e..97c9dbebc3a9 100644 --- a/language/predefined/attributes/attribute.xml +++ b/language/predefined/attributes/attribute.xml @@ -182,6 +182,10 @@ <entry>8.5.0</entry> <entry> Added <constant>Attribute::TARGET_CONSTANT</constant>. + Applying <code>#[\Attribute]</code> to an abstract class, enum, + interface, or trait now triggers a compile-time error (previously + it was only reported at runtime when + <methodname>ReflectionAttribute::newInstance</methodname> was called). </entry> </row> </tbody> diff --git a/language/types/integer.xml b/language/types/integer.xml index ef2256093f0c..8d456474465b 100644 --- a/language/types/integer.xml +++ b/language/types/integer.xml @@ -210,19 +210,24 @@ var_dump(intval(8.1)); // 8 in both cases </programlisting> </example> - <para> + <simpara> If the float is beyond the boundaries of <type>int</type> (usually <literal>+/- 2.15e+9 = 2^31</literal> on 32-bit platforms and <literal>+/- 9.22e+18 = 2^63</literal> on 64-bit platforms), the result is undefined, since the <type>float</type> doesn't have enough precision to give an exact <type>int</type> result. - No warning, not even a notice will be issued when this happens! - </para> + As of PHP 8.5.0, an <constant>E_WARNING</constant> is emitted when a + <type>float</type> that is not representable as an <type>int</type> is + cast to one. Prior to PHP 8.5.0, no diagnostic at all was issued. + </simpara> <note> - <para> + <simpara> <literal>NaN</literal>, <literal>Inf</literal> and <literal>-Inf</literal> will always be zero when cast to <type>int</type>. - </para> + As of PHP 8.5.0, casting them to <type>int</type> emits an + <constant>E_WARNING</constant>, as does casting <constant>NAN</constant> + to any other type. + </simpara> </note> <warning> diff --git a/reference/array/functions/list.xml b/reference/array/functions/list.xml index 4c22c70084fd..c99d23b5510e 100644 --- a/reference/array/functions/list.xml +++ b/reference/array/functions/list.xml @@ -87,6 +87,13 @@ </row> </thead> <tbody> + <row> + <entry>8.5.0</entry> + <entry> + Destructuring a non-array value (other than &null;) now emits an + <constant>E_WARNING</constant>. + </entry> + </row> <row> <entry>7.3.0</entry> <entry> diff --git a/reference/funchand/functions/register-tick-function.xml b/reference/funchand/functions/register-tick-function.xml index 5577bd4b7977..4ef0d72a2f87 100644 --- a/reference/funchand/functions/register-tick-function.xml +++ b/reference/funchand/functions/register-tick-function.xml @@ -49,6 +49,34 @@ </para> </refsect1> + <refsect1 role="changelog"> + &reftitle.changelog; + <informaltable> + <tgroup cols="2"> + <thead> + <row> + <entry>&Version;</entry> + <entry>&Description;</entry> + </row> + </thead> + <tbody> + <row> + <entry>8.5.0</entry> + <entry> + Tick handlers are now deactivated later during request shutdown: after + all shutdown functions and destructors have run, and after the output + handlers have been cleaned up. Previously they were deactivated at the + very beginning of request shutdown, so tick functions were no longer + called during shutdown functions, destructors, or output handling. See + <link linkend="migration85.incompatible.core.tick-handlers">the + migration guide</link> for details. + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + </refsect1> + <refsect1 role="examples"> &reftitle.examples; <para> diff --git a/reference/spl/arrayiterator/construct.xml b/reference/spl/arrayiterator/construct.xml index 4d20239c1299..f568864eed94 100644 --- a/reference/spl/arrayiterator/construct.xml +++ b/reference/spl/arrayiterator/construct.xml @@ -28,9 +28,10 @@ <varlistentry> <term><parameter>array</parameter></term> <listitem> - <para> + <simpara> The array or object to be iterated on. - </para> + Passing an <type>object</type> is deprecated as of PHP 8.5.0. + </simpara> </listitem> </varlistentry> <varlistentry> @@ -46,13 +47,51 @@ </para> </refsect1> + <refsect1 role="errors"> + &reftitle.errors; + <simpara> + As of PHP 8.5.0, throws an + <exceptionname>InvalidArgumentException</exceptionname> if + <parameter>array</parameter> is an enum. + </simpara> + </refsect1> + + <refsect1 role="changelog"> + &reftitle.changelog; + <informaltable> + <tgroup cols="2"> + <thead> + <row> + <entry>&Version;</entry> + <entry>&Description;</entry> + </row> + </thead> + <tbody> + <row> + <entry>8.5.0</entry> + <entry> + Passing an enum as <parameter>array</parameter> now throws an + <exceptionname>InvalidArgumentException</exceptionname>. + </entry> + </row> + <row> + <entry>8.5.0</entry> + <entry> + Passing an <type>object</type> as <parameter>array</parameter> is deprecated. + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + </refsect1> + <refsect1 role="seealso"> &reftitle.seealso; - <para> - <simplelist> - <member><methodname>ArrayIterator::getArrayCopy</methodname></member> - </simplelist> - </para> + <simplelist> + <member><methodname>ArrayIterator::getArrayCopy</methodname></member> + <member><methodname>ArrayIterator::setFlags</methodname></member> + <member><methodname>ArrayObject::__construct</methodname></member> + </simplelist> </refsect1> </refentry> diff --git a/reference/spl/arrayobject/construct.xml b/reference/spl/arrayobject/construct.xml index 3a47cd919637..34324afc797a 100644 --- a/reference/spl/arrayobject/construct.xml +++ b/reference/spl/arrayobject/construct.xml @@ -17,6 +17,14 @@ <para> This constructs a new array <type>object</type>. </para> + <warning> + <simpara> + As of PHP 8.5.0, passing an enum as the <parameter>array</parameter> + parameter throws an <exceptionname>InvalidArgumentException</exceptionname>. + Modifying the <literal>$name</literal> or <literal>$value</literal> + properties of an enum would break engine assumptions. + </simpara> + </warning> </refsect1> <refsect1 role="parameters"> @@ -26,10 +34,11 @@ <varlistentry> <term><parameter>array</parameter></term> <listitem> - <para> + <simpara> The <parameter>array</parameter> parameter accepts an - <type>array</type> or an <type>Object</type>. - </para> + <type>array</type> or an <type>object</type>. + Passing an <type>object</type> is deprecated as of PHP 8.5.0. + </simpara> </listitem> </varlistentry> <varlistentry> @@ -54,6 +63,44 @@ </para> </refsect1> + <refsect1 role="errors"> + &reftitle.errors; + <simpara> + As of PHP 8.5.0, throws an + <exceptionname>InvalidArgumentException</exceptionname> if + <parameter>array</parameter> is an enum. + </simpara> + </refsect1> + + <refsect1 role="changelog"> + &reftitle.changelog; + <informaltable> + <tgroup cols="2"> + <thead> + <row> + <entry>&Version;</entry> + <entry>&Description;</entry> + </row> + </thead> + <tbody> + <row> + <entry>8.5.0</entry> + <entry> + Passing an enum as <parameter>array</parameter> now throws an + <exceptionname>InvalidArgumentException</exceptionname>. + </entry> + </row> + <row> + <entry>8.5.0</entry> + <entry> + Passing an <type>object</type> as <parameter>array</parameter> is deprecated. + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + </refsect1> + <refsect1 role="examples"> &reftitle.examples; <para> @@ -98,11 +145,11 @@ object(ArrayObject)#1 (1) { <refsect1 role="seealso"> &reftitle.seealso; - <para> - <simplelist> - <member><methodname>ArrayObject::setflags</methodname></member> - </simplelist> - </para> + <simplelist> + <member><methodname>ArrayObject::setFlags</methodname></member> + <member><methodname>ArrayObject::getArrayCopy</methodname></member> + <member><methodname>ArrayIterator::__construct</methodname></member> + </simplelist> </refsect1> </refentry>

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