3

I develop with E_STRICT on. When extending a class I sometimes encounter the following fatal error...

Strict Standards: Declaration of [...] should be compatible with that of [...] in [...]

...due to a child method signature not exactly matching its respective parent method signature.

Sometimes, it's simply that the class's documentation isn't accurate or up to date (I've encountered this in PHP's PDO library). Or, there may be little or no documentation. And in either case, downloading and reading the library's C source code can be as frustrating as guesswork.

What can one do to quickly work through these errors, without suppressing E_STRICT?

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Andrew Cheong
  • 29,362
  • 15
  • 90
  • 145
  • possible duplicate of [Strict Standards: Declaration of ' ' should be compatible with ' '](http://stackoverflow.com/questions/17234259/strict-standards-declaration-of-should-be-compatible-with) – T.Todua Jul 11 '14 at 18:02
  • @tazotodua - Actually, I think _that_ is a duplicate of _this_, and not only (or at all) because this was asked a year earlier, but because this is a general question with a general technique for finding signatures to solve any form of this general problem. The "possible duplicate" is only a specific case. – Andrew Cheong Jul 13 '14 at 07:25

2 Answers2

5

You can use the command-line reflection feature to find out the expected signature:

$ php --rc PDO
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • This is great, thanks! I'll try this as soon as I get home. My only concern is that sometimes I develop on shared hosting and shell access isn't available, and I don't always have a PHP installation on my working computer. – Andrew Cheong Aug 15 '12 at 14:00
  • I finally got around to SSH'ing into my server and trying it out. The output is of course more comprehensive than my solution, and well-formatted. Also, it made me realize I was doing something stupid. The reason "I did not see similar markers in my output" is because ``<...>`` gets interpreted as an HTML tag, duh. – Andrew Cheong Aug 17 '12 at 01:21
2

I found an extremely useful article that suggests using PHP's ReflectionClass to introspect what a parent class expects, here: PHP – Reflection Class – Determine Parent Method Signature.

I found no answer providing this tip on Stack Overflow, so I decided to submit this self-answered question with (my own extended version of) the article's sample code.

Use this snippet to learn more about the class you're trying to extend:

<?php

    $className = 'PDO'; // the class you're trying to extend

    echo "<pre>\n";
    echo "CLASS : $className\n\n========\n\n";
    $refClass = new ReflectionClass($className);
    foreach ($refClass->getMethods() as $refMethod) {
        echo "METHOD : " . $refMethod->getName(). "\n\n";
        echo "getNumberOfParameters()         : " . $refMethod->getNumberOfParameters() . "\n";
        echo "getNumberOfRequiredParameters() : " . $refMethod->getNumberOfRequiredParameters() . "\n";
        echo "\n";
        foreach ($refMethod->getParameters() as $refParameter) {
            echo $refParameter . "\n";
        }
        echo "\n--------\n\n";
    }
    echo "</pre>\n";

?>

This outputs, for PHP's PDO class for example:

CLASS : PDO

========

METHOD : __construct

getNumberOfParameters()         : 4
getNumberOfRequiredParameters() : 3

Parameter #0 [  $dsn ]
Parameter #1 [  $username ]
Parameter #2 [  $passwd ]
Parameter #3 [  $options ]

--------

METHOD : prepare

getNumberOfParameters()         : 2
getNumberOfRequiredParameters() : 1

Parameter #0 [  $statment ]
Parameter #1 [  $options ]

--------

METHOD : beginTransaction

getNumberOfParameters()         : 0
getNumberOfRequiredParameters() : 0

[...]

Note how, in the linked article, one sees entries like:

string(37) "Parameter #1 [ <optional> $cache_cb ]"

I did not see similar <optional> markers in my output (using the author's code verbatim), whether it's because I was using a different version of PHP (PHP 5.3.13) or it's something about the underlying PDO library. Suspecting that my issue might have something to do with optional parameters, I sought an alternative way to find out about them using the getNumberOf*Parameters methods(—and indeed my suspicion proved correct).


There are plenty of other useful reflection methods if one desires to output more information, of course. For example, method accessibility via ReflectionMethod::isPrivate, ReflectionMethod::isProtected, etc. Finally, note that the class ReflectionMethod extends ReflectionFunctionAbstract so be sure to check out the parent class's methods too.

Andrew Cheong
  • 29,362
  • 15
  • 90
  • 145