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

问题描述 投票:0回答:1

我将TYPO3Fluid用于我的自定义(独立)应用程序(没有TYPO3 CMS)。

我的自定义inArray-ViewHelper无法正常运行。

在页面的第一次调用中,它似乎被忽略了(viewhelper内部没有执行任何代码)。但是,在第二次调用页面时,viewhelper被执行并按预期工作(希望)。

此外,viewhelper仅在启用缓存的情况下有效,如果禁用缓存,则仅返回else-part。

<?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 '';
    }
}

有人知道要解决此问题吗?还是有人知道“ inArray”的更好解决方案?

编辑:

好,就像文档中所说的那样,renderStatic()不能用于需要访问其子级的viewhelper。所以我不能在这里使用renderStatic()。我尝试使用render(),这给了我更多的问题,因为然后第一次页面加载就给了500!所以我改用compile()作为渲染方法。现在,我可以将viewhelper用作if条件内的参数。很好,可以。

新问题:

  • 桑德,我不能在内联条件中使用它!悲伤!
  • 必须在我的状况周围使用-Tag,否则每次结果均为假。

现在,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\'])';
    }
}

编辑2:

我对compile()进行了一些更改-也许可以使用。

编辑3:

我试图做一个覆盖IfViewHelper的类。但这可悲地是行不通的。 in_array的值和结果与预期的一样,但呈现的始终为“ false”。

<?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\ViewHelpers\IfViewHelper {

    use CompileWithRenderStatic;

    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 RenderingContextInterface $renderingContext
     * @return bool
     */
    public static function verdict(array $arguments, RenderingContextInterface $renderingContext)
    {
        return in_array($arguments['needle'], $arguments['haystack']);
    }
}

因此,我使用第二个代码并禁用该条件周围的缓存。有效,但无法在inif-if条件下使用。

typo3 fluid
1个回答
0
投票

编译方法用于生成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.
 * ...

您上面在compile方法中发布的代码无论如何都不起作用($ arguments在该方法中不存在。

而不是重新实现if条件,我建议构建一个简单的InArrayViewHelper,该方法只返回true或false,然后像这样使用它:

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

但是如果它必须是一个自定义的类似ifView的ViewHelper,也许您想研究扩展类\TYPO3Fluid\Fluid\Core\ViewHelper\AbstractConditionViewHelper而不是默认的AbstractViewHelper。

正如我所看到的,只需扩展该类并only覆盖initializeArguments进行参数注册和verdict方法就足够了,该方法将包含in_array调用并返回布尔值。

也可以看看:\TYPO3Fluid\Fluid\ViewHelpers\IfViewHelper

© www.soinside.com 2019 - 2024. All rights reserved.