[Smarty Basics] Schleifen bauen mit {foreach}

Diskussionen zur Smarty-Template-Engine
Locked
nhaack

[Smarty Basics] Schleifen bauen mit {foreach}

Post by nhaack »

Hallo zusammen,

Mit Schleifen und einigen kleinen Kniffen kann man etwas Pepp und Abwechslung in das Layout bringen. Lange Tabellen können eintönig wirken, ab und zu mal die Headlines wiederholen damit man sich zurecht findet oder das erste Element größer darstellen als die Folge-Elemente - wären hier Beispiele.

Dies funktioniert mit allen Arrays die euch im Template zur Verfügung stehen. Manchmal möchte man hier die Daten bestimmter Arrays irgendwie ausgeben, irgendwas Nummerieren (und reicht hier nicht) etc pp.

Für solche Aufgaben eignen sich Schleifen. Für die folgenden Beispiele nehmen wir ein Array ($my_array) mit 9 Werten ($myarray['eins'] = 1 ... $myarray['neun'] = 9).

Wenn ich einfach alle Elemente unformatiert wiedergeben möchte, kommt man mit einer {foreach}-Schleife weiter.

Code: Select all


{foreach from=$my_array item=array_element}
{$array_element}
{/foreach}


Wird folgendes im Browser anzeigen.

Code: Select all

 

0 1 2 3 4 5 6 7 8 9 


Möchte ich einen Zeilenumbruch im HTML Dokument erreichen, kann man folgendes machen:

Code: Select all


{foreach from=$my_array item=array_element}
{$array_element}<br />
{/foreach}

Man kann das HTML mit dem Smarty Code also einwandfrei mischen ;)


Wenn ich alle Ergebnisse als Liste ausgeben möchte, sieht das dann so aus:

Code: Select all


<ul>
{foreach from=$my_array item=array_element}
  <li>Dieses Element enthält: "{$array_element}"</li>
{/foreach}
</ul>

Wichtig ist hier das ausserhalb der Schleife zu platzieren. Sonst würden diese Elemente mit jedem Durchlauf wiederholt werden.

Wenn man noch an den Schlüsselwert des Array Elementes (Name des aktuellen Schlüssel) herankommen möchte, kann man der foreach-Schleife einfach den Variabelnamen zur Ausgabe angeben.

Code: Select all


<ul>
{foreach from=$my_array item=array_element key=array_element_name}
  <li>Das Element "{$array_element_name}" enthält den Wert "{$array_element}"</li>
{/foreach}
</ul>


Man kann natürlich auch prüfen ob das Array Element Leer ist und in diesem Fall etwas anderes ausgeben

Code: Select all


<ul>
{foreach from=$my_array item=array_element key=array_element_name}
  <li>Das Element mit Namen "{$array_element_name}" enthält den Wert "{$array_element}"</li>
{foreachelse}
  <li>Das Array ist leer</li>
{/foreach}
</ul>

Den Index des aktuellen Elementes der Schleife erhalten

Code: Select all


<ul>
{foreach from=$my_array item=array_element name=array_name}
  <li>Das Element Nr. "{$smarty.foreach.array_name.index}" enthält den Wert "{$array_element}"</li>
{/foreach}
</ul>


Um z.B. nach jedem 5-ten Element eine neue Liste zu beginnen (bei 15 Elementen hätten wir 3 Listen mit je 5 Elementen)

Code: Select all


<ul>
{foreach from=$my_array item=array_element name=array_name}
 {if $smarty.foreach.array_name.index % 5 == 0}
 </ul><ul>
 {/if}
  <li>Das Element Nr. "{$smarty.foreach.array_name.index}" enthält den Wert "{$array_element}"</li>
{/foreach}
</ul>


Achtung, der Index beginnt beim Zählen mit "0"!, wenn wir die aktuelle Iteration brauchen (also den wievielten Durchlauf, beginnend mit "1") müssen wir wie folgt vorgehen um die entsprechende Eigenschaft anzufragen:

Code: Select all


<ul>
{foreach from=$my_array item=array_element name=array_name}
  <li>Das Element Nr. "{$smarty.foreach.array_name.iteration}" enthält den Wert "{$array_element}"</li>
{/foreach}
</ul>

Wenn ich jetzt aber z.B. nur das erste Element anders gestaltet wiedergeben möchte, kann ich auf das erste oder aber auch das letzte Element bequem direkt zugreifen, ohne den Namen, bzw. Index des letzten Elementes zu kennen. Dafür müssen wir nur {foreach ... name= ...} einen Wert zugewiesen haben.

Code: Select all


