以下のif条件を流体で記述しようとしていますが、期待どおりに動作しません。
条件 forループの一部として、アイテムが最初のものか、4番目、8番目などかを確認したい
私は以下がうまくいくと思ったでしょうが、すべての反復のコードを表示します。
<f:if condition="{logoIterator.isFirst} || {logoIterator.cycle % 4} == 0">
私はネストされたifでそれを機能させることができましたが、同じコードセクションが2回あり、サイクルチェックで<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条件(いくつかのor/andの組み合わせなど)については、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
よりも多くのパラメーターを追加することだけです。次に、if-Conditionsをphpし、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:ifスタックを使用してください: https://github.com/FluidTYPO3/vhs/issues/49
If Condition Extend ViewHelperVHS 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拡張機能には便利なViewHelperがたくさんあります。それらの多くはTYPO3 Fluidに含まれるべきだと思います。
多くの場合、配列比較を使用するだけで十分です。そのため、カスタムビューヘルパーを作成する必要はありません。
そして
<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 :(この配列比較では、文字列を比較することもできます)
Danielsの回答に加えて、「and」モード(デフォルト)または「or」モードのいずれかを使用して、複数の条件を受け入れる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>
同じコードを2回書くのが好きではないので、store-elementも追加されています。したがって、オプションで一部の流体を保存して、繰り返しの必要なしに成功と失敗の両方のコンテナに渡すことができます。
私にとって「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>
f:if、v:variable.setとv:mathの組み合わせで複雑なif条件を実装することは可能です。数学のViewHelperを使用して魔法をかけ、その結果を変数に格納します。次に、ifコンパレーターを使用して検証し、それに基づいて動作します。
これが私のサンプルコードです:
<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>
このコードはsettings.itemsperrowで定義されたすべてのXアイテムのグリッド行を開始/終了します。これは可変であり、プラグインの構成で設定できます。モジュロを使用してiterator.cycle(1で始まるカウンター)mod settings.itemsperrowを計算します。結果が1の場合、それは行の最初の要素です。 0は最後であることを意味するため、行を閉じる必要があります。
はい、それは間違っていると感じますが、これがあなたがそれを行うことができる唯一の方法です。これはビューヘルパーにとって非常に良いサイトです:: https://fluidtypo3.org/viewhelpers/fluid/master/IfViewHelper.html
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')}">
ステータス2017:
以下は、stack属性を使用した最新のVHSビューヘルパー条件の例です。この例には、NULLチェックと論理or(||
)それがどのように行われるかを示します。
<v:if stack="{0: '{itemId}', 1:'==', 2:NULL, 3: '||', 4: '{itemId}', 5: '==', 6: '{falMedia.uid}'}">
<f:then>
...
</f:then>
</v:if>
NULL
は引用されないことに注意してください!