Skip to content

Loops#


Loops execute a block of code a specified number of times, or while a specified condition is true. MivaScript provides three constructs for creating loops. Care must be taken to avoid endless loops, as they consume server resources until the engine times out.

Loop Constructs#

MivaScript provides three loop constructs:
- <MvWHILE>: Evaluates a condition at the start of each iteration and repeats as long as it’s true.
- <MvFOR>: Loops a specific number of times when the iteration count is known in advance.
- <MvFOREACH>: Iterates over each item in an array, with an optional early exit via <MvFOREACHSTOP>.

Syntax: MvWHILE#

The <MvWHILE> tag evaluates its EXPR attribute each time before entering the loop. To exit early, use <MvWHILESTOP>.

<MvASSIGN NAME="g.counter" VALUE="{ 1 }">
<MvWHILE EXPR="{ g.counter LE 10 }">
    Execute the code here 10 times.

    <MvASSIGN NAME="g.counter" VALUE="{ g.counter + 1 }">
</MvWHILE>

Breaking out of a loop#

You can manually end a <MvWHILE> loop using <MvWHILESTOP>, for example when an error condition is detected:

<MvASSIGN NAME="g.counter" VALUE="{ 1 }">
<MvWHILE EXPR="{ 1 }">
    Execute the code here.

    <MvASSIGN NAME="g.counter" VALUE="{ g.counter + 1 }">
    <MvIF EXPR="{ g.counter GT 100 }">
        <MvWHILESTOP>
    </MvIF>
</MvWHILE>

Example: Looping through a list#

Process a comma-separated list (l.fieldlist) one item at a time:

<MvASSIGN NAME="l.posn" VALUE="{ 1 }">
<MvASSIGN NAME="l.item" VALUE="{ gettoken(l.fieldlist, ',', l.posn) }">
<MvWHILE EXPR="{ l.item }">
    <MvEVAL EXPR="{ l.posn $ '. ' $ l.item }"><br>

    <MvASSIGN NAME="l.posn" VALUE="{ l.posn + 1 }">
    <MvASSIGN NAME="l.item" VALUE="{ gettoken(l.fieldlist, ',', l.posn) }">
</MvWHILE>

Syntax: MvFOR#

When you know the exact number of iterations, use <MvFOR> with the COUNT attribute, and optionally INDEX:

<MvFOR COUNT="{ 100 }">
    Execute the code here 100 times.
</MvFOR>

<MvFOR INDEX="l.pos" COUNT="{ 100 }">
    <MvEVAL EXPR="{ l.pos }">.<br>
</MvFOR>

<MvFOR> also supports advanced attributes for custom stepping and bounds:

<table><tr>
<td>
<MvFOR INDEX="l.pos" FIRST="{ 1 }" NEXT="{ l.pos + 2 }" LAST="{ 100 }">
    <MvEVAL EXPR="{ l.pos }">.<br>
</MvFOR>
</td>
<td>
<MvFOR INDEX="l.pos" FIRST="{ 2 }" NEXT="{ l.pos + 2 }" LAST="{ 100 }">
    <MvEVAL EXPR="{ l.pos }">.<br>
</MvFOR>
</td>
</tr></table>

Syntax: MvFOREACH#

<MvFOREACH> is ideal for iterating over array data. Specify ARRAY, ITERATOR, and optionally INDEX:

<MvFOREACH ITERATOR="l.item" ARRAY="l.orders" INDEX="l.pos">
    <MvEVAL EXPR="{ l.pos }">. <MvEVAL EXPR="{ l.item:Fname }"> <MvEVAL EXPR="{ l.item:Lname }"><br>
</MvFOREACH>

<MvFOREACH> supports the same advanced attributes as <MvFOR> - including skipping items, reversing order, limiting iterations, and conditional exits. See the MvFOREACH documentation for details.