7

I'm actually interested in making sure our codebase is free of errors that would be warned against by PHP's builtin error checking, but I'd like to see exactly what E_STRICT enforces. By extension, what are PHP's "strict standards"? I looked but couldn't find a comprehensive list.

Some strict standards that I know offhand from experience:

  • Warn against calling non-static methods statically
  • Warn against incompatible subclass function signatures
  • Warn against assigning a value by reference

All I know about E_STRICT is that it warns against code which might break forward compatibility, but I'm not sure what that means concretely.

Is there a good resource out there for information on this?

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Anthony Bishopric
  • 1,306
  • 11
  • 23
  • 1
    What is the concrete problem? You are right, that it helps you identify "not so good" code, so which information do you missing? – KingCrunch Jan 09 '13 at 20:31
  • Strict warns you about accessing keys in an array which don't exist, using functions which are deprecated, calling variables which have not been assigned, and calling constants which haven't been defined. – Joshua Burns Jan 09 '13 at 20:33
  • @KingCrunch I am specifically looking for exactly what "not so good" code actually is. I'm glad it does something, but I want to understand what I'm getting myself into. – Anthony Bishopric Jan 09 '13 at 21:30
  • But the messages already tells you, what you did "wrong" (better: What can be better). Do you have questions about that? – KingCrunch Jan 09 '13 at 21:34
  • Nope, that makes sense. It's not an issue of addressing the issues in my code - it's more a question of documentation. FWIW, we have a very large codebase (more than I manage personally) and so telling the other folks I work with what strict standards to expect might help my argument to getting everyone using the same strictness level. The alternative is to say "hey everyone, we're turning up strictness now! you're gonna get a bunch of warnings and you'll need to suck it up." Which I suppose we should do anyway, but having a list of what's actually expected can only help. – Anthony Bishopric Jan 09 '13 at 21:51
  • @KingCrunch I think the question here is very reasonable - if somebody is deciding whether to turn on strict mode, they'd probably like to know *in advance* what things it will warn over and whether they're sensible so that they know whether they're better off with or without it. I tried turning it on recently and quickly turned it off again when the only thing I could find that it objects to is using [abstract static methods](https://bugs.php.net/bug.php?id=53081) - which I and many others think make perfect sense. – Mark Amery Sep 12 '14 at 14:50
  • @MarkAmery I don't think, that you can know everything, that may appear with `E_STRICT` enabled on a legacy codebase. So even if you have a list, it wouldn't help you much. You shouldn't enable it on production systems anyway. Just enable it on your development system, look at the messages, decide what you want to fix. // btw my opinion: abstract statics are in most cases a sign of a bad design and even concrete statics often only exists as a misused replacement for functions. You disagree, I'm fine with that. – KingCrunch Sep 15 '14 at 21:11

1 Answers1

12

