Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

Nested view renderings

Hi all,

I'm building a system where each page a user sees is defined by a Page object. That Page object can then contain any number of Widget objects. Theoretically, the output the users sees is supposed to be generated by the Page object. Inside the Volt view file will be code that will loop through the Page object’s related Widget objects. Those Widget objects will then render their own template file and generate their own output. Something like:

{% extends 'partials/pages/page.phtml' %}

{% block body %}
    {% for Widget in Widgets %}
        {{ Widget.render() }}
    {% endfor %}
{% endblock %}

The difficulty I'm having is in writing the Widget::render() method. I tried using the View out of the DI and rendering the Widget’s view file that way, but that resulted in only the Widget’s view being displayed - not the Page’s.

Any ideas? I’m willing to completely re-organize how the Widget content gets displayed, if it turns out I’m doing it completely wrong.

UPDATE My render() method looks like this:

$View = \Phalcon\DI\FactoryDefault::getDefault()->get('view');
echo ob_get_clean();

Wrapping $View->render() in an output buffer appears to have solved the problem, and the Widget output is being displayed in the proper context. So, my problem has been solved, but I am interested in better approaches if they exist.

edited Feb '15

Perhaps you should use a Phalcon\Mvc\View\Simple for the widget and if you need nested views inside of the widget then render them and pass in the different view strings to the main simple view? I only use normal views for controller/action destinations. Anything like a widget is best done with the simple view as it is more "simple" in that it just processes the template without any other consideration.

Also, I've found that mixing simple and normal views to use the same Volt service in a single pass can mess things up. This is why I set define my volt service function as $voltFunc = ... and then I use that in the voltService lambda. Then I use it as well in the viewSimple service. The main voltService appears to reuse this for the main views and I've found it not to be appropriate to mix that service with the simple views. Also it causes weird issues when precompiling both types of templates (for a dist/prod build) in the CLI and reusing the voltService. Sorry if I said the same thing too many times.

I thought of using the simple service, but it doesn't have template inheritance - which I know I'll need/want in the future.

edited Feb '15

I thought of using the simple service, but it doesn't have template inheritance - which I know I'll need/want in the future.

I thought it did unless you meant the hierarchy instead of inheritance:

Simple Rendering

Phalcon\Mvc\View\Simple is an alternative component to Phalcon\Mvc\View. It keeps most of the philosophy of Phalcon\Mvc\View but lacks of a hierarchy of files which is, in fact, the main feature of its counterpart.

This component allows the developer to have control of when a view is rendered and its location. In addition, this component can leverage of view inheritance available in template engines such as Volt and others.

Taken from

@BadLuckBurt - You know, I think I did mean hierarchy - but what I actually want is inheritance - which means the Simple rendering might work. Thanks for clarifying.

Glad I could help :)