简体   繁体   English

自定义 TYPO3Fluid inArray viewhelper 在第一页加载时无法正常工作

[英]custom TYPO3Fluid inArray viewhelper does not work properly at first page-load

I use TYPO3Fluid for my custom (standalone) application (without TYPO3 CMS).我将 TYPO3Fluid 用于我的自定义(独立)应用程序(没有 TYPO3 CMS)。

My custom inArray-ViewHelper does not run properly.我的自定义 inArray-ViewHelper 无法正常运行。

At the first call of a page, it seems to be ignored (no code is executed inside the viewhelper).在第一次调用页面时,它似乎被忽略了(在 viewhelper 内没有执行任何代码)。 But at second call of a page, the viewhelper is executed and works (hopefully) as expected.但是在第二次调用页面时,viewhelper 会按预期执行并(希望)工作。

Also the viewhelper only works, if caching is enabled, if disabled it just returns the else-part.此外,viewhelper 仅在启用缓存的情况下才有效,如果禁用它只会返回 else 部分。

<?php
namespace TYPO3Fluid\Fluid\ViewHelpers;

use TYPO3Fluid\Fluid\Core\Compiler\TemplateCompiler;
use TYPO3Fluid\Fluid\Core\Parser\SyntaxTree\ViewHelperNode;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;

class InArrayViewHelper extends \TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper {

    /**
     * We accept value and children interchangeably, thus we must disable children escaping.
     *
     * @var bool
     */
    protected $escapeChildren = false;

    /**
     * If we decode, we must not encode again after that.
     *
     * @var bool
     */
    protected $escapeOutput = false;

    public function initializeArguments() {
        parent::initializeArguments();
        $this->registerArgument('haystack', 'mixed', 'View helper haystack ', TRUE);
        $this->registerArgument('needle', 'string', 'View helper needle', TRUE);
    }

    /**
     * @param array $arguments
     * @param \Closure $renderChildrenClosure
     * @param RenderingContextInterface $renderingContext
     * @return mixed
     */
    public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext){
        $needle = $arguments['needle'];
        $haystack = $arguments['haystack'];

        if(!is_array($haystack)) {
            return $this->renderElseChild();
        }else {
            if (in_array($needle, $haystack)) {
                if (isset($arguments['then'])) {
                    return $arguments['then'];
                }
                if (isset($arguments['__thenClosure'])) {
                    return $arguments['__thenClosure']();
                }
            }  elseif (!empty($arguments['__elseClosures'])) {
                $elseIfClosures = isset($arguments['__elseifClosures']) ? $arguments['__elseifClosures'] : [];
                return static::evaluateElseClosures($arguments['__elseClosures'], $elseIfClosures, $renderingContext);
            } elseif (array_key_exists('else', $arguments)){
                return $arguments['else'];
            }
            return '';
        }
    }

    /**
     * @param array $closures
     * @param array $conditionClosures
     * @param RenderingContextInterface $renderingContext
     * @return string
     */
    private static function evaluateElseClosures(array $closures, array $conditionClosures, RenderingContextInterface $renderingContext)
    {
        foreach ($closures as $elseNodeIndex => $elseNodeClosure) {
            if (!isset($conditionClosures[$elseNodeIndex])) {
                return $elseNodeClosure();
            } else {
                if ($conditionClosures[$elseNodeIndex]()) {
                    return $elseNodeClosure();
                }
            }
        }
        return '';
    }
}

Anyone an idea to fix this?有人有解决这个问题的想法吗? Or does anyone know a better solution for "inArray"?或者有人知道“inArray”的更好解决方案吗?

EDIT:编辑:

Ok, like teh documentation said, renderStatic() can't be used for viewhelper which needs access to their childs.好的,就像文档所说的那样,renderStatic() 不能用于需要访问其孩子的 viewhelper。 So I can't use renderStatic() here.所以我不能在这里使用 renderStatic() 。 I tried to use render() which gave me more problems, because then the first page-load gave a 500. So I switched to compile() as rendering-method.我尝试使用 render() 这给了我更多问题,因为第一个页面加载给出了 500。所以我切换到 compile() 作为渲染方法。 Now I can use my viewhelper as argument inside an if-condition.现在我可以在 if 条件中使用我的 viewhelper 作为参数。 That's fine and works.这很好并且有效。

New problems:新问题:

  • Sandly I can't use it inside an inline-if-condition! Sandly 我不能在 inline-if-condition 中使用它! Sad!伤心!
  • Have to use a -Tag around my condition, elsewhere the result is false everytime.必须在我的情况周围使用 -Tag,在其他地方每次结果都是错误的。

Now the viewhelper looks like this现在 viewhelper 看起来像这样

<?php
namespace TYPO3Fluid\Fluid\ViewHelpers;

use TYPO3Fluid\Fluid\Core\Compiler\TemplateCompiler;
use TYPO3Fluid\Fluid\Core\Parser\SyntaxTree\ViewHelperNode;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;

class InArrayViewHelper extends \TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper {

    use CompileWithRenderStatic;

    public function initializeArguments() {
        parent::initializeArguments();
        $this->registerArgument('haystack', 'mixed', 'View helper haystack ', TRUE);
        $this->registerArgument('needle', 'string', 'View helper needle', TRUE);
    }

    public static function renderStatic(
        array $arguments,
        \Closure $renderChildrenClosure,
        RenderingContextInterface $renderingContext
    ) {
        return in_array($arguments['needle'], $arguments['haystack']);
    }

    public function compile(
        $argumentsName,
        $closureName,
        &$initializationPhpCode,
        ViewHelperNode $node,
        TemplateCompiler $compiler
    ) {
        return 'in_array('$argumentsname.'[\'needle\'],'. $argumentsname.'[\'haystack\'].');';
    }
}

The compile method is for generating the PHP code and should - in most cases - not be overriden, unless you know what you're doing: compile 方法用于生成 PHP 代码,并且在大多数情况下不应被覆盖,除非您知道自己在做什么:

/**
 * You only should override this method *when you absolutely know what you
 * are doing*, and really want to influence the generated PHP code during
 * template compilation directly.
 * ...

The code you posted above in your compile method does not work that way anyway ($arguments does not exist in that method).您在 compile 方法中发布的代码无论如何都不能以这种方式工作(该方法中不存在 $arguments )。

Instead of reimplementing the if condition, I'd recommend building a simple InArrayViewHelper that simply returns true or false, and then use it like:我建议不要重新实现 if 条件,而是构建一个简单的 InArrayViewHelper,它只返回 true 或 false,然后像这样使用它:

<f:if condition="{x:inArray(haystack: haystack, needle: needle)}"> ... </f:if>

But if it has to be a custom if-like ViewHelper, maybe you want to look into extending the class \TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper instead of the default AbstractViewHelper.但是如果它必须是一个自定义的 if 类 ViewHelper,也许你想考虑扩展 class \TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper而不是默认的 AbstractViewHelper。

As I see it, it should be enough to simply extend that class and only override the initializeArguments for argument registration and the verdict method, that would contain your in_array call and return a bool.正如我所看到的,只需扩展 class 并覆盖用于参数注册的initializeArgumentsverdict方法就足够了,这将包含您的 in_array 调用并返回一个布尔值。

Also have a look at: \TYPO3Fluid\Fluid\ViewHelpers\IfViewHelper也看看: \TYPO3Fluid\Fluid\ViewHelpers\IfViewHelper

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM