⬆️ ⬇️

PHP html generation

I bring to your attention my solution for generating html in PHP. The task seems to be trivial, but I would like it to be expandable, brief, but at the same time with good functionality. It turned out not so bad.



I’ll say at once (as many people think in the comments) that the task was not to write the template engine (there are so many of them) and not to replace the JavaScript template engine. I know perfectly well that the true way is to separate html and data. But I needed to write html in classes, to create the framework components, like the CGridView in yii, is it up to you to decide whether to put html in separate files in such places.



The main goal is to get rid of html in classes and functions.

')

A simple example, the usual button:



CHtml::create() ->p() ->a(array('href' => 'http://habrahabr.ru', 'class' => 'btn')) ->text('') ->render(); 


Result:



 <p><a href="http://habrahabr.ru" class="btn"></a></p> 




Nothing tricky, it would be possible and this is limited, but I wanted cycles:

 $arr = array('1' => '', '2' => ''); CHtml::create() ->select($options) ->each(CHtml::plainArray($arr, 'value', 'text')) ->option('array("value" => $data->value)') ->text('$data->text') ->end() ->endEach() 


Here it was necessary to call the function plainArray () which turns the array in the form:

 $arr = array( array('value' => '1', 'text' =>''), array('value' => '2', 'text' => '') ); 


Tags inside the loop can contain functions or strings with eval expressions, any nesting, an example with a table:



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




Unclosed tags are closed automatically.



The class can be expanded, up to use in forms. You can extend it through inheritance or dependency injection, for how each tag is displayed and its attributes use one function, so you can easily override this behavior.



 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; } } 




The solution itself can be viewed and tried on github .



Thanks for attention.

Source: https://habr.com/ru/post/270147/



All Articles