如果条件,TYPO3流体复合物

时间:2013-11-01 16:36:39

标签: typo3 fluid

我正在尝试编写以下内容,如果条件不流畅,但它不能正常工作。

条件 作为for循环的一部分,我想检查项目是第一个还是第4个,第8个等等

我认为以下内容可行,但它会显示每次迭代的代码。

<f:if condition="{logoIterator.isFirst} || {logoIterator.cycle % 4} == 0">

我已经设法让它使用嵌套if但只是感觉错了两次使用相同的代码段并且周期检查使用<f:else>代替== 0

<f:if condition="{logoIterator.isFirst}">
    <f:then>
        Do Something
    </f:then>
    <f:else>
        <f:if condition="{logoIterator.cycle} % 4">
            <f:else>
                Do Something
            </f:else>
        </f:if>
    </f:else>
</f:if>

11 个答案:

答案 0 :(得分:18)

TYPO3 v8

更新了TYPO3 v8的答案。这引自克劳斯的答案如下:

  

使用当前情况更新此信息:

     

在TYPO3v8及更高版本上,支持以下语法   完全符合您的使用案例:

<f:if condition="{logoIterator.isFirst}">
    <f:then>First</f:then>
    <f:else if="{logoIterator.cycle % 4}">n4th</f:else>
    <f:else if="{logoIterator.cycle % 8}">n8th</f:else>
    <f:else>Not first, not n4th, not n8th - fallback/normal</f:else>
</f:if>
     

此外还支持这样的语法:

<f:if condition="{logoIterator.isFirst} || {logoIterator.cycle} % 4">
    Is first or n4th
</f:if>
     

哪些情况更适合某些情况(特别是在使用时)   内联语法中的条件,您无法在其中扩展为标记模式   为了获得对f:else的访问,使用新的if参数)。

TYPO3 6.2 LTS和7 LTS

对于更复杂的if-Conditions(如几个或/和组合),您可以在your_extension/Classes/ViewHelpers/中添加自己的ViewHelper。您只需要扩展流体AbstractConditionViewHelper。与Fluid交互的简单if-ViewHelper看起来像这样:

class IfViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractConditionViewHelper {

    /**
     * renders <f:then> child if $condition is true, otherwise renders <f:else> child.
     *
     * @param boolean $condition View helper condition
     * @return string the rendered string
     * @api
     */
    public function render($condition) {
        if ($condition) {
            return $this->renderThenChild();
        } else {
            return $this->renderElseChild();
        }
    }
}

您在自己的ViewHelper中所要做的就是添加比$condition更多的参数,例如$or$and$not等。然后您只需编写if -phditions在php中呈现then或者其他孩子。对于您的示例,您可以使用以下内容:

class ExtendedIfViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractConditionViewHelper {

    /**
     * renders <f:then> child if $condition or $or is true, otherwise renders <f:else> child.
     *
     * @param boolean $condition View helper condition
     * @param boolean $or View helper condition
     * @return string the rendered string
     */
    public function render($condition, $or) {
        if ($condition || $or) {
            return $this->renderThenChild();
        } else {
            return $this->renderElseChild();
        }
    }
}

