> 1) Point taken. > > 2) The use case can be solved with an object implementing ArrayAccess, but > not pragmatically, because then you need a class for > *each* bidirectional association. Let me give a short example: > > Given the class Article with a bidirectional many-to-one relation to Category > and a bidirectional many-to-many relation to Tag, > currently you implement the following methods to manage these relations: > > Article::setCategory($category); > Article::addTag($tag); > > Category::addArticle($article); // calls $article->setCategory($category) > > Tag::addArticle($article); // calls $article->addTag($tag) > > (there are different ways to implement this, but usually at least one side of > the relation also calls the setter/adder on the other > side) > > You *cannot* implement the $articles collection in Category and Tag using the > same class ArticleCollection, because in one case > addArticle($article) calls setCategory($category), in the other addTag($tag). > In other words, ArticleCollection depends both on the > related class (Category, Tag) and the arity (setXxx() vs. addXxx()) of the > relation. Consequently, every relation needs a custom > collection class and you end up with the classes > > Article > Category > Tag > ArticleTags > CategoryArticles > TagArticles > > just for this simple example if following your approach. > > With array accessors, this can be solved much more elegantly: > > class Article { > public $category { > set(); > get(); > } > > public $tags { > offsetSet(); > offsetGet(); > } > } > > class Category { > public $articles { > offsetSet($offset, $article) { > $this->_articles[$offset] = $article; > $article->category = $this; > } > offsetGet(); > } > } > > class Tag { > public $articles { > offsetSet($offset, $article) { > $this->_articles[$offset] = $article; > $article->tags[] = $this; > } > offsetGet(); > } > } > > $article->category = $category; > $article->tags[] = $tag; > > $category->articles[] = $article; // sets $article->category = $category > > $tag->articles[] = $article; // adds $article->tags[] = $tag > > (I know that this example has some flaws, like the automatic > offsetGet() or the missing $_articles field, but I guess you get my > point) >
I appreciate the desire to have these functions within accessors but I personally feel they would deviate from the purity of accessors moreso than they already are (unset/isset) and also the reasons for point #1. I'm not sure if your use case above is a specific problem you are trying to solve or if it's just an example of what it would allow, but if I may be so bold as to offer an alternative single-class solution to the collection problem you mention above. class SharedPropertyCollection implements ArrayAccess { public __construct($property, $object) { $this->PropertyName = $property; $this->PropertyValue = $object; } public offsetSet($offset, $object) { $this->_store[$offset] = $object; $object->{$this->ProperyName} = $this->PropertyValue } } Caveat: I'm not sure that $object->{$this->PropertyName} is legal, I haven't played with that new feature yet but if not, I'm sure you know the workaround to that issue. The example class above could obviously be extended to share multiple properties. It also has the additional advantage of decoupling. Your example above has a very high class interdependency issue. See if you can drum up any other interest in this feature/aspect... > 3) I don't know if many other languages allow overloading of the array > accessors at all. Many other languages offer overloading but they refer to it as operator overloading. C++ for example (the first language I learned) has operator overloading for any operator (=, ==, [], etc). I *wish as much as I could* that PHP would allow such flexibility. SPL has really helped a lot in that area. > > Cheers, > Bernhard