PHP 8.1: final
class constants
PHP 8.1 supports the final
flag on class constants.
Constants declared on PHP classes can be overridden by sub classes. Prior to PHP 8.1, the final
flag was not allowed on class constants, which would have protected class constants from being overridden by sub classes. Attempting to use the final
flag on class constants resulted in a fatal error.
In PHP 8.1 and later, the final
flag is allowed on class/interface constants, and none of the sub classes are allowed to extend/override final
constants.
class Foo {
final public const TEST = '1';
}
class Bar extends Foo {
public const TEST = '2';
}
Fatal error: Bar::TEST cannot override final constant Foo::TEST in %s on line %d
final private const
Adding final
flag to a private
constant is not allowed because private
constants/methods/properties cannot be accessed outside the class itself.
Declaring a final private
constant results in a fatal error:
class Foo {
final private const TEST = '1';
}
Fatal error: Private constant Foo::TEST cannot be final as it is never overridden in ... on line ...
Interface constant changes
Prior to PHP 8.1, overriding interface
constants was not allowed, and resulted in a fatal error. This behavior has changed in PHP 8.1.
interface I {
const C = 16;
}
class Cl implements I{
const C = 1;
}
In the snippet above, I::C
constant is overridden by the class Cl
. Although I::C
constant is not declared final
, this was not allowed prior to PHP 8.1:
Fatal error: Cannot inherit previously-inherited or override constant C from interface I in ... on line ...
With the introduction of final
constants in PHP 8.1, classes and interfaces are allowed to override a previously-declared class, unless the constant is declared with a final
flag.
In PHP 8.1, Interfaces constants support the final
flag as well, and attempting to override results in an error, just like it does when overriding a class constant:
interface I {
final public const C = 16;
}
class Cl implements I{
const C = 1;
}
Fatal error: Cl::C cannot override final constant I::C in ... on line ...
The same also applies when an Interface extends another Interface and override a final
constant.
Reflection API Changes
ReflectionClassConstant
class from the Reflection API has a new method isFinal
:
class ReflectionClassConstant {
// ...
public function isFinal(): bool {}
}
ReflectionClassConstant::isFinal
returns a bool
value whether a given class constant is declared final
.
class Foo {
final private const TEST = '1';
}
$reflector = new ReflectionClassConstant(Foo::class, 'TEST');
$reflector->isFinal(); // true
Related Changes
- Constant visibility modifiers (
public const FOO
,private const FOO
, etc) were introduced in PHP 7.1. - PHP 8.0: Inheritance rules are not applied to
private
class methods Thefinal
flag behavior onprivate
class methods changed in PHP 8.0. Prior to PHP 8.0, overriding afinal private
method was not allowed, and resulted in a fatal error. From PHP 8.0 and later, this is allowed (but only forprivate
methods), and PHP emits a PHP warning.
Backwards Compatibility Impact
This is a language-level change, it is not possible to port this feature to older PHP versions. Using final
flag on PHP versions older than 8.1 causes a fatal error:
Fatal error: Cannot use 'final' as constant modifier in ... on line ...
Note that the behavior of Interfaces has changed; PHP 8.1 and later allows re-declaring a non-final Interface constant. Existing code that relied on this behavior and assumed that Interface constants will never be overridden might need to add the final
flag to the Interface constant to ensure it is not overridden in PHP 8.1 and later versions.