Consider the example below. Class a has private const SOMETHING
, but class b has protected const SOMETHING
.
class a {
private const SOMETHING = 'This is a!';
public static function outputSomething() {
return static::SOMETHING ?? self::SOMETHING;
}
}
class b extends a {
protected const SOMETHING = 'This is b!';
}
echo (new b())::outputSomething();
Output:
This is b!
But now if I comment out the definition for SOMETHING
in class b, an error is thrown:
class a {
private const SOMETHING = 'This is a!';
public static function outputSomething() {
return static::SOMETHING ?? self::SOMETHING;
}
}
class b extends a {
//protected const SOMETHING = 'This is b!';
}
echo (new b())::outputSomething();
Output:
Fatal error: Uncaught Error: Cannot access private const b::SOMETHING in {file}.php:7
However, changing the visibility from private const SOMETHING
to protected const SOMETHING
in class a fixes this.
class a {
protected const SOMETHING = 'This is a!';
public static function outputSomething() {
return static::SOMETHING ?? self::SOMETHING;
}
}
class b extends a {
//protected const SOMETHING = 'This is b!';
}
echo (new b())::outputSomething();
Now the output is as expected:
This is a!
I don't understand why php is evaluating b::SOMETHING prior to applying the null coalescing operator, which according to the documentation:
The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.
Since b::SOMETHING is not set, why doesn't the first example work and a consistent visibility is required for the constant in the base class?