文件将在your_extension / Classes / ViewHelpers / ExtendedIfViewHelper.php中然后你必须在Fluid-Template中添加你的命名空间(这样就可以在模板中启用your_extension / Classes / ViewHelpers /中所有自编的ViewHelpers :

{namespace vh=Vendor\YourExtension\ViewHelpers}

并在您的模板中调用它:

<vh:extendedIf condition="{logoIterator.isFirst}" or="{logoIterator.cycle} % 4">
  <f:then>Do something</f:then>
  <f:else>Do something else</f:else>
</vh:extendedIf>

编辑:已更新。

答案 1 :(得分:11)

使用当前情况更新此信息:

在TYPO3v8及更高版本上,支持以下语法,完全符合您的用例:

<f:if condition="{logoIterator.isFirst}">
    <f:then>First</f:then>
    <f:else if="{logoIterator.cycle % 4}">n4th</f:else>
    <f:else if="{logoIterator.cycle % 8}">n8th</f:else>
    <f:else>Not first, not n4th, not n8th - fallback/normal</f:else>
</f:if>

此外还支持这样的语法:

<f:if condition="{logoIterator.isFirst} || {logoIterator.cycle} % 4">
    Is first or n4th
</f:if>

哪些情况更适合某些情况(特别是在内联语法中使用条件时,您无法扩展到代码模式,以便使用新f:else访问if参数)。

答案 2 :(得分:6)

v:if.condition将在vhs V2.0中弃用 使用v:if stack: https://github.com/FluidTYPO3/vhs/issues/493

答案 3 :(得分:4)

您还可以使用If Condition Extend ViewHelper提供的VHS extension

<v:if.condition>
    <v:if.condition.extend>
        {logoIterator.isFirst} || {logoIterator.cycle % 4} == 0
    </v:if.condition.extend>
    <f:then>Output if TRUE</f:then>
    <f:else>Output if FALSE</f:else>
</v:if.condition>

旁注:VHS扩展提供了许多有用的ViewHelpers。我觉得很多都应该包含在TYPO3液体中。

答案 4 :(得分:4)

对于许多情况,它足以使用数组比较 - 因此您不必创建自定义视图助手。

<f:if condition="{0:user.number,1:user.zip}=={0:123,1:01234}">

OR

<f:if condition="{0:user.number,1:user.zip}!={0:false,1:false}">

可悲的是,这只是为了检查是否设置了一个变量而不是一个值。但是对于很多情况来说这已经足够了。

PS :(通过此数组比较,您还可以比较字符串)

答案 5 :(得分:1)

除了Daniels的回答之外,我制作了一个ViewHelper,它接受多个条件,带有“和” - 模式(默认)或“或” - 模式:

<?php
namespace TLID\Contentelements\ViewHelpers;

class IfViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
  /**
   * Checks conditions
   *
   * @param mixed $checks
   * @param string $type
   *
   * @return boolean whether is array or not
   */
  public function render($checks, $type = "and") {
    $success = $type === "and" ? true : false;
    $doc = new \DOMDocument();
    $doc->loadHTML($this->renderChildren());
    $xpath = new \DOMXpath($doc);

    // get store values
    $storeNodes = $xpath->query("//body/store");
    $store = "";
    foreach ($storeNodes as $storeNode) {
      foreach ($storeNode->childNodes as $childNode) {
        $store .= $doc->saveHTML($childNode);
      }
    }

    // do the actual check
    foreach ($checks as $check) {
      if (
        ($type === "and" && (is_array($check) && count($check) === 0 || is_object($check) && get_object_vars($check) === 0 || empty($check))) ||
        (is_array($check) && count($check) !== 0 || is_object($check) && get_object_vars($check) !== 0 || !empty($check))
      ) {
        $success = $type === 'and' ? false : true;
        break;
      }
    }

    // render content
    $renderQueryElement = $success ? "success" : "failure";
    $renderNodes = $xpath->query("//body/" . $renderQueryElement);
    $content = "";
    foreach ($renderNodes as $renderNode) {
      foreach ($renderNode->childNodes as $childNode) {
        $content .= $doc->saveHTML($childNode);
      }
    }

    //insert contents
    $matches;
    $content = preg_replace("/<use[^>]*><\/use>/", $store, $content);

    //return rendered content
    return $content;
  }
}
?>

虽然它可以写得更好,但它确实有效。 以下是我如何使用它:

{namespace vhs=TLID\contentelements\ViewHelpers}

<vhs:if checks="{0: settings.link}">
  <f:comment><!-- store the content --></f:comment>
  <store>
    <f:if condition="{images}">
      <f:for each="{images}" as="image">
        <f:image image="{image}" alt="{image.description}" title="{image.title}" />
      </f:for>
    </f:if>

    <vhs:if checks="{0: settings.headline, 1: settings.text}" type="or">
      <success>
        <div>
          <f:if condition="{settings.headline}"><h2><f:format.nl2br><vhs:shy>{settings.headline}</vhs:shy></f:format.nl2br></h2></f:if>
          <f:if condition="{settings.text}"><p><f:format.nl2br><vhs:shy>{settings.text}</vhs:shy></f:format.nl2br></p></f:if>
        </div>        
      </success>
    </vhs:if>
  </store>

  <f:comment><!-- use the content of this container on success --></f:comment>
  <success>
    <vhs:link href="{settings.link}" target="{settings.target}" class="box">
      <use />
    </vhs:link>
  </success>

  <f:comment><!-- use the content of this container on failure --></f:comment>
  <failure>
    <div class="box">
      <use />
    </div>
  </failure>
</vhs:if>

它还有一个store-element,因为我不喜欢它两次写相同的代码。因此,您可以选择保存一些流体并将其传递给成功和失败容器,而无需重复。

答案 6 :(得分:0)

是的,这感觉不对,但这是你能做到的唯一方法。这是viewhelper :: https://fluidtypo3.org/viewhelpers/fluid/master/IfViewHelper.html

