Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP 7.4: detect use of static::$prop for private static properties #1685

Open
1 task
jrfnl opened this issue Mar 7, 2024 · 0 comments
Open
1 task

PHP 7.4: detect use of static::$prop for private static properties #1685

jrfnl opened this issue Mar 7, 2024 · 0 comments

Comments

@jrfnl
Copy link
Member

jrfnl commented Mar 7, 2024

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 using static::$prop...
  • And the class gets extended...
  • And the child class calls the parent::method() which uses static::$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 or final.
  • I intend to create a pull request to implement this feature.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant