【问题标题】:PhpStorm not recognizing TYPO3 Fluid closing tagsPhpStorm 无法识别 TYPO3 Fluid 结束标签
【发布时间】:2016-03-04 19:10:32
【问题描述】:

我有一个 Fluid 模板,我将列表分成 4 组,例如:

<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>

我已将 Fluid XML 命名空间添加到我的项目 like this 中,但 PhpStorm 仍然通知我我的结束 &lt;/f:if&gt; 标记“不匹配”。

有没有办法配置 PhpStorm 来识别这个结构?

&lt;f:if&gt; 中包含结束标签和开始标签是否违反了最佳实践?

【问题讨论】:

  • 我不熟悉 Fluid.. 所以只是一个想法:也许这是因为您在 &lt;/f:if&gt; 之前有 &lt;/ul&gt;&lt;ul&gt;。 XML/HTML 解析器可能认为&lt;f:if&lt;/ul&gt; 之前已经关闭(尤其是如果它是HTML5)因此matches nothing。如果是这种情况,那么可能的解决方法是使用实​​际的 Fluid 语法打印那些 ul 对(Fluid 是否有某种回显/打印标签/指令?您可以将此类文本分配给变量然后输出)跨度>

标签: typo3 phpstorm fluid


【解决方案1】:

PHP Storm 验证的第一件事是正确嵌套 XML/HTML - 类似标签,在您的示例中,您无情地破坏了它(从 IDE 的角度来看,不是我的,因为我理解需要使用模 break 在 Fluid 中),添加有效的 XML 命名空间甚至完全禁用 XML 检查器都没有关系。

聪明甚至可以在内联then通知中识别标签(该死!),这也会显示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,在 endTag 之前声明 startTage 很重要!):

<?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>

(当然你要用自己的值替换 myNsVendorMyext

【讨论】:

    【解决方案2】:

    我会建议一种不同的方法来确保可靠的 html 结构。将模板 HTML 与来自视图助手的 HTML 混合起来似乎是一个危险的想法,因为开始标签来自一个标签,而结束标签来自另一个标签。

    由于将列表分成块似乎是一种逻辑上的必要性,而不是一种表现形式,因此这种逻辑应该发生在控制器而不是视图中。如果由于某种原因,您无法更改控制器逻辑(第 3 方扩展?),您应该求助于小部件/视图助手。在那里,您可以使用纯 PHP 将列表拆分为 4 组,然后使用循环迭代模板中的组。这样一来,HTML 将更不易损坏、更易于维护且更易于理解(对您和 PHPSTORM 而言)。

    【讨论】:

      【解决方案3】:

      我受到 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>
      

      也就是说,我在代码中放了括号,并将它们切换为尖括号以用于输出。

      所以对于任何想要使用它的人来说,有一个非常冗长的选项。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-19
        • 1970-01-01
        • 2017-07-24
        • 2022-01-05
        • 2019-01-16
        • 1970-01-01
        • 1970-01-01
        • 2019-04-30
        相关资源
        最近更新 更多