Coder Perfect

In PHP, method declarations must be compatible with parent methods.

Problem

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

What could be the source of this PHP error? What resources can I use to learn more about what it means to be compatible?

Asked by waiwai933

Solution #1

childClass::customMethod() differs from parentClass::customMethod() in terms of arguments and access level (public/private/protected) ().

Answered by davidtbernal

Solution #2

This notice indicates that there are some method calls that could fail at run-time. Assume 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 merely compares $a->foo() to the requirements of A::foo(), which has no parameters. $a, on the other hand, may be an object of class B that requires a parameter, causing the call to fail at runtime.

This, on the other hand, can never fail and does not result in an error.

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

As a result, no method may require more parameters than its parent method.

When type hints do not match, the same message is generated, but PHP is considerably more restricted in this situation. This results in the following 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 appears to be more restrictive than it should be, and I guess it’s because of internals.

Differences in visibility result in a different error, but for the same underlying reason. There is no way for a method to be less apparent than its parent method.

Answered by ldrut

Solution #3

You can also: if you want to preserve OOP form without turning off any errors:

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();
        // ...

    }
}

Answered by Sajjad Shirazy

Solution #4

To elaborate on this mistake in the context of an interface, if you enter hint your function parameters in the following way:

interface A

use Bar;

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

Class B

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

Even if the method parameters are identical, you will get this error if you forget to include the use statement on your implementing class (Class B).

Answered by Spholt

Solution #5

When I tried to extend an existing class from GitHub, I ran across this issue. I’ll try to explain myself by first writing the class as I imagined it should be, and then the class as it currently exists.

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 accomplished

namespace mycompany\CutreApi;

use \vendor\AwesomeApi\ClassOfVendor;

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

This error appears to occur when you use a method that returns a namespaced class and then try to return the same class with a different namespace. Fortunately, I found this solution, although I’m not sure what the value of this feature in PHP 7.2 is; for me, it’s typical to update existing class methods as needed, including redefinition of input parameters and/or changing the method’s behavior.

One disadvantage of the prior approach is that the new methods added in mycompanyCutreApiClassOfVendor were not recognized by IDEs (). So, for the time being, I’ll stick 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, rather of attempting to use the “anything” technique, I created a new one called “getWhatever.” In fact, they’re both performing the same thing, returning a class, but with different namespaces, as I’ve previously described.

I hope this information is useful to someone.

Answered by Ferran

Post is based on https://stackoverflow.com/questions/3115388/declaration-of-methods-should-be-compatible-with-parent-methods-in-php