<ul>
{foreach from=$my_array item=array_element name=array_name}
  <li>{if $smarty.foreach.array_name.first}<em>Erster: {$array_element}</em>{else}{$array_element}{/if}</li>
{/foreach}
</ul>

Um z.B. eine Summe der Elemente am Ende wiederzugeben, gibt es noch .total (funktioniert nur am Ende des Schleifendurchlaufes).

Code: Select all

<ul>
{foreach from=$my_array item=array_element name=array_name}
  <li>Dieses Element enthält: "{$array_element}"</li>
  {if $smarty.foreach.array_name.last}
  <li>Gesamtzahl der Einträge: {$smarty.foreach.array_name.total} items</li>
  {/if}
{/foreach}
</ul>

Sonstiges
-----------------------------------

Das waren jetzt einmal ein paar simple Beispiele auf Basis von ungeordneten Listen und einem einfachen Array. Schleifen lassen sich aber auch auf Arrays von Objekten anwenden.

Code: Select all


<ul>
{foreach from=$my_array item=array_element}
  <li>{$array_element->object_name}"</li>
{/foreach}
</ul>

Um sich durch mehrdimensionale Arrays zu wühlen kann man die foreach Schleifen auch schachteln

Code: Select all


<ul>
{foreach from=$my_array item=array_element}
  {foreach from=$array_element item=array_sub_element}
  <li>{$array_sub_element}"</li>
  {/foreach}
{/foreach}
</ul>

Und natürlich ist man nicht auf Listen begrenzt. Es können alle Formen von Smarty, HTML oder ähnlichem innerhalb der Schleifen verwendet werden.


Um Schleifen z.B. in Javascript einzusetzen muss man {literal} unterbrechen und entsprechende Sonderzeichen Escapen

Code: Select all


{literal}
  <__script__ type="text/javascript">
    //<![CDATA[
      var data = [
{/literal}
{foreach from=$my_array item=array_element}
      {literal}{{/literal} first: "{$array_element->string_id} ", last: "{$array_element->text|escape:'javascript'}" {literal}}{/literal}
{/foreach}
{literal}
      ];
    //]]>
  </__script>
{/literal}

Wenn ihr noch Ideen habt, was man mit Foreach-Schleifen in Smarty machen kann, immer her damit...  :D

Beste Grüße
Nils
nicmare
Power Poster
Power Poster
Posts: 1150
Joined: Sat Aug 25, 2007 9:55 am
Location: Berlin

Re: [Smarty Basics] Schleifen bauen mit {foreach}

Post by nicmare »

Frage: wie kann man die Werte aus einer foreach schleife ohne großen aufwand zufällig ausgeben?
Also aktuell werden die werte immer in der selben reihenfolge ausgegeben. ich möchte aber dass die beim neuladen der seite immer eine unterschiedl. reihenfolge haben. Habe nun schon gegooglet und das Forum durchsucht aber das scheint garnicht so einfach zu sein. mein problem ist, dass ich genau weiß wieviele Werte ausgegeben werden. Also das Array ist unterschiedlich lang.
nhaack

Re: [Smarty Basics] Schleifen bauen mit {foreach}

Post by nhaack »

Probier mal:

{$my_array|@print_r}
{assign var=my_array value=$my_array|@array_rand}
{$my_array|@print_r}

Das |@print_r nur um direkt zu sehen, ob er umsortiert ;)

Beste Grüße
Nils
nicmare
Power Poster
Power Poster
Posts: 1150
Joined: Sat Aug 25, 2007 9:55 am
Location: Berlin

Re: [Smarty Basics] Schleifen bauen mit {foreach}

Post by nicmare »

das scheint nicht zu funzen
nhaack

Re: [Smarty Basics] Schleifen bauen mit {foreach}

Post by nhaack »

äääh... ja... jetzt fällt mir auch der Fehler auf ;) (doooh)

Code: Select all


{assign var=random_index value=$my_array|@array_rand}

Index des zufälligen Elementes = {$random_index}

So erhältst du ein zufälliges Element aus dem Array... bzw. den Index des zufälligen Elementes.

Ich glaube, entweder musst du die Änderung der Reihenfolge vor Übergabe an Smarty lösen oder dir aber einen eigenen kleinen Modifier schreiben.

Grüezis
Nils
nicmare
Power Poster
Power Poster
Posts: 1150
Joined: Sat Aug 25, 2007 9:55 am
Location: Berlin

Re: [Smarty Basics] Schleifen bauen mit {foreach}

Post by nicmare »

um das kind mal beim namen zu nennen, das ist meine foreach abfrage:

Code: Select all

