Forums / National / Russian / Шаблонизатор

<<<1234>>>

dervan
#31 2009-03-10 04:05
# medar : dervan
Надо будет решить эту проблему по-другому - вообще отказаться от scan_globals(), а при парсинге тэгов {PHP.xxx} обращаться непосредственно к $GLOBALS.

Кстати, medar, если так переделывать, то вот от таких накладок при работе parse() всё равно не избавишься:
# dervan : К тому же есть нюансы при работе метода parse(). Например, такой код в конце system/header.php, плюс тег {PHP.TEST_DEFINE) в header.tpl:
define('TEST_DEFINE', 'test_define');
$TEST_DEFINE = '';

$t->parse("HEADER");
$t->out("HEADER");

echo $TEST_DEFINE, '<br />';
В случае оригинального scan_globals() глобальная переменная $TEST_DEFINE останется пустой строкой (значение будет присвоено её копии), а с переделанным scan_globals() после работы парсера $TEST_DEFINE получит значение 'test_define'.

А действия, подобные
$t->assign('PHP', 'test_assign');
это совершенно идиотские действия, что со старым scan_globals(), что с переделанным - из того же разряда, что и доступ к глобальным переменным через $t->vars. Так что если отказываться от локальной копии $GLOBALS, пожалуй нет смысла совсем убирать scan_globals(), проще его подправить.
Dayver
#32 2009-03-10 04:51
# medar : Логику написали, теперь регулярки поправить внутри и все ок будет.
Тогда может уже закинешь в транк хотя бы с прикрученой логикой(в англ ветке отписался = офф. часть выполнил .... там молчат - знач моно закидывать!)? .... а с регулярками уже как нить опосля!?
Pavlo Tkachenko aka Dayver
medar
#33 2009-03-10 15:28
Я просто жду реакции англоязычных товарищей, но её, походу, не будет.
Приличия соблюдены, сейчас закоммичу.
rangjungyeshe.ru
Ratibor
#34 2009-03-15 04:06
# medar : Использование.

Итак, у нас в шаблонах стала доступна вот такая вот конструкция:
<!-- IF <if_statement> -->
этот текст будет показан если <if_statement> является true
<!-- ENDIF -->

<if_statement> - это логическое php-выражение, только вместо переменных используются tpl-тэги (в том числе и глобальные!)

Примеры:
<!-- IF {PHP.usr.profile.user_name} == "admin" -->
привет, админ !
<!-- ENDIF -->

Попробовал сейчас добавить логику в шаблон.
Работает вроде все нормально, но есть небольшое замечание.

Чтоб было более понятно, объясню на приведенном выше примере:
если имя не admin, т.е. условие не срабатывает, то все нормально,
всмысле в выходном коде это все вырезается,
но если это admin, т.е. условие срабатывает, то в выходном коде мы видим следующее:
<!-- IF admin == "admin" -->
привет, админ !
<!-- ENDIF -->

Не порядок, надо бы вырезать вот это:
<!-- IF admin == "admin" -->
<!-- ENDIF -->
Не задавай глупых вопросов, не услышишь вранья.
Sergeich
#35 2009-03-15 05:25
Приведите пример пожалуйста для случая с зарегеным юзером и гостем. Т.е. если на сайт зашёл гость - показывается один блок, а если юзер - другой.
dervan
#36 2009-03-15 06:17
# Sergeich : ... если на сайт зашёл гость - показывается один блок, а если юзер - другой.
<!-- IF {PHP.usr.id} < 1 -->
вы - гость
<!-- ENDIF -->
<!-- IF {PHP.usr.id} >= 1 -->
вы - зарегистрированный посетитель
<!-- ENDIF -->
Ratibor
#37 2009-03-15 14:36
Данная функция понравилась, можно намного гибче шаблоны делать.
Осталось только доработать, чтоб все лишнее вырезалось если условие совпадает.
Не задавай глупых вопросов, не услышишь вранья.
dervan
#38 2009-03-15 18:43
# Ratibor : Осталось только доработать, чтоб все лишнее вырезалось если условие совпадает.
А у medar'а для этого всё готово.
				$short_tpl_block = $ifs[2][$i];
...
				if(!$if_result)
				{
					// delete this IF block with all content
					$copy = str_replace($full_tpl_block, "", $copy);
				}
				else
				{
					// delete only IF construction
					// ? delete or not - speed ?
				}

Осталось выяснить, как сильно упадёт скорость работы парсера, если коментарий
					// ? delete or not - speed ?
заменить на код
					$copy = str_replace($full_tpl_block, $short_tpl_block, $copy);

Delete or not delete? :)
medar
#39 2009-03-16 04:31
Да, я на самом деле зря тут перестраховался, на скорости это серьезно не скажется, сделаю попозже удаление мусора.
rangjungyeshe.ru
Dayver
#40 2009-03-16 23:44
medar а как с логикой типа else? Не получилось реализовать? Или уже есть такое(если есть то моно примерчик?)?
Pavlo Tkachenko aka Dayver
dervan
#41 2009-03-23 02:50
Мы с Dayver'ом представляем результаты практического применения XTemplate с IF'ами - из опыта работы Dayver'а по выносу HTML из админки.

Предлагаем для тестирования доработанный XTemplate: xtemplate.class.php_57.zip

Просьба к medar'у - посмотреть внесённые изменения, может будут какие замечания. Существенных изменений не вносилось, все исправления - простые.


1.
Использование переменных bool приводило к ошибке.

Пример.
Переменная в коде PHP:
$is_test = false;
Условие в шаблоне:
<!-- IF !{PHP.is_test} -->not is_test<!-- ENDIF -->
В результате - ошибка:
Parse error: syntax error, unexpected ')' in mysite.com/system/xtemplate.class.php(781) : eval()'d code on line 1

Причина - в XTemplate не было поддержки bool, они не нужны в шаблонах. Это мы поправили, тут вроде обсуждать нечего - bool в условиях использоваться будут.


2.
Исходя из практики, кроме короткого варианта с IF нужен ещё и вариант с ELSE. Такой вариант добавлен, сейчас в шаблоне возможны такие условия:
<!-- IF <'if' statement> -->['then' content]<!-- ENDIF -->
<!-- IF <'if' statement> -->['then' content]<!-- ELSE -->['else' content]<!-- ENDIF -->

Реализация получилась простой - в коде medar'а исправлено 2 строки, и добавлена одна необязательная (в стиле уже сделанного им кода).

Немного усложнился regex, но в целом применение такой конструкции должно давать выигрыш во времени обработки.

Примеры из этого топика.

# medar :
<!-- IF strpos({PAGE_TITLE}, "жуй") -->
{PAGE_TITLE|str_replace('жуй', '', %s)} ц-ц-ц как нехорошо
<!-- ENDIF -->
<!-- IF !strpos({PAGE_TITLE}, "жуй") -->
{PAGE_TITLE}
<!-- ENDIF -->

# dervan :
<!-- IF {PHP.usr.id} < 1 -->
вы - гость
<!-- ENDIF -->
<!-- IF {PHP.usr.id} >= 1 -->
вы - зарегистрированный посетитель
<!-- ENDIF -->

В каждом из этих примеров парсится 2 условия IF, т.е. regex обрабатывается 2 раза. Кроме того, в 1-м примере в условиях IF дважды вызывается функцища strpos(), а во 2-м примере - дважды парсится тег {PHP.usr.id}. Если переписать эти примеры с ELSE, они будут работать быстрее, хотя regex для реализации ELSE чуть сложнее.

<!-- IF strpos({PAGE_TITLE}, "жуй") -->
{PAGE_TITLE|str_replace('жуй', '', %s)} ц-ц-ц как нехорошо
<!-- ELSE -->
{PAGE_TITLE}
<!-- ENDIF -->

<!-- IF {PHP.usr.id} < 1 -->
вы - гость
<!-- ELSE -->
вы - зарегистрированный посетитель
<!-- ENDIF -->

В шаблоне для админки, который переделал Dayver, подобных конструкций - подавляющее большинство, поэтому исходя из практики выгоднее использовать вариант с ELSE.

Предлагаем оставить в XTemplate вариант с поддержкой ELSE.


