我将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条件内的参数。很好,可以。
新问题:
现在,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条件下使用。
编译方法用于生成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