的一个非常好的网站

答案 7 :(得分:0)

对我来说,最好的方式是使用&#39; f:循环&#39;。如果我需要将每个第3个元素划分为行,我只会这样做:

<v:variable.set  name="wraper" value='</div><div class="row">' />
<f:for each="{items}" as="item" iteration="itemIterator">
 ....
   <f:cycle values="{0: '', 1: '', 2: '{wraper}'}" as="cycle">
        {cycle -> f:format.raw()}
  </f:cycle>
 ...
</f:for>

答案 8 :(得分:0)

如果你有CObjects帮助这个逻辑OR的解决方法:

public void onResponse(String response) { 
                Log.d("2pg",response); 
                Toast.makeText(getApplicationContext(),response,Toast.LENGTH_LONG).show(); 
                recyclerView = (RecyclerView) findViewById(R.id.recyclerView); 

                //recyclerView.setAdapter(new CardAdapter(listWorkers, this)); 
                recyclerView.setHasFixedSize(true); 
                layoutManager = new LinearLayoutManager(getApplicationContext()); 
                recyclerView.setLayoutManager(layoutManager); 
                //Finally initializing our adapter 
                adapter = new CardAdapter(listWorkers, getApplicationContext()); 
                recyclerView.setAdapter(adapter); 

                getData();
            } 

 public void getData(){

     Worker worker=new Worker(); 
     worker.setImageUrl("http://vorkal.com/images/vorkal_cover.PNG"); 
     worker.setName("name"); 
     worker.setLocation("location"); 
     worker.setRating(5); 
     worker.setId(1); 
     worker.setPhone(784512369); 
     worker.setOccupation("occupation"); 
     worker.setPrice(20); 
     worker.setReview("Review"); 
     listWorkers.add(worker); 
     adapter.notifydatasetchanged()
 }

流体如果条件:

# Sidebar | 1 ColPos = 78
lib.sidebar1 < styles.content.get
lib.sidebar1.select.where = colPos=78
# Sidebar | 2 ColPos = 79
lib.sidebar2 < styles.content.get
lib.sidebar2.select.where = colPos=79

#LogicalOR
lib.tempLogicalOrSidebar = COA
lib.tempLogicalOrSidebar {
    10 < lib.sidebar1
    10.stdWrap.override.cObject =< lib.sidebar2
}

答案 9 :(得分:0)

如果条件与 f:if,v:variable.set v:math 相结合,则可以实现复杂的条件。使用数学ViewHelper来完成魔术并将其结果存储在变量中。然后使用比较器验证并对其进行操作。

以下是我的示例代码:

<f:for each="{customers}" as="customer" iteration="iterator">
    <v:variable.set name="isFirst" value="{v:math.modulo(a: iterator.cycle, b: settings.itemsperrow, fail: 0)}" />
    <f:if condition="{isFirst}==1">
        <div class="row">
    </f:if>
    <div class="col-md-{settings.colWidth}">
        <div class="clientlogo_ref">
            <f:image src="{customer.logo.originalResource.publicUrl}" />
        </div>                 
    </div>
    <f:if condition="{isFirst}==0">
        </div>
    </f:if>
</f:for>

此代码开始/结束每个X项的网格行,由 settings.itemsperrow 定义。这是可变的,可以在插件的配置中设置。它使用modulo来计算 iterator.cycle(以1开头的计数器)mod settings.itemsperrow 。如果结果为1,则它是行的第一个元素。 0表示它是最后一个,因此必须关闭行。

答案 10 :(得分:0)

2017年状态:

以下是使用stack属性的现代VHS viewhelper条件的示例。此示例还包含NULL检查和逻辑或(<v:if stack="{0: '{itemId}', 1:'==', 2:NULL, 3: '||', 4: '{itemId}', 5: '==', 6: '{falMedia.uid}'}"> <f:then> ... </f:then> </v:if> )以显示它是如何完成的。

NULL

请注意function makeExec(command) { return function(/* ignore results */) { return new Promise(function(resolve, reject) { child_process.exec(command, function(err, stdout, stderr) { if (err != null) reject(Object.assign(err, {stderr})); else resolve(stdout); }); }); }); } Promise.resolve() .then(makeExec("git pull")) .then(makeExec("git push -u origin branchname")) .then(makeExec("git pull origin develop")) .then(makeExec("git checkout develop")) .then(makeExec("git merge branchname")) .then(makeExec("git push")) .catch(function(err) { //display an error message }) 未引用!