I'm wondering if an object belonging to a collection class, whilst being iterated on can know it's being iterated and know about the collection class it belongs to? e.g.
<?php
class ExampleObject
{
public function myMethod()
{
if( functionForIterationCheck() ) {
throw new Exception('Please do not call myMethod during iteration in ' . functionToGetIteratorClass());
}
}
}
$collection = new CollectionClass([
new ExampleObject,
new ExampleObject,
new ExampleObject
]);
foreach($collection as $item) {
$item->myMethod(); //Exception should be thrown.
}
(new ExampleObject)->myMethod(); //No Exception thrown.
I've done some Google'ing and couldn't find anything, I'm guessing it's not possible because it breaks an OOP principal somewhere but thought I'd ask anyway!
I think we can split this into the following problems:
Collection
that is iterableThe
Collection
shoulda. have the names of prohibited methods hard-coded (bad) or
b. be able to fetch the names of prohibited methods from the elements of the collection
when iterating over the collection, it should yield proxies to the original object, intercepting calls to methods which should not be allowed to be called when iterating over the collection
1) Collection should be iterable
This is easy, just make it implement the
Iterator
interface:2) Collection should be able to fetch methods from elements
Rather than hard-coding the prohibited methods into the collection, I would suggest to create an interface, and have that be implemented by the elements of the collection, if need be, for example:
This also has the advantage that the collection would work with all kinds of elements, as long as it is able to fetch that information from the element.
Then have your elements, if need be, implement the interface:
3) When iterating, yield proxies
As suggested in a different answer by @akond, you could use
ocramius/proxymanager
, and specifically, an Access Interceptor Value Holder Proxy.Run
to add it to your project.
Adjust the collection as follows:
Example
Note This can still be optimized, for example, you could store references to the created proxies in the
Collection
, and instead of creating new proxies every time,current()
could return previously created proxies, if need be.For reference, see: