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

Controller initialize() called twice on forwards

I noticed that the controller initialize() method is called twice when performing a forward from one action to another (thus called for each action).

Is this the normal behavior? Is there a way to prevent it from executing code if already executed?

My problem is that in the initializer I add the basic CSS and JS files fot the application is an assets collection. They get added twice to the output.

Could you please provide a small script that demostrate the problem?



5.7k

Base class:

<?php

namespace MyApp\Frontend\Controllers;
use Phalcon\Mvc\Dispatcher;

class ControllerBase extends \Phalcon\Mvc\Controller
{

    protected function initialize()
    {
        $this->assets
            // Bootstrap
            ->addCss('css/bootstrap.min.css')
            ->addCss('css/style.css');

        $this->assets
            ->collection('footer')
            // jQuery (necessary for Bootstrap's JavaScript plugins)
            ->addJs('js/jquery/jquery-1.11.2.min.js')
            // Bootstrap and plugins
            ->addJs('js/bootstrap/bootstrap.min.js');
    }

    ...
}

Controller:

<?php

namespace MyApp\Frontend\Controllers;

use MyApp\Base50;
use MyApp\Frontend\Forms\EventForm;
use MyApp\Frontend\Models\Event;
use MyApp\Frontend\Models\Resources\Events;

class EventsController extends ControllerBase
{
    public function initialize()
    {
        $this->view->setTemplateAfter('main');
        parent::initialize();

        $this->assets->collection('footer')
            ->addJs('js/moment/moment.min.js');
    }

    public function indexAction()
    {
        $this->dispatcher->forward(array(
            "controller" => "events",
            "action"     => "future"
        ));
    }

    public function futureAction()
    {
        $this->assets->collection('footer')
            ->addJs('js/myapp/eventer.js')
            ->addJs('js/frontend/events/future.js');
    }

    ...
}

When I access the https://<tld>/events/index (or https://<tld>/events), which makes a forward to the futureAction, the assets defined in initialize() method of the base class are added twice.



5.7k
Accepted
answer

Honestly, the way you described what is happening seems like something I would expect to be the "expected behavior". The reason I say this is because when you forward to a new action, let's say it belongs to a different controller, that other controller may have some initialization logic to restrict access, for example.

So in your case, you're seeing the initialize funciton called when indexAction is called, but then you forward that to the "future" action, which should also trigger the initialize class for whatever that controller belongs to.

What I would recommend is something like this:

<?php

namespace MyApp\Frontend\Controllers;
use Phalcon\Mvc\Dispatcher;

class ControllerBase extends \Phalcon\Mvc\Controller
{

    private $mainAssetsLoaded = false;

    protected function initialize()
    {

        // Check to see if the assets have been loaded or not
        if($this->mainAssetsLoaded === false){
          $this->assets
          // Bootstrap
          ->addCss('css/bootstrap.min.css')
          ->addCss('css/style.css');

          $this->assets
          ->collection('footer')
          // jQuery (necessary for Bootstrap's JavaScript plugins)
          ->addJs('js/jquery/jquery-1.11.2.min.js')
          // Bootstrap and plugins
          ->addJs('js/bootstrap/bootstrap.min.js');
          }

          // Indicate that the assets have been loaded
          $this->mainAssetsLoaded = true;
    }

    ...
}


5.7k

Well, this is somehow contradicted by this thread: bug-in-forwarding-to-the-same-controller

Therefore, I'm not sure which is the "expected behavior". I'm expecting that a forward won't do a reinitialization of the controller class, while a redirect should (and probably is).

Forward has to instantiate the controller to execute the specified action.



5.7k

Indeed it makes sense, especially when forwarding from one controller to another. Thank you!