E_STRICT and "strict standards" are the same thing. (And they're removed in PHP 7.)

The documentation presently has no list of E_STRICT-specific warnings, but we can construct one reasonably easily by searching the PHP source.

The list below (which I believe to be accurate as of PHP 5.6) was formed on a Unix system via the following methodology:

  1. Cloning the PHP Git repo:

    git clone https://github.com/php/php-src
    
  2. Checking out version 5.6.0:

    cd php-src
    git checkout PHP-5.6.0
    
  3. Searching for all C files (ones with .h and .c extensions) containing E_STRICT:

    grep --include=*.[ch] -rl . -e E_STRICT
    
  4. Manually looking through each of the (21) matched files to find code emitting E_STRICT warnings, attempting to deduce the circumstances in which the warning would be emitted (I'm not a C programmer, but it's not too hard to take a good guess at this stuff, especially with the human-readable error messages right there in the code to guide you) then testing them at the interactive PHP shell to make sure I was right.

Given that the methodology described above is slightly crude and depends upon the assumption that E_STRICT can be found in the source code next to all places where E_STRICT warnings are emitted, it's possible I've missed some stuff - but this is hopefully at least close to being a comprehensive list.

Things in PHP that cause E_STRICT warnings

  1. Calling mktime() with no arguments

    php > mktime();
    PHP Strict Standards:  mktime(): You should be using the time() function
    instead in php shell code on line 1
  2. Using a resource as an array index

    php > $file_pointer = fopen('/dev/null', 'r');
    php > $array = [3,4,5,6];
    php > $array[$file_pointer];
    PHP Strict Standards:  Resource ID#2 used as offset, casting to integer (2)
    in php shell code on line 1
  3. Passing a multi-byte encoding other than UTF-8 to htmlentities

    php > htmlentities('qwertyuiop', 0, 'BIG5');
    PHP Strict Standards:  htmlentities(): Only basic entities substitution is
    supported for multi-byte encodings other than UTF-8; functionality is
    equivalent to htmlspecialchars in php shell code on line 1
  4. Declaring an abstract static method

    php > abstract class Foo { static abstract function bar(); }
    PHP Strict Standards:  Static function Foo::bar() should not be abstract in
    php shell code on line 1
  5. Declaring a class with both a __construct method and an old-style constructor function named after the class

    php > class MyClass {
    php {     function MyClass () {}
    php {     function __construct () {}
    php { }
    PHP Strict Standards:  Redefining already defined constructor for class
    MyClass in php shell code on line 3
  6. Calling mysqli_next_result or mysqli::next_result on a Mysqli connection object that does not have a next result to prepare

    php > $conn = mysqli_connect('127.0.0.1', 'root');
    php > mysqli_multi_query($conn, "SELECT 'first'; SELECT 'second';");
    php > echo mysqli_use_result($conn)->fetch_row()[0];
    first
    php > mysqli_next_result($conn);
    php > echo mysqli_use_result($conn)->fetch_row()[0];
    second
    php > mysqli_next_result($conn);
    PHP Strict Standards:  mysqli_next_result(): There is no next result set.
    Please, call mysqli_more_results()/mysqli::more_results() to check whether
    to call this function/method in php shell code on line 1
  7. Overriding a method in a subclass to take a different number of arguments to the same method in its parent

    php > class A           { public function foo ($x) {} }
    php > class B extends A { public function foo () {} }
    PHP Strict Standards:  Declaration of B::foo() should be compatible with
    A::foo($x) in php shell code on line 1
    php > class C extends A { public function foo ($x, $y) {} }
    PHP Strict Standards:  Declaration of C::foo() should be compatible with
    A::foo($x) in php shell code on line 1
  8. Declaring, compatibly, the same property in a trait and a class that uses it. This one is actually nicely documented:

    If a trait defines a property then a class can not define a property with the same name, otherwise an error is issued. It is an E_STRICT if the class definition is compatible (same visibility and initial value) or fatal error otherwise.

    Example #12 Conflict Resolution

    <?php
    trait PropertiesTrait {
        public $same = true;
        public $different = false;
    }
    
    class PropertiesExample {
        use PropertiesTrait;
        public $same = true; // Strict Standards
        public $different = true; // Fatal error
    }
    ?>
    

    An example of the strict mode warning:

    php > trait PropertiesTrait {
    php {     public $same = true;
    php { }
    php > class PropertiesExample {
    php {     use PropertiesTrait;
    php {     public $same = true;
    php { }
    PHP Strict Standards:  PropertiesExample and PropertiesTrait define the
    same property ($same) in the composition of PropertiesExample. This might
    be incompatible, to improve maintainability consider using accessor
    methods in traits instead. Class was composed in php shell code on line 4
  9. Calling a non-static method statically

    php > class Foo { function bar() {} }
    php > Foo::bar();
    PHP Strict Standards:  Non-static method Foo::bar() should not be called
    statically in php shell code on line 1
  10. Referring to a static property non-statically

    php > class Cow { static public $noise = 'moo'; }
    php > $cow = new Cow;
    php > $cow->noise = "MOOOOO";
    PHP Strict Standards:  Accessing static property Cow::$noise as non static
    in php shell code on line 1
  11. Directly passing the result of a function call by reference.

    php > function foo () { return 1; }
    php > function bar (&$some_arg) {} 
    php > bar(foo());
    PHP Strict Standards:  Only variables should be passed by reference in php
    shell code on line 1
    php > $var = &foo();
    PHP Strict Standards:  Only variables should be assigned by reference in
    php shell code on line 1

    Note that passing other non-variables by reference, like literals or constants, is a fatal error instead of an E_STRICT

Mark Amery
  • 143,130
  • 81
  • 406
  • 459