Return type "self" in PHP abstract class
PHP 7.1
I am currently trying to create an abstract class to provide and define and partially implement the functionality of my "child classes".
Here I am using the following construction:
abstract class Parent {
public static function fromDB(string $name = '') {
$instance = new static();
if (!empty($name)) {
$instance->setName($name)->read();
}
return $instance;
}
public abstract function read();
public abstract function setName(string $name): self;
}
Here PHP seems to understand that it is setName($name)
returning an object with a type Parent
, but PhpStorm indicates that read()
it cannot be called as a result, which would be the expected result.
Error message: Reference method not found in the topic class.
I'm not sure if this is a bug in PHP or PhpStorm, or more likely, I don't understand what I am doing ...
I read about late static binding and the following questions that partially discuss this issue, but I couldn't figure out how to fix it:
- Question 1
- Question 2
- Late Static Binding Doc
Thanks for your time and help.
EDIT: As shown below, I am trying to implement in child classes, for example:
public function setName(string $name = null): user {...}
which obviously doesn't work with return self
, but (IMO should) with static
, which is prohibited.
Your code example looks fine in PhpStorm 2017.2 (currently at EAP stage), but shows a warning in 2017.1.4.
This may have been fixed with WI-33991 or one of the related tickets.
You can get and try EAP 2017.2 build anytime from here: http://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Early+Access+Program
It comes with its own 30-day license and can run in parallel with the current version (general IDE settings are stored in separate folders).
self
will always reference the class containing it, never child classes . So when it Parent
says it returns :self
, it expects you to create a function that returns an instance Parent
. You need to have your child class declare that it does this directly. Instead of declaring a child element to setName
be returned :self
(which is an instance Child
), we declare that we are going to return our class Parent
directly. PHP considers this to be perfectly correct ( Child
is an instance Parent
)
We cannot use it :static
here because it static
is a reserved word in class definitions
abstract class ParentTest {
public static function fromDB(string $name = '') {
$instance = new static();
if (!empty($name)) {
$instance->setName($name)->read();
}
return $instance;
}
public abstract function read();
public abstract function setName(string $name): self;
}
class Child extends ParentTest {
public function read() {
}
public function setName(string $name) :ParentTest {
return $this;
}
}
$child = new Child();
The above code works without error
Try changing static , static should indicate that you are returning an extending class that can remove the error.
It's a guess, but it's worth it.
public abstract function setName(string $name): static;
EDIT: Ok, I don't think it will do it, can you provide more information on this? What is the purpose of reading? fromDb? etc.?