I always missed the foreachelse function I used in smarty-templates, so I created a ViewRenderer that handles this.
My regex skills are very bad, so if someone has a better solution, feel free to share the changes you’ve made here.
Usage example:
<div class="blogs">
<h1>Blogs</h1>
<? foreach ($blogs as $blog) : ?>
<?= $this->renderPartial('_item', compact('blog')); ?>
<? foreachelse ?>
There aren't any blogs yet <img src='http://www.yiiframework.com/forum/public/style_emoticons/default/sad.gif' class='bbc_emoticon' alt=':(' />
<? endforeach; ?>
</div>
Becomes: (note, I also implemented a PHP shorthand tag replacement)
<div class="blogs">
<h1>Blogs</h1>
<?php if(count($blogs) > 0) foreach($blogs as $blog){ ?>
<?php echo $this->renderPartial('_item', compact('blog')); ?>
<?php } else { ?>
There aren't any blogs yet <img src='http://www.yiiframework.com/forum/public/style_emoticons/default/sad.gif' class='bbc_emoticon' alt=':(' />
<?php } ?>
</div>
Viewrenderer: (see http://www.yiiframework.com/doc/guide/topics.prado how to implement)
<?php
class ViewRenderer extends CViewRenderer {
private $_input;
private $_output;
private $_sourceFile;
/**
* Parses the source view file and saves the results as another file.
* This method is required by the parent class.
* @param string the source view file path
* @param string the resulting view file path
*/
protected function generateViewFile($sourceFile, $viewFile) {
static $regexRules = array(
'<\?=*[^x]\s*', // PHP shorthand
'foreach?\s*\(\s*(.*?)\s(.*?)\)?\s*[{:]', // foreach
'foreachelse?\s*[{:]*', // foreachelse
'endforeach;', // foreachelse
);
$this->_sourceFile = $sourceFile;
$this->_input = file_get_contents($sourceFile);
$n = preg_match_all('/'.implode('|', $regexRules).'/msS', $this->_input, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
$textStart = 0;
$this->_output = '';
for ($i = 0; $i < $n; ++$i) {
$match =& $matches[$i];
$str = $match[0][0];
$matchStart = $match[0][1];
$matchEnd = $matchStart + strlen($str) - 1;
if ($matchStart > $textStart)
$this->_output .= substr($this->_input, $textStart, $matchStart - $textStart);
$textStart = $matchEnd + 1;
if (strpos($str, '<?=') === 0) // expression
$this->_output .= '<?php echo '.$match[1][0];
else if (strpos($str, '<?') === 0) // statement
$this->_output .= '<?php '.$match[1][0];
else if (strpos($str, 'foreachelse') === 0)
$this->_output .= ' } else { ';
else if (strpos($str, 'endforeach') === 0)
$this->_output .= ' } ';
else if (strpos($str, 'foreach') === 0)
$this->_output .= 'if(count('.$match[1][0].') > 0) foreach('.$match[1][0].' '.$match[2][0].'){';
}
if ($textStart < strlen($this->_input))
$this->_output .= substr($this->_input, $textStart);
//echo $this->_output; exit; //debug
file_put_contents($viewFile, $this->_output);
}
}