Search code examples
typo3fluidtypo3-flow

why is a duplicate variable declaration exception thrown while rendering a TYPO3 Flow fluid template?


How do I debug this exception? It is in a section that displays recently viewed items which is on a page that displays an individual item. the templates for both sections use the same variable name in the for loops eg <f:for each="{productArticles}" as="productArticle"> but the exception is not always thrown when recently viewed items are listed (just links to those items are shown anyway). The exception only seems to happen when: I am on the page displaying a gift card and then I select a different gift card from a drop down (which shows different gift card denominations) and then when the page refreshes to display the different card and then I guess the first card displayed is now one of the recently viewed items. But if I go to another page and then back to the gift card page the error may not appear.

    Exception while rendering
page<TYPO3.Neos:Page>/
body<TYPO3.TypoScript:Template>/
content/
main<TYPO3.Neos:PrimaryContent>/
default<TYPO3.TypoScript:Matcher>/
element<TYPO3.Neos:ContentCollection>/
itemRenderer<TYPO3.Neos:ContentCase>/
default<TYPO3.TypoScript:Matcher>/
element<TYPO3.Neos.NodeTypes:TwoColumn>/
columns<TYPO3.TypoScript:Collection>/
itemRenderer<TYPO3.Neos.NodeTypes:MultiColumnItem>/
columnContent<TYPO3.Neos:ContentCollection>/
itemRenderer<TYPO3.Neos:ContentCase>/
default<TYPO3.TypoScript:Matcher>/
element<MyCompany.Store:RecentlyViewedProduct>:
Duplicate variable declaration, "productArticle" already set! (20141105131932df2032)

Here is the template:

<f:layout name="Default" />
<f:section name="Title">
    <h3>
        <f:translate id="MyCompany.Store.Recently-Viewed">Recently Viewed</f:translate>
    </h3>
</f:section>
<f:section name="Content">
    <f:if condition="{productArticles}">
        <f:then>
            <f:for each="{productArticles}" as="productArticle">
                <f:link.action action="showProductArticle" controller="Product" arguments="{productArticle: productArticle}">{productArticle.product.name}</f:link.action><br />

            </f:for>
        </f:then>
        <f:else>
            <p>
            <f:translate id="MyCompany.Store.No-Recently-Viewed">No recently viewed product</f:translate>
            </p>
        </f:else>
    </f:if>
</f:section>

and the Action for the template:

    /**
     * Shows most recently viewed products
     *
     * @param \MyCompany\Store\Domain\Model\ProductArticle $productArticle
     * @return void
     */
    public function recentlyViewedProductsAction() {
        $recentProduct = $this->cart->getProductArticle();
        $recentProductThree = array_reverse($recentProduct);

        array_splice($recentProductThree, 3);
        if (count($recentProduct) !== 0) {
            $this->view->assign('productArticles', $recentProductThree);
        }
    }

The message about a duplicate var would make sense to me if the exception was always thrown as the other template uses it too, but since it is only an occasionally thrown I don't know what to make of it.

The exception log looks like this

Uncaught exception #1224479063 in line 116 of /home/thebigcat/domains/store.thebigcat.ca/public_html/releases/20131219160416/Data/Temporary/Development/Cache/Code/Flow_Object_Classes/TYPO3_Fluid_ViewHelpers_ForViewHelper.php: Duplicate variable declaration, "productArticle" already set!

115 TYPO3\Fluid\Core\ViewHelper\TemplateVariableContainer_Original::add("productArticle", TYPO3\Flow\Persistence\Doctrine\Proxies__CG__\Mycompany\Store\Domain\Model\ProductArticle) 114 TYPO3\Fluid\ViewHelpers\ForViewHelper_Original::renderStatic(array|5|, Closure, TYPO3\Fluid\Core\Rendering\RenderingContext) 113 {closure}() 112 TYPO3\Fluid\Core\ViewHelper\AbstractConditionViewHelper::renderThenChild() 111 TYPO3\Fluid\ViewHelpers\IfViewHelper_Original::render(TRUE) 110 call_user_func_array(array|2|, array|1|) 109 TYPO3\Fluid\Core\ViewHelper\AbstractViewHelper::callRenderMethod() 108 TYPO3\Fluid\Core\ViewHelper\AbstractViewHelper::initializeArgumentsAndRender() 107 FluidCache_Mycompany_Store_Product_action_recentlyViewedProducts_1f6458e2b69625fca8d5707e4161562d5d061770::section_4f9be057f0ea5d2ba72fd2c810e8d7b9aa98b469(TYPO3\Fluid\Core\Rendering\RenderingContext) 106 TYPO3\Fluid\View\AbstractTemplateView::renderSection("Content", array|1|, FALSE)

and the bottom of the Security_Development.log looks like this, with many similar errors above so I doubt its related to the problem:

14-11-05 13:48:48 64.39.189.157 INFO Flow
Access denied (0 denied, 0 granted, 1 abstained) on resource "TYPO3_Neos_Backend_GeneralAccess".

Thanks


Solution

  • Problem is that productArticle which you use for as in f:for was assigned before to this template (outside f:for).. So for example when in your action you do:

    $this->view->assignMultiple(array(
            'message' => 'xxx',
            'messages' => $messages,
    ));
    

    you cannot do <f:for each="{messages}" as="message"> because message is already assigned. Use something like msg or loopedMessage..

    You can use <f:debug> outside f:for to check if your productArticle is NULL.

    And about Access denied - when you add new action to your controller, you have to flush cache.