Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does E_STRICT do?

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?

like image 966
Anthony Bishopric Avatar asked Jan 09 '13 20:01

Anthony Bishopric


1 Answers

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

like image 192
Mark Amery Avatar answered Oct 15 '22 10:10

Mark Amery