迭代私有属性中的数组保持

I have the 'Article' class with the private property words which holds and array of Word class objects. I also have getWord method which can return one word:

class Article {
    private $words = Array(1 => new Word(1), 2 => new Word(2), ...);

    public function getWord($wordId) {
        if (array_key_exists($wordId, $this->words)) {
            return $this->words[$wordId];
        } else {
            return NULL;
        }
    }
}

I need to iterate through all exising words. What is the best way to do that?

Currently I'm returning all words as array using another method, but I don't think that is a good option.

If you want to iterate over an Article object, accessing all Word objects, you should implement either the Iterator interface, or IteratorAggregate.

If this is done, iterating would be as easy as this:

foreach ($article as $word) {
    // do stuff with Word object here
}

The easiest way would be to convert your existing getWords method. You could add a new method getIterator as required by the IteratorAggregate interface and implement it like this:

public function getIterator() {
    return new ArrayIterator($this->getWords());
}

If you want to get rid of getWords(), you could also pass the internal array directly.

Your solution is the best an cleanest one. Making getters for private Properties is widely accepted in the OOP. See this stackoverflow entry

A getter looks like this:

public function getWords() {
  return $this->words;
}

If you would that every class can access AND edit the property you can also make it a public property. But as I understand your code other classes and methods should have read only access to this property, so a getter is the definitive best solution.

If you only want to expose some specific word objects of your property then the method would look like:

public function getFilteredWords($param) {
  $tmpWords = array();

  foreach($this->words as $w) {
    if(/*word NOT matches your filter criteria ($param)*/)
      continue;

    $tmpWords[] = $w;
  }

  return $tmpWords;
}