We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Widgets implementation.

Hey there. I've stumbled upon a pretty weird situation while implementing a widgets support.

So the setup is as basic as this: I've created a blank new project and added as per now, 2 namespaces:

'Library'               => __DIR__ . '/../app/libraries/',
'Widget'                => __DIR__ . '/../app/widgets/',

Then, I've created the widget manager which loads the requested widget.

<?php

namespace Library;

class WidgetManager {

    public static function load($widgetNamespace, $params = array()) {
        $class = '\\Widget\\' . $widgetNamespace;

        return new $class($params);
    }

} 

After that, I had to register the custom Volt function in my services.php

$compiler = $volt->getCompiler();
$compiler->addFunction('render_widget', function($args){
          return '\\Library\\WidgetManager::load(' . $args . ')->getContent()';
});

Then I've created a really simple widget, to test it out:

<?php

namespace Widget\Frontend;

class Demo extends \Phalcon\DI\Injectable {

    public function getContent() {
        $this->view->start();
        $this->view->render('widgets', 'Frontend/Demo');
        $this->view->finish();

        print $this->view->getContent();
    }

}

Calling the widget as it is:

{% extends 'layouts/frontend.volt' %}

{% block content %}
    {{ render_widget('Frontend\Demo') }}
{% endblock %}

worked fine at first. But, once I added my HTML code to my layout, calling my widget causes a recursion of its output. I've tried to delete the cached templates, I've enabled compileAlways as well. I call my widget once only in my index.volt template which extends my layout.

I really have no idea what could cause the recursion, since it was working just fine. Any kind of help/advice would be really appriciated.

edited Aug '14

I think you shoulr return the view contents, rather than printing it:

class Demo extends \Phalcon\DI\Injectable {

    public function getContent() {
        $this->view->start();
        $this->view->render('widgets', 'Frontend/Demo');
        $this->view->finish();

        return $this->view->getContent();
    }

}

Other than that, I can't see what's wrong. Can you post the compiled templates?

EDIT: nevermind, I'm wrong about the return, this is not Twig :)

EDIT2 and OT: @phalcon i think the reputation decreases if I edit my post too quickly. I was at 942, I'm back at 877.



1.1k

Hey, thanks for your reply. Returning/printing the output, causes recursion all over again.

The html is really simple, just for the tests.

index.volt

{% extends 'layouts/frontend.volt' %}

{% block content %}
    {{ render_widget('Frontend\Demo') }}
{% endblock %}

widgets/Frontend/Demo.volt

<h1>Demo here</h1>

But the fact is, that I cant even see the outpuf of my widget. The HTML of my layout gets in the recursion.



1.1k

Alright, a started over once again, in order to properly find whats bugging my application so hard, and I've got it.

Everything with the widgets is working just fine, as it turn outs. The moment I added new namespace for my Controllers everything went wrong.

$loader->registerNamespaces([
        'Controller\Frontend'   => ROOT . '/app/controllers/Frontend/',

So far so good. But since I'm now using a namespace convention, $this->view can no longer find the desired template on its own.

So in my Controller, I've called it manually like that:

<?php

namespace Controller\Frontend;

class HomeController extends \Phalcon\Mvc\Controller {

    public function indexAction() {
        $this->view->pick('index/index');
    }

}

And this is what is causing the recursion. Adding

$view->setRenderLevel(View::LEVEL_ACTION_VIEW);

doesnt help either. Any advice what to do?

Thanks.