PHP 7.4: detect use of `static::$prop` for private static properties
jrfnl opened this issue · comments
Juliette commented
Is your feature request related to a problem?
Happened to come across this lovely PHP 7.4 change, which I cannot find a changelog entry for in the PHP 7.4 UPGRADING guide, nor have I been able to find an RFC to link this too....
What it comes down to is the following:
- If a class declares a
private static
property... - And refers to that
private static
property in a method usingstatic::$prop
... - And the class gets extended...
- And the child class calls the
parent::method()
which usesstatic::$prop
... - You will get a fatal
Error: Cannot access property ChildClass::$prop
error in PHP < 7.4.
As of PHP 7.4.0 this works fine.
Demo: https://3v4l.org/hK3Tn#veoh
Code sample:
<?php
abstract class CrossVersionA {
private static $prop;
public static function bar() {
// Refering to a `private static` property using `self::` is fine.
self::$prop = 10;
}
}
class ChildOkayA extends CrossVersionA {
public static function bar() {
parent::bar();
}
}
abstract class CrossVersionB {
protected static $prop;
public static function bar() {
// Refering to a `protected static` property using `static::` is fine.
static::$prop = 10;
}
}
class ChildOkayB extends CrossVersionB {
public static function bar() {
parent::bar();
}
}
class SometimesCrossVersion {
private static $prop;
public static function bar() {
// Refering to a `private static` property using `static::` is fine if the method is not called from a child class.
static::$prop = 10;
}
}
abstract class NotCrossVersionB {
private static $prop;
public static function bar() {
// Refering to a `private static` property using `static::` is problematic.
static::$prop = 10;
}
}
class ChildError extends NotCrossVersionB {
public static function bar() {
parent::bar();
}
}
ChildOkayA::bar(); // This will work fine.
ChildOkayB::bar(); // This will work fine.
SometimesCrossVersion::bar(); // This will work fine as long as the class is not extended and the method is not called from a child class.
ChildError::bar(); // This will only work in PHP 7.4+.
Describe the solution you'd like
A new sniff which detects this in codebases which need to support PHP < 7.4.
I think the sniff should look for properties declared as private static
and being referenced using static::$prop
.
In my opinion it should then:
- Stay silent if the class is declared as
final
. - Throw an error if the class is declared as
abstract
(even though we don't know for sure that the method is called from the child, but this is the highest risk scenario). - Throw a warning if the class is neither
abstract
orfinal
.
- I intend to create a pull request to implement this feature.