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

Data in View Partials

Hello to all

How can I share variables to several controllers?

In my layout I have a box that lists the latest 10 news site, and another (menu) that lists the categories of news.

I have to put on each controller:

$ this->view->menuItens = Menus :: find (array ('order' => 'order DESC' ));

$ this->view->categories = Categories :: find (array ('order' => 'title DESC' ));

Has somehow I do this just one time? And this variable be available in all controllers?

Thanks!

You should extend BaseController which you need to implement initialize() or onConstruct() method

class BaseController extend \Phalcon\Mvc\Controller 
{
    public function initialize()
    {
        $ this->view->menuItens = Menus :: find (array ('order' => 'order DESC' ));
        $ this->view->categories = Categories :: find (array ('order' => 'title DESC' ));
    }
}

Thanks for responding.

This works, and I've thought and use that, but I think that is not correct.

initialize() is called before the action, in some actions I do not show the view layer, eg sending a form email with redirect, save data with redirects etc ...

the ideal would be to function with these methods occur after the action.

Okay that does not affect anything, but in cases of redirects, this processing is not necessary, would have a way to avoid them?

Ideally a finalize () function in the controller, which would only be called if there is no redirects in Action.

Thanks!

Why don't you use Menus::find in your view tempate? It will be used only when view will be used

<ul>
<?php foreach(Menus::find() as $menu) { ?>
    <li><a href="/<?= $menu->slug ?>"><?= $menu->name ?></a></li>
<?php } ?>
</ul>

Again thanks for the reply.

see, the problem is to do, but how best to do.

In my specific case, I do one part (PHP, MySql, AWS, etc.) and another team is in charge of layouts.

For me, it is unthinkable to delegate them access to model layer. I am studying to enable the migration of our platform for Phalcon.

In the current platform, I built a class template which replaces certain tags defined by established and documented values.

All this to avoid them to do stupid things in the code.

My controller: $this->view->var = 'teste';

Layout by staff frontend, only HTML <h1>{:teste:}</h1> code....

This library I did not issue NOTICES warning in case of undeclared variables, it simply does not do the replace.

My english é bad (google translate)

A solution that I thought would create a plugin triggered the event afterDispatch

this plugin gets Menu :: find (); Category :: find () ...

And create my TemplateEngine based on tags.

ok, so do it in simiar way, this is only conspect:

class Utility extends \Phalcon\Mvc\User\Plugin
{
    public function get_menus()
    {
        $menus = Menus :: find (array ('order' => 'order DESC' ));
        return  $menus;
    }
}

register this class in your DI

$di->set('utility', function(){
    return new Utility();
}, true);

and in your view your designer can use it like that

<ul>
<?php foreach($this->utility->get_menus() as $menu) { ?>
    <li><a href="/<?= $menu->slug ?>"><?= $menu->name ?></a></li>
<?php } ?>
</ul>
edited Mar '14

if you do as i write above you could use it in Volt template too:

{{ utility.get_menus() }}
edited Mar '14

is possible in utility class:

public function get_menus()
{
    $menus = Menus :: find (array ('order' => 'order DESC' ));
    $this->view->menu = $menus;
}

And, in tpl file:

<?php foreach( $menus as $menu) {...}

Utility class, no in DI, Considering the utility class as event listener, and not as a plugin.

I do not want the html staff to have access class functions, only the results vars



40.8k
Accepted
answer
edited Mar '14

you can use __get()
and you only give access only what you implemented

class Utility extends \Phalcon\Mvc\User\Plugin
{
    public function __get($property) 
    {
        if (method_exists($this, $property)) 
        {
            return $this->$property();
        }
        else
        {
            return "not implemented";
        }
    }

    public function menus()
    {
        $menus = Menus :: find (array ('order' => 'order DESC' ));
        return  $menus;
    }
}

and in your templates

{{ utility.menus }}
<?= $this->utility->menus ?>

This is good. Thans!!

How do I call when a variable is not declared in the View returns a message "not implemented" e not error?

edited Mar '14

This way:

class Utility extends \Phalcon\Mvc\User\Plugin
{
    public function __get($property)
    {
        if (method_exists($this, $property))
        {
            return $this->$property();
        }

        if(property_exists($this, $property))
        {
            return $this->property;
        }

        return "not implemented";
    }

    public function menus()
    {
        $menus = Menus :: find (array ('order' => 'order DESC' ));
        return  $menus;
    }

}

This plugin is ok, resolved.

Now, in View class, my question now is to avoid errors in view

controller: $this->view->serVar('varName', 'Rafael');

templates <h1>{{ othervar }}</h1>

expected result: <h1>not implemented!</h1>

Rafael, please for new question make new thread, this way other people could find solution for problems easier :)

Try this, should work.

class MyView extends \Phalcon\Mvc\View
{

    public function __get($property)
    {

        if(property_exists($this, $property))
        {
            return $this->property;
        }

        return "variable not set";
    }

}
$di->set('view', function(){
    $view = new MyView();
    $view->setViewsDir('../app/views/');
    return $view;
});