Home > Blockchain >  PhpStorm: what is the best way to handle "return value is expected to be ..." warning?
PhpStorm: what is the best way to handle "return value is expected to be ..." warning?

Time:12-01

My PHP code is structured to be something like follows (this structure is unchangeable):

class BaseFooClass {
}

class ChildFooClass1 extends BaseFooClass {
}

class ChildFooClass2 extends BaseFooClass {
}

//... (there are like a hundred child foo classes)

class BaseBarClass {
    protected function getFooBase($input) : BaseFooClass 
    {
        $class = "ChildFooClass" . $input;
        return new $class();
    }
}

class ChildBarClass1 extends BaseBarClass {
    public function getFoo() : ChildFooClass1 
    {
        return $this->getFooBase(1);
    }
}

Now in the getFoo() function in ChildBarClass1, PhpStorm will give the warning "Return value is expected to be 'ChildFooClass1', 'BaseFooClass' returned " and it correctly does so.

However I want a clean code with no warning without changing this structure.

I tried the following by adding PHP doc:

    public function getFoo() : ChildFooClass1 
    {
        /** @var ChildFooClass1 $foo **/
        $foo = $this->getFooBase(1);
        return $foo;
    }

However this time it gives a different warning "Unnecessary local variable" and ask me to inline it back.

Is there a good way to get rid of the warnings?

EDIT: the following is tried too but still the warning of "Return value is expected ..." is showing up.

    /**
     * @return ChildFooClass1
     */
    public function getFoo() : ChildFooClass1 
    {
        return $this->getFooBase(1);
    }

CodePudding user response:

Given your code BaseBarClass::getFooBase() returns a BaseFooClass while ChildBarClass1::getFoo() wants to return a ChildFooClass1.

This violates php's Covariance/Contravariance rules, by which you can only return a more specifc type not a more general type, of which PhpStorm correctly warns you about.

So you could either adhere to this rule (good) and refactor your code or suppress the error (bad).

E.g.:

// corrected type:
class ChildBarClass1 extends BaseBarClass
{
    public function getFoo(): BaseFooClass
    {
        return $this->getFooBase(1);
    }
}

// error suppressed:
class ChildBarClass1 extends BaseBarClass
{
    public function getFoo(): ChildFooClass1
    {
        /** @noinspection PhpIncompatibleReturnTypeInspection */
        return $this->getFooBase(1);
    }
}
  • Related