无限地寻找父母的对象

I'm propably too tired but I've been wrestling with this one for a while. A container can either have a layout on its own, or it can have a parent somewhere up the hierarchy that has a layout. I need to find that layout no matter how far up the line it is.

The object $container has a property $parent which, if not null, references another $container object (same type).

I think this code has a problem in the while condition?

private function findInheritedLayout($container) {

    do {
        if ( $container->getLayoutTemplate() ) {
            return $container->getLayoutTemplate();
        }
        else {
            if ( $container->getParent() ) {
                $container = $container->getParent();
            }
            else {
                return null;
            }   
        }
    } while ( $container->getParent() ); //flawed? looks for a parent one step too far?
}

Your assumption is correct. The while condition checks if the current $container has a parent, without checking for a layout.

Try the following:

while (!$container->getLayoutTemplate() && $container->getParent()) {
    $container = $container->getParent();
}

$template = $container->getLayoutTemplate();
return $template ?: null;

The Test:

$test = new View('A');
$test->assign('A', new View('B'));
$test->assign('B', $test2 = new View('C'));
$test2->assign('D', $test3 = new View('E'));
$test3->assign('F', $searchTarget = new View('G'));

$root = RootViewIterator::findRootOf($searchTarget);

var_dump($root->getName());

The Result:

string(1) "A"

The Iterator:

class RootViewIterator
    implements Iterator
{

    protected $view;
    protected $startView;
    protected $key = 0;

    public function __construct(View $view)
    {
        $this->view = $view;
        $this->startView = $view;
    }

    public function next()
    {
        $this->view = $this->view->getParent();
        $this->key++;
    }

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

    public function current()
    {
        return $this->view;
    }

    public function rewind()
    {
        $this->view = $this->startView;
        $this->key = 0;
    }

    public function valid()
    {
        return null !== $this->view;
    }

    public static function findRootOf(View $view)
    {
        $result = iterator_to_array(new static($view));

        end($result);

        return current($result);
    }

}

The View:

class View
{
    protected $name;
    protected $items;
    protected $parent;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }

    public function assign($key, $content)
    {
        if ( $content instanceof View ) {
            $content->setParent($this);
        }

        $this->items[$key] = $content;
    }

    public function setParent(View $view)
    {
        $this->parent = $view;
    }

    public function getParent()
    {
        return $this->parent;
    }

    public function hasParent()
    {
        return !empty($this->parent);
    }
}