Использование PHP массивов рутин интерфейсов
Вы можете достичь своей цели с, например, ArrayAccess
реализации. Вместе с Iterator
он будет выглядеть следующим образом:
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
Так что - да, вы делаете instanceof
проверку в явном виде, но конечный пользователь вашего класса не знает об этом. Это возможно только для действительных экземпляров в контексте этого хранилища (вы можете проверить this fiddle для примера использования). Концепция, как:
$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 поведение отказоустойчивость проверка до вас, но, мое мнение, выбрасывая исключение является лучшим выбором здесь, поскольку они catchable, таким образом, конечный пользователь может решить, что делать в этом случае , Дополнительным вариантом может быть добавление Countable
к хранилищу, но это не изменит общую идею.
И минусы
Даунсайд - нет, вы не сможете "typehint" это как-то. Хотя это полезно, в блоках doc вам все равно нужно будет указать, какую сущность вы принимаете. С точки зрения общих особенностей языка, существует arrayof RFC, Джо Уоткинс, который был предложен для PHP версии 5.6, но, к сожалению, не удалось. Может быть, это будет пересмотрено в версиях следующих версий.
Это именно то, что я искал! Спасибо за ваш ответ. – liopic
После некоторых экспериментов я обнаружил, что подписи 'attach()' и 'detach()' НЕ могут быть изменены, поэтому это должно быть 'attach ($ rule, $ inf = null)' ... но, конечно, вы можете сделать проверка типа внутри метода. – liopic