我有一个Fluid模板,我将列表分成4组,如:
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
startService(new Intent(context, MyService.class));
}
}
我已将Fluid XML命名空间添加到我的项目like this中,但PhpStorm仍然告诉我,我的结束<ul>
<f:for each="{items}" as="item" iteration="i">
<li>(CONTENT HERE)</li>
<f:if condition="{i.cycle} % 4">
</ul>
<ul>
</f:if>
</f:for>
</ul>
标记与#39;不匹配。
有没有办法配置PhpStorm来识别这个构造?
我是否通过在</f:if>
中包含结束标记和开始标记来违反最佳做法?
答案 0 :(得分:2)
PHP Storm验证的第一件事就是正确嵌套XML / HTML - 就像标签一样,在你的样本中你无情地打破它(从IDE的角度来看,不是我的,因为我理解需要使用modulo 在流体中打破,如果您要添加有效的XML命名空间甚至根本不禁用XML检查器,则无关紧要。
即使在内联然后通知中也能识别标签的聪明的还有什么呢?该死的!显示IDE级别错误:
<ul>
<f:for each="{items}" as="item" iteration="i">
<li>Item {i.cycle}</li>
{f:if(condition: '{i.cycle} % 4', then: '</ul><ul>')}
</f:for>
</ul>
到目前为止我发现并在许多项目中成功使用它的唯一解决方案是在自定义ext中自定义ViewHelper(对于IDE来说,在startTage
之前声明endTag
非常重要!) :
<?php
namespace Vendor\Myext\ViewHelpers;
/**
* {namespace myNs=Vendor\Myext\ViewHelpers}
*
* = Inline samples
*
* === Break the list:
* {myNs:breakTagByModulo(iterator: i, modulo: 2)}
* or...
* {myNs:breakTagByModulo(iterator: i, modulo: 2, startTag: '<ul class="next-level">', endTag: '</ul>')}
*
* result on valid modulo:
* </ul><ul class="next-level">
*
* === Break the Bootstrap row:
* {myNs:breakTagByModulo(iterator: i, modulo: 2, startTag: '<div class="row">', endTag: '</div>')}
*
* result on valid modulo:
* </div><div class="row">
*
* etc...
*/
class BreakTagByModuloViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
/**
* @param array $iterator Iterator from `f:for` VH
* @param integer $modulo Modulo to check
* @param boolean $skipLast If skipLast==true VH will return false even if condition is correct, needed for `not full` lists
* @param string $startTag Begin of the tag
* @param string $endTag End of the tag
*
* @return bool|string
*/
public function render($iterator, $modulo, $skipLast = true, $startTag = '<ul>', $endTag = '</ul>') {
$i = $iterator['cycle'];
$bool = ($i % $modulo == 0);
if ($skipLast && $iterator['isLast']) {
$bool = false;
}
return ($bool) ? $endTag . $startTag : null;
}
}
?>
视图中的用法如上所示,仅适用于您的示例,它将类似于:
{namespace myNs=Vendor\Myext\ViewHelpers}
<ul>
<f:for each="{items}" as="item" iteration="i">
<li>(CONTENT HERE)</li>
{myNs:breakTagByModulo(iterator: i, modulo: 4)}
</f:for>
</ul>
(当然您要用自己的价值取代myNs
,Vendor
和Myext
)
答案 1 :(得分:1)
我建议采用不同的方法来确保可靠的html结构。将模板HTML与来自视图助手的HTML混合似乎是一个危险的想法,当开始标记来自一个而结束标记来自另一个时。
由于将列表拆分为块似乎是逻辑必需而不是表示,因此逻辑应该在控制器而不是视图中发生。如果由于某种原因,您无法更改控制器逻辑(第三方扩展?),您应该使用窗口小部件/视图助手。在那里,您可以使用纯PHP将列表拆分为4个集合,然后使用循环迭代模板中的集合。通过这种方式,HTML将更易于破解,更易于维护且更易于理解(适用于您和PHPSTORM)。
答案 2 :(得分:0)
我的灵感来自LazyOne的评论和Biesior的回答。采取以下措施:
<ul>
<f:for each="{items}" as="item" iteration="i">
<li>Item {i.cycle}</li>
{f:if(condition: '{i.cycle} % 4', else: '</ul><ul>')}
</f:for>
</ul>
我尝试用HTML实体和Unicode转义序列替换尖括号,两者都输出完整。然后我想做个性替换。我找到了v:format.replace viewhelper,我做了以下内容:
<v:format.replace substring="(" replacement="<"><v:format.replace substring=")" replacement=">">{f:if(condition: '{iter.cycle} % 4', else: '(/ul)(ul)')}</v:format.replace></v:format.replace>
也就是说,我在括号中添加括号,然后将它们切换到输出的尖括号。
对于任何想要使用它的人来说,有一个荒谬冗长的选择。