Reputation: 31531
Consider an Active Record implementation which uses a static builder to return instances of a model. Here is a very reduced version of the ModelBuilder and Model classes to demonstrate, with all code irrelevant to the question removed:
class ModelBuilder {
public function __construct($class) {
$this->class = $class
}
private function _execute() {
$result = $pdo->query("SELECT * FROM {$this->class}");
return $result->fetchAll(PDO::FETCH_CLASS, $this->class);
}
public function all() {
return $this->_execute();
}
public function one() {
return $this->_execute()[0];
}
}
class Model {
public static function builder() {
return new ModelBuilder(get_called_class());
}
}
class FooModel extends Model {
}
To get a Foo item we call the FooModel class like this:
$foo = FooModel::builder()->one();
In this case intelligent IDEs (in my case PhpStorm) do not know what type of object $foo
is. I could type-hint the variable /** @var $foo FooModel */
each time I create an object but I would prefer proper type-hinting on the all()
and one()
methods.
What is the proper type hinting to add to the all()
and one()
methods? Note that static
does not work, I believe because ModelBuilder is not an ancestor of the initial called class and it is being called explicitly in the builder()
method.
This particular project is using PHP 5.6, but answers that are PHP 7 specific are welcome as well.
Upvotes: 1
Views: 119
Reputation: 17091
If your models have parent class like BaseModel
- you can use BaseModel
in return block inside doc-block for all
and one
methods, like:
/**
* @return BaseModel Model instance.
*/
public function one() {
return $this->_execute()[0];
}
But in this case - it is just BaseModel
it is not FooModel
nor BooModel
...
You will have access only to BaseModel methods and properties, but not to FooModel specific...
With purpose to have certain model - you have override needed method in child model with proper doc-block, like:
class FooModel extends BaseModel
{
/**
* @return FooModel Foo model instance.
*/
public function one() {
return parent::one();
}
}
Or have doc-block for class, like this:
/**
* @method FooModel one Foo model instance.
*/
class FooModel extends BaseModel
{
}
Or use doc-block /** @var $foo FooModel */
like you've already mentioned.
Upvotes: 1