117
Strict Standards: Declaration of childClass::customMethod() should be compatible with that of parentClass::customMethod()

What are possible causes of this error in PHP? Where can I find information about what it means to be compatible?

waiwai933
  • 14,133
  • 21
  • 62
  • 86
  • notJim has it exactly right. @waiwai933, if you could post the headers (just the first line: `function customMethod( ... )`) for each function we could tell you the specific problem – nickf Jun 25 '10 at 03:41
  • More details about the error message and PHP compile time implications: https://bugs.php.net/bug.php?id=46851 – hakre May 21 '13 at 09:15
  • 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
  • 1
    My problem was that an argument was type-hinted but then I hadn't added `use Closure;` to the top of my class (since the type-hint was `Closure`). So... be sure to check whether you're missing dependencies like that. – Ryan Aug 27 '17 at 00:51

5 Answers5

131

childClass::customMethod() has different arguments, or a different access level (public/private/protected) than parentClass::customMethod().

davidtbernal
  • 13,434
  • 9
  • 44
  • 60
  • 1
    probably its because the _visibility_, methods signature isn't an issue in PHP – Gabriel Sosa Jun 25 '10 at 03:42
  • 47
    Having the same exact argument default values is important as well. For example, `parentClass::customMethod($thing = false)` and `childClass::customMethod($thing)` would trigger the error, because the child's method hasn't defined a default value for the first argument. – Charles Jun 25 '10 at 04:19
  • 1
    I believe visibility is actually a different error. By the way, at my shop we don't use strict mode, because of this (we use E_ALL, IIRC). – davidtbernal Jun 25 '10 at 07:01
  • 12
    This has changed in PHP 5.4, btw: * E_ALL now includes E_STRICT level errors in the error_reporting configuration directive. See here: http://php.net/manual/en/migration54.other.php – Duncan Lock Nov 17 '12 at 01:08
  • 2
    Missing an ampersand (`&`) in the arguments can trigger this error too. – IvanRF Aug 21 '14 at 20:34
  • @GabrielSosa, nowadays it is an issue. – Pere Oct 30 '14 at 09:33
  • also triggered by type hinting. `parent::method(array $var)` and `child::method($var)` would trigger it – chiliNUT Mar 11 '16 at 00:25
  • Just to make it clear, different arguments also include fewer arguments. Although you don't need them you should declare them. – PhoneixS Oct 11 '17 at 16:06
39

This message means that there are certain possible method calls which may fail at run-time. Suppose you have

class A { public function foo($a = 1) {;}}
class B extends A { public function foo($a) {;}}
function bar(A $a) {$a->foo();}

The compiler only checks the call $a->foo() against the requirements of A::foo() which requires no parameters. $a may however be an object of class B which requires a parameter and so the call would fail at runtime.

This however can never fail and does not trigger the error

class A { public function foo($a) {;}}
class B extends A { public function foo($a = 1) {;}}
function bar(A $a) {$a->foo();}

So no method may have more required parameters than its parent method.

The same message is also generated when type hints do not match, but in this case PHP is even more restrictive. This gives an error:

class A { public function foo(StdClass $a) {;}}
class B extends A { public function foo($a) {;}}

as does this:

class A { public function foo($a) {;}}
class B extends A { public function foo(StdClass $a) {;}}

That seems more restrictive than it needs to be and I assume is due to internals.

Visibility differences cause a different error, but for the same basic reason. No method can be less visible than its parent method.

ldrut
  • 3,807
  • 1
  • 17
  • 4
  • 3
    in your last example - there shouldn't be an error here because it is legit, stdClass $a is more restrictive than mixed $a. is there a way to get around this? i mean in this case PHP should allow this but it still gives an error... – galchen Dec 22 '12 at 17:38
  • 2
    Your last example is type-safe, so it certainly is "more restrictive than it needs to be". This may be a case of cargo-cult programming, since it conflicts with polymorphism in C++ and Java http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#Contravariant_method_argument_type – Warbo Apr 28 '14 at 16:34
  • thanks for the explanation, in my case the first example you gave was exactly what was triggering my error. – But those new buttons though.. Jun 12 '18 at 01:37
  • Thank you for this, sir. – Eldoïr Jul 10 '18 at 08:41
25

if you wanna keep OOP form without turning any error off, you can also:

class A
{
    public function foo() {
        ;
    }
}
class B extends A
{
    /*instead of : 
    public function foo($a, $b, $c) {*/
    public function foo() {
        list($a, $b, $c) = func_get_args();
        // ...

    }
}
Sajjad Shirazi
  • 2,657
  • 26
  • 24
  • I would love to use this hack to get around these errors. I worry that there might be a performance penalty to this approach? I'll research this but if you have any resources to help answer that question, that'd be great. – Adam Friedman Feb 09 '15 at 21:18
  • Depends on the situation I guess. Still Yes it maybe a bit hacky, but it's php? already, sometimes that can be a nice work around, thanks! <@ – Master James Jan 10 '17 at 14:38
  • you saved my day! this was the only option to launch legacy php5 project on server with php7 without pain – vladkras Jun 04 '19 at 14:37
  • For this case you can use default values instead of `func_get_args()`, i.e., in `B`, `public function foo($a = null, $b = null, $c = null)`, as this does not break the contract promised by `A`. – Jake Oct 22 '19 at 00:01
2

Just to expand on this error in the context of an interface, if you are type hinting your function parameters like so:

interface A

use Bar;

interface A
{
    public function foo(Bar $b);
}

Class B

class B implements A
{
    public function foo(Bar $b);
}

If you have forgotten to include the use statement on your implementing class (Class B), then you will also get this error even though the method parameters are identical.

Spholt
  • 3,724
  • 1
  • 18
  • 29
0

I faced this problem while trying to extend an existing class from GitHub. I'm gonna try to explain myself, first writing the class as I though it should be, and then the class as it is now.

What I though

namespace mycompany\CutreApi;

use mycompany\CutreApi\ClassOfVendor;

class CutreApi extends \vendor\AwesomeApi\AwesomeApi
{
   public function whatever(): ClassOfVendor
   {
        return new ClassOfVendor();
   }
}

What I've finally done

namespace mycompany\CutreApi;

use \vendor\AwesomeApi\ClassOfVendor;

class CutreApi extends \vendor\AwesomeApi\AwesomeApi
{
   public function whatever(): ClassOfVendor
   {
        return new \mycompany\CutreApi\ClassOfVendor();
   }
}

So seems that this errror raises also when you're using a method that return a namespaced class, and you try to return the same class but with other namespace. Fortunately I have found this solution, but I do not fully understand the benefit of this feature in php 7.2, for me it is normal to rewrite existing class methods as you need them, including the redefinition of input parameters and / or even behavior of the method.

One downside of the previous aproach, is that IDE's could not recognise the new methods implemented in \mycompany\CutreApi\ClassOfVendor(). So, for now, I will go with this implementation.

Currently done

namespace mycompany\CutreApi;

use mycompany\CutreApi\ClassOfVendor;

class CutreApi extends \vendor\AwesomeApi\AwesomeApi
{
   public function getWhatever(): ClassOfVendor
   {
        return new ClassOfVendor();
   }
}

So, instead of trying to use "whatever" method, I wrote a new one called "getWhatever". In fact both of them are doing the same, just returning a class, but with diferents namespaces as I've described before.

Hope this can help someone.

Ferran
  • 189
  • 2
  • 7