[英]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:新问题:
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 并仅覆盖用于参数注册的initializeArguments
和verdict
方法就足够了,这将包含您的 in_array 调用并返回一个布尔值。
Also have a look at: \TYPO3Fluid\Fluid\ViewHelpers\IfViewHelper
也看看: \TYPO3Fluid\Fluid\ViewHelpers\IfViewHelper
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.