Генерация html на PHP

от автора

Предлагаю вашему вниманию свое решение по генерации html на PHP. Задача вроде бы тривиальная, но хотелось бы, чтобы это было расширяемо, кратко, но в тоже время с хорошим функционалом. Получилось вроде не плохо, чем и спешу поделиться.

Простой пример, обычная кнопка:

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(); 


Незакрытые теги закрываются автоматически.

Класс можно расширить, вплоть до использования в формах. Расширить можно за счет наследования или внедрения зависимости, за то, как будет выводится каждый тег и его атрибуты используется одна функция, поэтому можно легко переопределить это поведение.

 class CMyHtml extends CHtml {  	public function a($options = array()) { 		$default = array( 			'href' => 'javascript:void(0)' 		); 		return parent::a(array_replace($default, $options)); 	} }  
class CForm {                  private $_lastLabel = ''; 	public function __construct(CModel $model, CHtml $html = null) { 		$this->_model = $model; 		$this->_html = $html ?: CHtml::create(); 	}  	public function __call($method, $ps) { 		$options = $ps ? $ps[0]: array();  		if ($method === 'label') { 			$this->_lastLabel = isset($options['for']) ? $this->_model->getLabel($options['for']) : ''; 		}  		if ($method === 'text' && $this->_lastLabel) { 			$options = $options ?: $this->_lastLabel; 			$this->_lastLabel = ''; 		}                $this->_html->$method($options); 	       return $this;        } } 

Само решение можно посмотреть и попробовать на github.

Спасибо за внимание.

ссылка на оригинал статьи http://habrahabr.ru/post/270147/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *