Reputation: 66717
Is there a way to properly typehint a \SimpleXMLElement? So that I do not have to typehint all what it accesses also a a \SimpleXMLElement?
If I want to have typehinting all the way, I currently have to do it this way:
/**
* @var \SimpleXMLElement $values (this is not! an array, yet it is traversable)
*/
$values = $response->params->param->value->array->data->value;
foreach ($values as $row) {
$row = $row->array->data->value;
/**
* @var \SimpleXMLElement $row
*/
$entry = $row[0];
/**
* @var \SimpleXMLElement $entry
*/
$xmlString = $entry->asXML();
}
This seems utterly verbose and redundant. Is there a way to typehint a SimpleXMLElement so that all what it returns will also be coreclty typehinted?
Upvotes: 1
Views: 553
Reputation: 97898
If you Ctrl-click through to the "definition" of SimpleXMLElement in PHPStorm, you will see that it has a stub class definition which it uses for auto-completion and code analysis.
In older versions of PHPStorm, the overloaded ->
operator was represented in that stub as follows (taken from PHPStorm 9.0):
/**
* Provides access to element's children
* @param $name child name
* @return SimpleXMLElement[]
*/
function __get($name) {}
Note that the return type here is SimpleXMLElement[]
, i.e. "an array of SimpleXMLElement
objects". This allows it to correctly auto-complete if you write something like $node->childName[0]->grandChild[0]->asXML()
, but not if you use the short-hand form of $node->childName->grandChild->asXML()
This could be classed as a bug in the IDE, and was filed in their public tracker as WI-15760, which is now fixed.
As of PHPStorm 2018.1.2, the stub instead declares the return type of __get()
as SimpleXMLElement
and also declares implements ArrayAccess
with offsetGet()
also returning SimpleXMLElement
.
/**
* Provides access to element's children
* @access private Method not callable directly, stub exists for typehint only
* @param string $name child name
* @return SimpleXMLElement
*/
private function __get($name) {}
/**
* Class provides access to children by position, and attributes by name
* @access private Method not callable directly, stub exists for typehint only
* @param string|int $offset
* @return SimpleXMLElement Either a named attribute or an element from a list of children
*/
private function offsetGet ($offset) {}
This should correctly auto-complete for both explicit [0]
and short-hand cases.
(The @access private
is a hack to stop the method showing up in auto-complete results, since you can't actually call $node->__get()
or $node->offsetGet()
in real PHP code.)
Upvotes: 4