Предлагаю вашему вниманию свое решение по генерации html на PHP. Задача вроде бы тривиальная, но хотелось бы, чтобы это было расширяемо, кратко, но в тоже время с хорошим функционалом. Получилось вроде не плохо.
Сразу скажу( как многие считают в комментариях), что задача ставилось не написать шаблонизатор (которых и так много) и не заменить шаблонизатор JavaScript. Я прекрасно знаю, что true way это разделять html и данные. Но мне понадобилось писать html в классах, для создания компонентов фреймворка, на подобие CGridView в yii, стоит ли в таких местах выносить html в отдельные файлы решать вам.
Основная цель, избавится от html в классах и функциях.
Простой пример, обычная кнопка:
CHtml::create()
->p()
->a(array('href' => 'http://habrahabr.ru', 'class' => 'btn'))
->text('Перейти')
->render();
Результат:
<p><a href="http://habrahabr.ru" class="btn">Перейти</a></p>
Ничего хитрого, можно было бы этим и ограничется, но захотелось циклы:
$arr = array('1' => 'Первый', '2' => 'Второй');
CHtml::create()
->select($options)
->each(CHtml::plainArray($arr, 'value', 'text'))
->option('array("value" => $data->value)')
->text('$data->text')
->end()
->endEach()
Тут понадобилось вызвать функцию plainArray() которая превращает массив в виде:
$arr = array(
array('value' => '1', 'text' =>'Первый'),
array('value' => '2', 'text' => 'Второй')
);
Теги внутри цикла могут содержать функции или строки с eval выражениями, вложенность любая, пример с таблицей:
$columns = array(
array('id' => 'NAME', 'label' => 'Имя'),
array('id' => 'AGE', 'label' => 'Возраст')
);
$data = array(
array('NAME' => 'Петр', 'AGE' => 29),
array('NAME' => 'Василий', 'AGE' => 32)
);
CHtml::create()
->table()
->thead()
->tr()
->each($columns)
->th()
->text(function($column){
return $column['label'];
})
->end()
->endEach()
->end()
->end()
->tbody()
->each($data)
->tr()
->each($columns)
->td()
->text(function($row, $column) {
return $row[$column['id']];
})
->end()
->endEach()
->end()
->endEach()
->render();