Usage of PHP array-routines interfaces
You may achieve your goal with, for example, ArrayAccess implementation. Together with Iterator it will look like:
class ArrayStorage implements Iterator, ArrayAccess
{
private $holder = [];
private $instanceName;
public function __construct($instanceName)
{
if (!class_exists($instanceName)) {
throw new \Exception('Class '.$instanceName.' was not found');
}
$this->instanceName = $instanceName;
}
public function rewind()
{
reset($this->holder);
}
public function current()
{
return current($this->holder);
}
public function key()
{
return key($this->holder);
}
public function next()
{
next($this->holder);
}
public function valid()
{
return false !== $this->current();
}
public function offsetSet($offset, $value)
{
if (!($value instanceof $this->instanceName)) {
throw new \Exception('Storage allows only '.$this->instanceName.' instances');
}
if (is_null($offset)) {
$this->holder[] = $value;
} else {
$this->holder[$offset] = $value;
}
}
public function offsetExists($offset)
{
return isset($this->holder[$offset]);
}
public function offsetUnset($offset)
{
unset($this->holder[$offset]);
}
public function offsetGet($offset)
{
return isset($this->holder[$offset]) ? $this->holder[$offset] : null;
}
}
Procs
So - yes, you are doing instanceof check explicitly, but end user of your class doesn't know about that. It will only be possible to operate on valid instances in context of this storage (you can check this fiddle for usage sample). Concept is like:
$storage = new ArrayStorage('Foo'); //define what we will accept
$storage[] = new Foo; //fine, [] array-writing
$storage['baz'] = new Foo; //fine, key set
foreach ($storage as $key => $value) {
echo($key. ' => '.PHP_EOL.var_export($value, 1).PHP_EOL);
}
//invalid, will not pass. Either throw exception or just ignore:
$storage['bee'] = new Bar;
End fail-check behavior is up to you, but, my opinion, throwing exception is the best choice here as they are catchable, thus, end user may decide what to do in this case. Further option may be to add Countable to the storage, but it won't change generic idea.
And cons
Downside - no, you will not be able to "typehint" it somehow. While it is useful, in doc blocks you still will need to show what kind of entity are you accepting. In terms of general language features, there is arrayof RFC, by Joe Watkins, which was proposed for PHP version 5.6, but, unfortunately, failed. May be it will be reconsidered in next versions releases.