<ul>
{foreach from=$events key=key item=event}
	<li>
		<a href="{$event.url}">
			{$event.event_title}
		</a>
	</li>
{/foreach}
</ul>
das wird mir sinngemäß ausgegeben:

Code: Select all

Veranstaltung1
Veranstaltung2
Veranstaltung3
Veranstaltung4
Veranstaltung5
Ich möchte aber:

Code: Select all

Veranstaltung3
Veranstaltung2
Veranstaltung5
Veranstaltung1
Veranstaltung4
Also immer eine andere Auflistung beim Aktualisieren der Seite. Wie bei einem Webbanner.

Nach deinem Vorschlag müsste das dann so aussehen oder?

Code: Select all

<ul>
{assign var=randomitem value=$events|@array_rand}
{foreach from=$randomitem key=key item=event}
	<li>
		<a href="{$event.url}">
			{$event.event_title}
		</a>
	</li>
{/foreach}
</ul>
Aber das scheint auch nicht zu klappen
Last edited by nicmare on Wed Aug 25, 2010 7:49 am, edited 1 time in total.
nhaack

Re: [Smarty Basics] Schleifen bauen mit {foreach}

Post by nhaack »

Naja, das meinte ich ja, mein Vorschlag war falsch und funktioniert nicht ;)

Kannst du die Events nicht vorher umsortieren, also in dem Script, welches dir die Events anliefert per PHP das Array zufällig sortieren (z.B. mit shuffle())? Alternativ könntest du einen neuen Modifier erstellen, da es in Smarty anscheinend nicht direkt möglich ist, das Array zufällig zu sortieren (wenn ich mich nicht irre).

Grüezis
Nils
LightFighter

Re: [Smarty Basics] Schleifen bauen mit {foreach}

Post by LightFighter »

Hallo!
Ich komme mit meiner Schleife nicht weiter. Genau gesagt mit etwas innerhalb der Schleife. Es müssen nummerische Werte in der Schleife addiert werden.

Ich definiere eine Variable mit dem Anfangswert 0. Zu diesem Wert müssen dann in jedem Durchlauf ein weiterer Wert addiert werden, aber so dass das Summeergebnis erhalten bleibt. Vereinfacht sieht mein Versuch so aus:

{assign var='a' value=0} {* $b=wert_aus_der_DB *}
{foreach from=$cartitems item='oneitem' name='loop'}
{math equation='x+y' x=$a y=$b}
{/foreach}

Leider wird in jedem Durchlauf die $a immer wieder auf 0 gesetzt, obwohl der Anfangswert außerhalb der Schleife definiert ist. Ich möchte aber eine Summe am Ende haben. Wie kriege ich das hin?
nhaack

Re: [Smarty Basics] Schleifen bauen mit {foreach}

Post by nhaack »

Hi LightFighter,

guck' dir mal die Rechenschritte genau an.

1. Du definierst $A und $B vor der Schleife
2. In jedem Schleifendurchlauf addierst du $A zu $B

Mehr machst du nicht ;)

Was du bräuchtest:

1. Du definierst $A und $B vor der Schleife
2. In jedem Schleifendurchlauf addierst du $A zu $B
3. $A erhält das Ergebnis der Berechnung

Noch ein kleiner Hinweis: für die Addition musst du nicht auf math zugreifen.

Denkbar wäre also

Code: Select all


{assign var='a' value=$a+$b}

Wobei, so wie es aussieht, willst du als Ergebniss eine Multiplikation eines Wertes. Und zwar so oft, wie du Einträge im Array hast.

Jetzt wird math wieder interessant ;) ... in Kombination mit @count

Code: Select all


{math equation='x*y' x=$cartitems|@count y=wert_aus_der_DB}

Grüezis
Nils
LightFighter

Re: [Smarty Basics] Schleifen bauen mit {foreach}

Post by LightFighter »

Hallo, nhaack!

Vielen Dank für deine Beteiligung. Ist echt elegant, wie du mein Problem gelöst hast. Mein Gedankenfehler habe ich auch schon entdeckt. Löste ich dies aber über ein UDT, und zwar so:

Code: Select all

$items = $params['items'];
$tax = 0;
foreach($items as $produkte) {
$tax = $tax+$produkte->unit_price*$produkte->mwst*$produkte->quantity;
}
$smarty->assign('mwst_sum',$tax);
Ich übergebe hier ein Array mit den ganzen Informationen über ein Produkt im Warenkorb, fummel daraus was ich brauche (MwSt.-Anteil) und addiere dann in der Schleife alles zusammen. Anschließend packe ich das Ergebnis in eine Smarty-Variable.
Aber so, wie du es vorgeschlagen hast, ist viel einfacher.
Locked

Return to “Smarty-Tipps und -Tricks”