Skip to content

Rendering stages get multiplied when viewDirs is an array #12977

Closed
@memmaker

Description

Expected and Actual Behavior

I am using a multi-module setup for Phalcon and each of my modules is supposed to have its own views in addition to the shared ones in the core module.

A few versions back, Phalcon introduced the ability to set the viewsDir of the view service to an array. This greatly simplifies my endeavor.

I am currently using this feature like this:

$view->setViewsDir(['../Modules/Core/Views/byController/', '../Modules/'.$moduleName.'/Views/']);

This works great, as Phalcon now looks in both of these directories for a view to render.

However I ran into problems with this setup. The rendering is now doubled for my menu and all my partials.

So my expectation would be, that I can just register multiple paths as viewDirs and Phalcon will use the first view it will find in any of these directories and use it for rendering. I expect each view to only be rendered once. I would also expect, that rendering of partials would be unaffected by setting the viewDirs to an array.

The result is, that partials get output once for each entry in the viewDirs variable. Which results in broken output.

I traced the problem down to the _engineRender() method in cphalcon/phalcon/mvc/view.zep. The problem is that we iterate over the viewDirs but do not check if we already rendered this view successfully. So we just do it again, if there are multiple viewDirs.

I even proposed a fix in this commit:
https://github.com/memmaker/cphalcon/commit/b0fca223d105d07a10f16db2c507d00bfe25d6e8

I am currently not able to supply a minimal example. However you should be able to reproduce the Problem by setting the viewDirs of your view service to an array of paths and trying to render a partial.

We found the problem because we used a multi module setup and are setting the viewDirs of our view Service to an array in the modules.

I also found a way to workaround this bug by using the events manager.

Workaround:

        $this->menuHasBeenRendered = false;
        /** @var ManagerInterface $eventsManager */
        $eventsManager = $di->getShared('eventsmanager');

        // TODO: submit issue to phalcon for this bug..
        $eventsManager->attach(
            "view:beforeRenderView",
            function (Event $event, $component, $path)
            {
                if (ends_with($event->getData(), 'menu.phtml'))
                {
                    if ($this->menuHasBeenRendered)
                    {
                        return false;
                    }
                    $this->menuHasBeenRendered = true;
                }
                return true;
            }
        );

Details

  • Phalcon version: 3.1.2
  • PHP Version: 7.1.3
  • Operating System: linux
  • Installation type: Compiling from source
  • Zephir version (if any): n/a
  • Server: Nginx
  • Other related info (Database, table schema): mongoDb, Custom Schema

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions