web-dev-qa-db-fra.com

TYPO3 Complexe fluide si conditions

J'essaie d'écrire ce qui suit si la condition est fluide mais cela ne fonctionne pas comme je l'espère.

Condition Dans le cadre d'une boucle for, je souhaite vérifier si l'élément est le premier ou les 4e, 8e, etc.

J'aurais pensé que ce qui suit fonctionnerait, mais il affiche le code pour chaque itération.

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

J'ai réussi à le faire fonctionner avec un if imbriqué, mais je me sens mal d'avoir deux fois la même section de code et d'avoir également la vérification du cycle, utilisez un <f:else> au lieu de == 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
dmanners

TYPO3 v8

Mise à jour de la réponse pour TYPO3 v8. Ceci est cité de la réponse de Claus ci-dessous:

Mise à jour de ces informations avec la situation actuelle:

Sur TYPO3v8 et versions ultérieures, la syntaxe suivante est prise en charge, qui convient à parfaitement avec votre cas d'utilisation:

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

De plus, la syntaxe est supportée comme ceci:

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

Ce qui peut être plus approprié dans certains cas (en particulier lorsque vous utilisez Une condition de la syntaxe en ligne où vous ne pouvez pas développer le mode balise dans Afin d'accéder au f: else avec le nouvel argument if).

TYPO3 6.2 LTS et 7 LTS

Pour des conditions if plus complexes (telles que plusieurs combinaisons ou/et), vous pouvez ajouter votre propre ViewHelper dans your_extension/Classes/ViewHelpers/. Il vous suffit d’étendre Fluides AbstractConditionViewHelper. Le simple if-ViewHelper qui expédie avec Fluid ressemble à ceci:

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();
        }
    }
}

Tout ce que vous avez à faire dans votre propre ViewHelper est d’ajouter plus de paramètres que $condition, comme $or, $and, $not, etc. Ensuite, il vous suffit d’écrire vos if-Conditions dans php et de rendre l’enfant alors. Pour votre exemple, vous pouvez utiliser quelque chose comme ceci:

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();
        }
    }
}

Le fichier se trouverait dans votre_extension/Classes/ViewHelpers/ExtendedIfViewHelper.php. Ensuite, vous devez ajouter votre espace de noms dans le Fluid-Template comme ceci (qui active tous vos ViewHelpers auto-écrits à partir de your_extension/Classes/ViewHelpers/dans le modèle:

{namespace vh=Vendor\YourExtension\ViewHelpers}

et appelez-le dans votre modèle comme ceci:

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

Edit: mis à jour.

17
Daniel

Mise à jour de ces informations avec la situation actuelle:

Sur TYPO3v8 et les versions ultérieures, la syntaxe suivante est prise en charge et correspond parfaitement à votre cas d'utilisation:

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

De plus, la syntaxe est supportée comme ceci:

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

Ce qui peut être plus approprié dans certains cas (en particulier lorsque vous utilisez une condition dans la syntaxe en ligne où vous ne pouvez pas développer en mode balise afin d'accéder au f:else avec le nouvel argument if).

10
Claus Due

v: if.condition sera obsolète dans vhs V2.0 utilisez v: if pile à la place: https://github.com/FluidTYPO3/vhs/issues/493

6
rob-ot

Dans de nombreux cas, il suffit d'utiliser une comparaison de tableaux - vous n'avez donc pas besoin de créer un assistant de visualisation personnalisé.

ET

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

Malheureusement, cela fonctionne uniquement pour vérifier si une variable est définie et non par rapport à une valeur. Mais dans de nombreux cas, cela suffit.

PS: (avec cette comparaison de tableau, vous pouvez également comparer des chaînes)

4
Tobias Gaertner

Vous pouvez également utiliser l'option If Condition Extend ViewHelper fournie par l'extension VHS :

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

Remarque supplémentaire: l'extension VHS fournit de nombreux ViewHelpers utiles. Je pense que beaucoup d’entre eux devraient être inclus dans TYPO3 Fluid.

3
Leon de Rijke

En plus de la réponse de Daniels, j'ai créé un ViewHelper qui accepte plusieurs conditions, avec un "et" -mode (par défaut) ou un "ou" -mode:

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

Bien que cela puisse être écrit beaucoup mieux, cela fonctionne . Voici comment je l’utilise:

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

Il a également un élément store, car je n'aime pas écrire deux fois le même code. Vous pouvez donc éventuellement économiser du liquide et le transmettre aux conteneurs de succès et d’échec sans répétition.

1
Mohammer

Pour moi, le meilleur moyen d'utiliser 'f: cycle'. Si j'ai besoin d'un appareil pour les lignes chaque 3ème élément, je fais juste:

<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>
0
Oleg V Karun

Il est possible d'implémenter des conditions complexes si une combinaison de f: if, v: variable.set et v: math . Utilisez le math ViewHelper pour faire la magie et stocker son résultat dans une variable. Puis utilisez si les comparateurs pour valider et agir en conséquence.

Voici mon exemple de code:

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

Ce code commence/termine une ligne de grille pour chaque élément X, défini par settings.itemsperrow . Ceci est variable et peut être défini dans la configuration du plugin. Il utilise modulo pour calculer iterator.cycle (compteur commençant par 1) mod settings.itemsperrow . Si le résultat est 1, il s'agit du premier élément d'une ligne. 0 signifie que c'est la dernière, donc la ligne doit être fermée.

0
Maddin

Oui, c'est faux, mais c'est la seule façon de le faire. C'est un très bon site pour viewhelper :: https://fluidtypo3.org/viewhelpers/fluid/master/IfViewHelper.html

0
Tjade

Si vous avez des objets CObjects aider cette solution de contournement pour un OU logique:

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

FLUID SI CONDITION:

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

Statut 2017:

Voici un exemple d’une condition de spectateur VHS moderne utilisant l’attribut stack. Cet exemple contient également une vérification NULL et une logique ou (||) pour montrer comment procéder.

<v:if stack="{0: '{itemId}', 1:'==', 2:NULL, 3: '||', 4: '{itemId}', 5: '==', 6: '{falMedia.uid}'}">
    <f:then>
    ...
    </f:then>
</v:if>

Remarquez que NULL n'est PAS cité!

0
Jpsy