Ich weiß, ich bin spät dran, aber ich habe mich in letzter Zeit mit diesem Problem beschäftigt. Ich hoffe, jemand sieht dies, denn die akzeptierte Antwort, obwohl korrekt, ist nicht die beste Art und Weise, wie Sie dies tun können. Zumindest nicht in PHPStorm, NetBeans habe ich allerdings nicht getestet.
Am besten ist es, die Klasse ArrayIterator zu erweitern, anstatt native Array-Typen zu verwenden. Dies ermöglicht es Ihnen, Hinweise auf Klassenebene und nicht auf Instanzebene zu geben, was bedeutet, dass Sie PHPDoc nur einmal und nicht im gesamten Code verwenden müssen (was nicht nur unordentlich ist und gegen DRY verstößt, sondern auch problematisch sein kann, wenn es um Refactoring geht - PHPStorm hat die Angewohnheit, PHPDoc beim Refactoring zu übersehen)
Siehe Code unten:
class MyObj
{
private $val;
public function __construct($val) { $this->val = $val; }
public function getter() { return $this->val; }
}
/**
* @method MyObj current()
*/
class MyObjCollection extends ArrayIterator
{
public function __construct(Array $array = [])
{
foreach($array as $object)
{
if(!is_a($object, MyObj::class))
{
throw new Exception('Invalid object passed to ' . __METHOD__ . ', expected type ' . MyObj::class);
}
}
parent::__construct($array);
}
public function echoContents()
{
foreach($this as $key => $myObj)
{
echo $key . ': ' . $myObj->getter() . '<br>';
}
}
}
$myObjCollection = new MyObjCollection([
new MyObj(1),
new MyObj('foo'),
new MyObj('blah'),
new MyObj(23),
new MyObj(array())
]);
$myObjCollection->echoContents();
Der Schlüssel dazu ist die PHPDoc @method MyObj current()
Überschreibung des von ArrayIterator geerbten Rückgabetyps (der mixed
). Die Einbeziehung dieses PHPDoc bedeutet, dass wir bei der Iteration über die Klasseneigenschaften mit foreach($this as $myObj)
erhalten wir die Code-Vervollständigung, wenn wir uns auf die Variable $myObj->...
Für mich ist dies der sauberste Weg, um dies zu erreichen (zumindest bis PHP Typed Arrays einführt, falls dies jemals der Fall sein wird), da wir den Iterator-Typ in der Iterable-Klasse deklarieren und nicht in Instanzen der Klasse, die im Code verstreut sind.
Ich habe hier nicht die vollständige Lösung für die Erweiterung von ArrayIterator gezeigt, wenn Sie also diese Technik verwenden, möchten Sie das vielleicht auch:
- Fügen Sie bei Bedarf weitere PHPDoc auf Klassenebene ein, z. B. für Methoden wie
offsetGet($index)
y next()
- Verschieben Sie die Plausibilitätsprüfung
is_a($object, MyObj::class)
aus dem Konstruktor in eine private Methode
- Rufen Sie diese (jetzt private) Sicherheitsüberprüfung von Methodenüberschreibungen wie
offsetSet($index, $newval)
y append($value)