I think we can break it down into the following problems:
1)
, Iterator:
class Collection implements \Iterator
{
private $elements;
private $key;
public function __construct(array $elements)
{
$this->elements = array_values($elements);
$this->key = 0;
}
public function current()
{
return $this->elements[$this->key];
}
public function next()
{
++$this->key;
}
public function key()
{
return $this->key;
}
public function valid()
{
return array_key_exists(
$this->key,
$this->elements
);
}
public function rewind()
{
$this->key = 0;
}
}
2)
, , , :
<?php
interface HasProhibitedMethods
{
public function prohibitedMethods();
}
, , .
, , :
class Element implements HasProhibitedMethods
{
public function foo()
{
return 'foo';
}
public function bar()
{
return 'bar';
}
public function baz()
{
return 'baz';
}
public function prohibitedMethods()
{
return [
'foo',
'bar',
];
}
}
3)
@akond, ocramius/proxymanager , , - .
Run
$ composer require ocramius/proxymanager
.
:
<?php
use ProxyManager\Factory\AccessInterceptorValueHolderFactory;
class Collection implements \Iterator
{
private $elements;
private $key;
private $proxyFactory;
public function __construct(array $elements)
{
$this->elements = array_values($elements);
$this->key = 0;
$this->proxyFactory = new AccessInterceptorValueHolderFactory();
}
public function current()
{
$element = $this->elements[$key];
if (!$element instanceof HasProhibitedMethods) {
return $element;
}
$prohibitedMethods = $element->prohibitedMethods();
$configuration = array_combine(
$prohibitedMethods,
array_map(function ($prohibitedMethod) {
return function () use ($prohibitedMethod) {
throw new \RuntimeException(sprintf(
'Method "%s" can not be called during iteration',
$prohibitedMethod
));
};
}, $prohibitedMethods)
);
return $this->proxyFactory->createProxy(
$element,
$configuration
);
}
public function next()
{
++$this->key;
}
public function key()
{
return $this->key;
}
public function valid()
{
return array_key_exists(
$this->key,
$this->elements
);
}
public function rewind()
{
$this->key = 0;
}
}
<?php
require_once __DIR__ .'/vendor/autoload.php';
$elements = [
new Element(),
new Element(),
new Element(),
];
$collection = new Collection($elements);
foreach ($collection as $element) {
$element->foo();
}
. , , Collection, , current() , .
.: