title: Troubleshooting "The (subclass) instance wasn't initialized properly" in custom RecursiveIteratorIterator
body: <p>I have created a custom iterator that extends <code>RecursiveIteratorIterator</code> which I use to iterate over a <code>Doctrine_Collection</code> from a table that uses the <code>NestedSet</code> behavior (e.g., so that I apply custom sorting to records at each level in the hierarchy).</p>
  
  <p>There are a couple of models in my project that leverage this iterator, so I have created a base class that looks like the following:</p>
  
  <pre><code>/** Base functionality for iterators designed to iterate over nested set
   *    structures.
   */
  abstract class BaseHierarchyIterator
    extends RecursiveIteratorIterator
  {
    /** Returns the component name that the iterator is designed to work with.
     *
     * @return string
     */
    abstract public function getComponentName(  );
  
    /** Inits the class instance.
     *
     * @param $objects  Doctrine_Collection Assumed to already be sorted by `lft`.
     *
     * @throws LogicException If $objects is a collection from the wrong table.
     */
    public function __construct( Doctrine_Collection $objects )
    {
      /** @kludge Initialization will fail horribly if we invoke a subclass method
       *    before we have initialized the inner iterator.
       */
      parent::__construct(new RecursiveArrayIterator(array()));
  
      /* Make sure we have the correct collection type. */
      $component = $this-&gt;getComponentName();
      if( $objects-&gt;getTable()-&gt;getComponentName() != $component )
      {
        throw new LogicException(sprintf(
          '%s can only iterate over %s collections.'
            , get_class($this)
            , $component
        ));
      }
  
      /* Build the array for the inner iterator. */
      $top = array();
      /** @var $object Doctrine_Record|Doctrine_Node_NestedSet */
      foreach( $objects as $object )
      {
        // ... magic happens here ...
      }
  
      parent::__construct(
          new RecursiveArrayIterator($top)
        , RecursiveIteratorIterator::SELF_FIRST
      );
    }
  
    ...
  }
  </code></pre>
  
  <p>A subclass might look something like this:</p>
  
  <pre><code>/** Iterates hierarchically through a collection of User objects.
   */
  class UserHierarchyIterator
    extends BaseHierarchyIterator
  {
    /** Returns the component name that the iterator is designed to work with.
     *
     * @return string
     */
    public function getComponentName()
    {
      return UserTable::getInstance()-&gt;getComponentName();
    }
  
    ...
  }
  </code></pre>
  
  <p>Note the <code>@kludge</code> at the top of the constructor in the base class:</p>
  
  <pre><code>/** @kludge Initialization will fail horribly if we invoke a subclass method
   *    before we have initialized the inner iterator.
   */
  parent::__construct(new RecursiveArrayIterator(array()));
  </code></pre>
  
  <p>As long as I keep that extra initialization line at the top of the base class' constructor, everything works as expected.</p>
  
  <p>However, if I remove/comment that line, I get the following error as soon as script execution gets to <code>$component = $this-&gt;getComponentName()</code>:</p>
  
  <blockquote>
    <p>Fatal error: BaseHierarchyIterator::__construct(): The UserHierarchyIterator instance wasn't initialized properly in /path/to/BaseHierarchyIterator.class.php on line 21.</p>
  </blockquote>
  
  <p>Alternatively, if I remove the code that calls <code>$this-&gt;getComponentName()</code> (and the subsequent conditional block), the constructor still operates as expected (minus the check to make sure the component name is correct).</p>
  
  <p>What is the root cause of this error?  Is there a better workaround for this issue?</p>
  
  <p>PHP version info:</p>
  
  <pre>
  PHP 5.3.3 (cli) (built: Jul  3 2012 16:40:30) 
  Copyright (c) 1997-2010 The PHP Group
  Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
      with Suhosin v0.9.29, Copyright (c) 2007, by SektionEins GmbH
  </pre>