View Source

<ac:macro ac:name="note"><ac:parameter ac:name="title">Under Construction</ac:parameter><ac:rich-text-body>
<p>This proposal is under construction and is not ready for review.</p></ac:rich-text-body></ac:macro>

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[{zone-template-instance:ZFDEV:Zend Proposal Zone Template}

{zone-data:component-name}
Zend_View_Helper_Loop
{zone-data}

{zone-data:proposer-list}
[My E-mail Address|mailto:mayer.martin@gmail.com]
{zone-data}

{zone-data:revision}
0.9 - 5 March 2008: First draft.
{zone-data}

{zone-data:overview}
Zend_View_Helper_Loop is a view helper that simplifies iterating over arrays and iterable objects and also simplifies common operations during the iteration.
{zone-data}

{zone-data:references}
* [Smarty: \{section}|http://www.smarty.net/manual/en/language.function.section.php]
* [Smarty: \{foreach}|http://www.smarty.net/manual/en/language.function.foreach.php]
{zone-data}

{zone-data:requirements}

{zone-data}

{zone-data:dependencies}
* Zend_View_Exception
{zone-data}

{zone-data:operation}
Zend_View_Helper_Loop wraps array or Iterator into Zend_View_Helper_Loop_Iterator and provides access to it. Zend_View_Helper_Loop_Iterator provides suplemental methods for:
* modifying iteration process befor starting
** setMax()
** setStep()
** setStart()
* retrieving iteration info while processing
** isFirst()
** isLast()
** getIndex()
** getIteration()
** getTotal()

See the use cases.
{zone-data}

{zone-data:milestones}

{zone-data}

{zone-data:class-list}
* Zend_View_Helper_Loop
* Zend_View_Helper_Loop_Iterator
{zone-data}

{zone-data:use-cases}
||Iterate over array||

inside view script:
{code}
<?php
$this->data = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);

// Loop over array, from second value, take every second value, maximum 5 loops
foreach ($this->loop($this->data)->setStart(2)->setStep(2)->setMax(5) as $key=>$val) {
echo "\n\nValue: ".$val;
echo "\nIndex: ".$this->loop()->getIndex();
echo "\nIteration: ".$this->loop()->getIteration();
echo "\nIs first: ".($this->loop()->isFirst() ? 'Yes' : 'No');
echo "\nIs last: ".($this->loop()->isLast() ? 'Yes' : 'No');
echo "\nIs odd: ".($this->loop()->isOdd() ? 'Yes' : 'No');
}

echo "\n\nTotal: ".$this->loop()->getTotal();
{code}

Outputs:
{noformat}
Value: 3
Index: 2
Iteration: 1
Is first: No
Is last: No
Is odd: Yes

Value: 5
Index: 4
Iteration: 2
Is first: No
Is last: No
Is odd: No

Value: 7
Index: 6
Iteration: 3
Is first: No
Is last: No
Is odd: Yes

Value: 9
Index: 8
Iteration: 4
Is first: No
Is last: No
Is odd: No

Value: 11
Index: 10
Iteration: 5
Is first: No
Is last: Yes
Is odd: Yes

Total: 5
{noformat}

||Nested iterations||
{code}
$table = array(
array(11, 12, 13, 14),
array(21, 22, 23, 24),
array(31, 32, 33, 34)
);

foreach ($this->loop($table) as $row) {
echo "<tr>\n";
echo " <td>".$this->loop()->getIteration()."</td>\n";
foreach ($this->loop('row', $row) as $cell) {
if ($this->loop('row')->isFirst()) {
echo " <td>".$cell."</td>\n";
} else {
echo " <td>".$cell."</td>\n";
}
}
echo "</tr>\n";
}
{code}

Output:
{noformat}
<tr>
<td>1</td>
<td><strong>11</strong></td>
<td>12</td>
<td>13</td>
<td>14</td>
</tr>
<tr>
<td>2</td>
<td><strong>21</strong></td>
<td>22</td>
<td>23</td>
<td>24</td>
</tr>
<tr>
<td>3</td>
<td><strong>31</strong></td>
<td>32</td>
<td>33</td>
<td>34</td>
</tr>
{noformat}
{zone-data}

{zone-data:skeletons}
{code}
class Zend_View_Helper_Loop
{
private $iterators = array();

/**
* @return Zend_View_Helper_Loop_Iterator
*/
public function loop($name = 'default', $iterable = null)
{
if (!is_string($name)) {
if (!is_array($name) && !($name instanceof Iterator)) {
throw new Zend_View_Exception("First argument must be string, array or instance of Iterator interface.");
}
$iterable = $name;
$name = 'default';
}

if ($iterable !== null) {
$iterator = new Zend_View_Helper_Loop_Iterator($iterable);
$this->iterators[$name] = $iterator;
}

return $this->iterators[$name];
}
}

class Zend_View_Helper_Loop_Iterator implements Iterator
{
/**
* Number of items in array
* @var int
*/
private $count;

/**
* Current iterator position
* @var int
*/
private $offset = 0;

/**
* Number of iteration
* @var integer
*/
private $iteration = 1;

/**
* Step between two iterations
* @var integer
*/
private $step = 1;

/**
* The offset to start from
* @var integer
*/
private $start = 0;

/**
* Max number of iterations
* @var integer
*/
private $max = null;

/**
* Iterated object
* @var array|Iterator
*/
private $iterable;

public function __construct($iterable)
{
$this->iterable = $iterable;

if (is_array($iterable) || $iterable instanceof Countable) {
$this->count = count($iterable);
} else {
$count = 0;
foreach ($iterable as $item) {
++$count;
}
$this->count = $count;
}
}

public function setStart($start)
{
$this->start = $start;
return $this;
}

public function setStep($step)
{
$this->step = $step;
return $this;
}

public function setMax($max)
{
$this->max = $max;
return $this;
}

/**
* @param $positions integer
*/
private function _moveForward($positions)
{
for ($i = 0; $i < $positions; ++$i) {
if ($this->offset >= $this->count) {
return;
}
if ($this->iterable instanceof Iterator) {
$this->iterable->next();
} else {
next($this->iterable);
}
++$this->offset;
}
}

/**
* Rewinds iterator to first item
*
* @return void
*/
public function rewind()
{
if ($this->iterable instanceof Iterator) {
$this->iterable->rewind();
} else {
reset($this->iterable);
}
if ($this->start) {
$this->_moveForward($this->start);
}
$this->iteration = 1;
}

/**
* Move to next entry
*
* @return void
*/
public function next()
{
$this->_moveForward($this->step);
++$this->iteration;
}

/**
* Get current item
*
* @return mixed
*/
public function current()
{
if ($this->iterable instanceof Iterator) {
return $this->iterable->current();
}

return current($this->iterable);
}

/**
* Get current key
*
* @return unknown
*/
public function key()
{
if ($this->iterable instanceof Iterator) {
return $this->iterable->key();
}

return key($this->iterable);
}

/**
* Enter description here...
*
* @return unknown
*/
public function valid()
{
if ($this->offset + $this->step <= $this->count && ($this->max === null || $this->iteration <= $this->max)) {
return true;
}

return false;
}

/**
* Returns true if current iteration is the first
* *
* @return boolean
*/
public function isFirst()
{
if ($this->offset === 0) {
return true;
} else {
return false;
}
}

/**
* Returns true if current iteration is the last
*
* @return boolean
*/
public function isLast()
{
if ($this->offset + $this->step >= min($this->count, $this->step * $this->max + $this->start)) {
return true;
} else {
return false;
}
}

/**
* Returns true if curren iteration number is even
*
* @return boolean
*/
public function isOdd()
{
return $this->iteration % 2 == 1;
}

/**
* Returns true if curren iteration number is odd
*
* @return boolean
*/
public function isEven()
{
return $this->iteration % 2 == 0;
}

/**
* Get current iteration number
*
* @return integer
*/
public function getIteration()
{
return $this->iteration;
}

/**
* Get current offset
*
* @return unknown
*/
public function getIndex()
{
return $this->offset;
}

/**
* Get the number of iterations that this will be looped
*/
public function getTotal()
{
return min(($this->count - $this->start) / $this->step, $this->max);
}
}

{code}
{zone-data}

{zone-template-instance}]]></ac:plain-text-body></ac:macro>