簡體   English   中英

TYPO3流體復合物,如果條件

[英]TYPO3 Fluid complex if conditions

如果條件不流暢,我試着寫下面的內容,但它沒有按照我希望的方式工作。

條件作為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>

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> 

對於某些情況,這可能更合適(特別是在內聯語法中使用條件時,您無法擴展到標記模式以便使用新的if參數訪問f:else)。

TYPO3 6.2 LTS和7 LTS

對於更復雜的if-Conditions(如幾個或/和組合),您可以在your_extension/Classes/ViewHelpers/添加自己的ViewHelper。 您只需要擴展Fluids 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等。然后你只需在php中編寫if-Conditions並渲染then或者else子。 對於您的示例,您可以使用以下內容:

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>

編輯:更新。

使用當前情況更新此信息:

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

對於某些情況,這可能更合適(特別是在內聯語法中使用條件時,您無法擴展到標記模式以便使用新的if參數訪問f:else )。

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

您還可以使用VHS擴展提供的If Condition Extend ViewHelper

<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液體中。

對於許多情況,它足以使用數組比較 - 因此您不必創建自定義視圖助手。

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

要么

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

遺憾的是,這只是為了檢查是否設置了一個變量而不是一個值。 但對於很多情況來說這已經足夠了。

PS :(通過此數組比較,您還可以比較字符串)

除了Daniels的回答之外,我創建了一個ViewHelper,它接受多個條件,帶有“and”-mode(默認值)或“or”模式:

<?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,因為我不喜歡它兩次寫相同的代碼。 因此,您可以選擇保存一些流體並將其傳遞給成功和失敗容器,而無需重復。

是的,這感覺不對,但這是你能做到的唯一方法。 這是一個非常好的viewhelper網站:: https://fluidtypo3.org/viewhelpers/fluid/master/IfViewHelper.html

對我來說,使用'f:cycle'的最佳方式。 如果我需要為每行的第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>

如果你有CObjects幫助這個邏輯OR的解決方法:

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

流體如果有條件:

<f:if condition="{f:cObject(typoscriptObjectPath: 'lib.tempLogicalOrSidebar.10')}">

如果條件結合使用f:if,v:variable.setv:math ,則可以實現復雜的if。 使用數學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表示它是最后一個,因此必須關閉行。

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沒有引用!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM