Как известно PHP имеет встроенный шаблонизатор. Весь текст, который интерпретатор встречает межде тегами обозначающими конец и начало PHP кода, он отправляет в буфер вывода. Убедиться в этом можно на следующем примере:
<?php echo "Hello, "; ?> World. <?php echo "All is fine\n";
Выводом программы будет «Hello, World. All is fine», что и следовало ожидать. Но что происходит на самом деле? Посмотрим на другой пример:
<?php $three = function() { ?> Three <?php }; $one = function() { ?> One <?php }; $two = function() { ?> Two <?php }; $one(); $two(); $three();
Если выполнить исходный код, то выводом программы будет «One Two Three», что немного странно. Ведь текст в коде встречался совсем в другой последовательности и в буфер вывода должно было попасть «Three One Two».
На самом деле PHP не отправляет текст в буфер вывода как только он его встречает. В интерпертаторе языка есть специальный опкод ZEND_ECHO (имено в этот опкод транслируется echo) и кусок текста между PHP кодом будут транслироваться в аргумент этого опкода. Именно поэтому у нас текст во втором примере выводиться в той последовательности в которой мы вызываем созданные анонимные функции (вывод текста стал частью анонимных функций благодаря опкоду ZEND_ECHO.
В подтверждении моих слов кусочек содержимого файла zend_language_parser.y
| T_INLINE_HTML { zend_do_echo(&$1 TSRMLS_CC); }
И реализация самой функции zend_do_echo из zend_compile.c:
void zend_do_echo(const znode *arg TSRMLS_DC) /* {{{ */ { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_ECHO; SET_NODE(opline->op1, arg); SET_UNUSED(opline->op2); } /* }}} */
Ну и какой от этого толк?
Толк на самом деле есть. Ведь мы можем привязать к анонимной функции произвольный вывод, а значит теоретически это можно использовать в реализации шаблонизатора. Немного подумав я набросал следующий вариант содержимого файла такого теоретического шаблонизатора:
$c->header->addClass('header')->setContent(function() { ?> <ul> <?= $c->li->addClassIf(1, 'active')->setContent('Main') ;?> <?= $c->li->addClassIf(0, 'active')->setContent('Account') ;?> <?= $c->li->addClassIf(0, 'active')->setContent('FAQ') ;?> <?= $c->li->addClassIf(0, 'active')->setContent('Logout') ;?> </ul> <?php })->_print(); ?>
Где в переменой $c->header объект класса CElement. Удобно? На вкус и цвет товарищей нет)
ссылка на оригинал статьи http://habrahabr.ru/post/171097/
Добавить комментарий