3.
Проблема из-за копирования глобальных переменных методом scan_globals(), в результате чего в шаблоне не видны глобальные переменные, присвоенные после создания объекта XTemplate. На практике это создаёт большие сложности.

Пример.
Эту переменную $lincif_conf можно использовать в шаблоне:
$lincif_conf = sed_auth('admin', 'a', 'A');
$t = new XTemplate(sed_skinfile('admin.inc', false, true));
А эту переменную $lincif_conf использовать в шаблоне невозможно:
$t = new XTemplate(sed_skinfile('admin.inc', false, true));
$lincif_conf = sed_auth('admin', 'a', 'A');

Для решения проблемы удалось легко реализовать то, о чём говорил medar:
# medar : Надо будет решить эту проблему по-другому - вообще отказаться от scan_globals(), а при парсинге тэгов {PHP.xxx} обращаться непосредственно к $GLOBALS.

Из метода scan_globals() убрано копирование $GLOBALS:
	public function scan_globals () {
		if ($this->force_globals && ini_get('auto_globals_jit') == true) {
			$tmp = $_SERVER;
			$tmp = $_ENV;
			$tmp = $_REQUEST;
			unset($tmp);
		}
	}

А в методе parse() присваивается указатель:
$this->vars['PHP'] =& $GLOBALS;
и уничтожается перед выходом из parse(). Т.е. $GLOBALS теперь не копируется, и в то же время нет опасности уничтожения $GLOBALS через указатель $this->vars['PHP'] - этот указатель теперь не существует вне метода parse().

Возникавшая из-за работы через указатель напрямую с $GLOBALS накладка, которая проявлялась в копировании в пустые строки умолчательных значений, определённых define(), в методе parse() была исправлена. Сообщение об этой накладке:
# dervan : К тому же есть нюансы при работе метода parse(). Например, такой код в конце system/header.php, плюс тег {PHP.TEST_DEFINE} в header.tpl:
define('TEST_DEFINE', 'test_define');
$TEST_DEFINE = '';

$t->parse("HEADER");
$t->out("HEADER");

echo $TEST_DEFINE, '<br />';
В случае оригинального scan_globals() глобальная переменная $TEST_DEFINE останется пустой строкой (значение будет присвоено её копии), а с переделанным scan_globals() после работы парсера $TEST_DEFINE получит значение 'test_define'.

Из метода get_vars_value() аналогичный код был удалён - пустую строку, которая пойдёт на проверку в IF, не надо подменять умолчательным значением.

Остальной код в parse() был внимательно изучен, других накладок из-за работы через указатель напрямую с $GLOBALS не обнаружено.

Предлагаем оставить в XTemplate этот вариант без копирования $GLOBALS.
Sergeich
#42 2009-03-23 03:37
Ну вы звери :). Вариант с <!-- ELSE --> мне понравился. Это значительно проще и понятнее для неподготовленного юзера (типа меня). Будем пробовать. :)
Dayver
#43 2009-03-23 03:47
А для полноты информации об изменениях и заявленом применении на практике привожу два админовских пхп файлах из которых венесен xhtml

его тплка

его тпл

Эти два файла так сказать наиболее показательны в плане применения логики в шаблонизаторе потому код остальных переделаных файлов приводить не буду. Посему просьба к медару потестить скорость так сказать переделаного шаблонизатора с реальным примером применения. Если не возникнет замечаний то и шаблонизатор и части переделаной админки пойдут в транк.[/][/][/]
Pavlo Tkachenko aka Dayver
esclkm
#44 2009-03-23 05:00
вау ребята! medar и dervan - вы потрясающие парни! молодцы! а что то я слышал по поводу оптимизации самого шаблонизатора - то как с этим обстоят дела?
littledev.ru - мой маленький зарождающийся блог о котонти.
снижение стоимости программирования и снижение стоимости производства разные вещи. Первое можно скорее сравнить с раздачей работникам дешевых инструментов, чем со снижением зарплаты
dervan
#45 2009-03-23 05:48
esclkm, больших изменений мы не делали - было улучшено то, что сделал medar. Это он говорил про оптимизацию, но будут ли это частичные изменения, или же предстоит серьёзный рефакторинг - сказать сложно, мы с Dayver'ом этот вопрос не рассматривали.

<<<1234>>>