1. как в мануале PHP: <title><?php echo $title; ?></title> 2. продвинуто PHP: <?php print "<title>{$title}</title>"; ?> 3. простые шаблоны (быстрая замена/подстановка) PHP: <?php $t = new Template('title'); $t->Set('title',$title); $t->Show(); ?> Код (Text): <title>{title}</title> 4. сложные шаблоны с логикой PHP: <?php $t = new Template('html'); $t->Set('title',$title); $t->Parse('title','headertitle'); $t->Show('html'); ?> Код (Text): <!-- begin html --> <html> {headertitle} <body>{body}</body> </html> <!-- end html --> <!-- begin title --> <title>{title}</title> <!-- end title -->
Smarty. А как же варианты PHP: <?=$content;?> и PHP: <?php $echo = <<<HEREDOC <div> {$content} </div> HEREDOC; echo $echo; ? Правда обоим не пользуюсь, но это уже получше чем <title><?php echo $title; ?></title> и <?php print "<title>{$title}</title>"; ?>
Хм, мой вариант такой: PHP PHP: <?php $parser->set('data', $array); $parser->set('content_center', $this->template('template.htm'); HTML Template PHP: <? if (is_set('data')){?> <table cellspacing="0" cellpadding="0"> <tr> <th>Header</th> <th>Header 2</th> </tr> <? foreach (get('data') as $value){?> <tr> <td><?=$value['name_1']?></td> <td><?=$value['name_2']?></td> </tr> <?}?> </table> <?}else{?> <div class="no-data">No data avaliable</div> <?}?> Минимум логики, голый PHP
Зависит от задачи. Если уже сделано на smarty - переделывать в простой вид не буду. Продолжу на smarty. Если написано "как в мануале" - переделывать на smarty не буду. Продолжу так. А вот "продвинутый" вид я вообще не понимаю - это типа "сами создаём себе трудности, чтобы их успешно пердолевать". Если есть время/желание - переделаю в "мануальный" вид. Если нет - просто не будут трогать. А дальше буду писать нормально, по "мануальному". Ну а если написано на ООП - с удовольствием продолжу на ООП. Мне пофик вид. Больших проектов с нуля я не писал. И в ближайшее время не предвидится. Так что - продолжаю писать так, как было до меня написано.
Поскольку большие проекты и с нуля, то… Каждый модуль генерит XML, который а) используется после XSL-преобразование в ответ XML-RPC сервиса; б) включается в общую структуру, которая потом через XSL-шаблоны превращается в конечный HTML, JS, CSS… PS: мелкие сайты делал на быстрых шаблонах.
PHP: <?php # код код код # Создаём список доступных модулей | ГРУЗИМ ШАБЛОН МЕНЮШКИ И ПРОГОНЯЕМ ЕГО В ЦИКЛЕ, А ПОТОМ ВСТАВЛЯЕМ В ШАПКУ $mods_dir = opendir(ROOT_PATH.'admin/modules'); while(false !== ($mod_name = readdir($mods_dir))) { if($mod_name != '.' and $mod_name != '..') { $mods_list[] = $mod_name; if($mod_name != 'error' and $mod_name != 'complete') { # Подгружаем файл локализации с названием модуля для главного меню require_once ROOT_PATH.'languages/'.LANGUAGE.'/admin/'.$mod_name.'/main_menu.php'; if($mod_name == $mod) $TPL_REPL['mod_name'] = $lang['main_menu']; $main_menu['lang_main_menu'] = $lang['main_menu']; $main_menu['url_main_menu'] = HTTP.DOMAIN.PATH.'admin/'.SCRIPT_FILENAME.'?m='.base64_encode($mod_name).SID; $tpl_main_menu_array[] = $TPL->parse('admin/main_menu', 1, $main_menu); } else { $TPL_REPL['mod_name'] = NULL; } } } closedir($mods_dir); # Собираем главную менюшку из модулей $TPL_REPL['main_menu'] = implode('', $tpl_main_menu_array); # Служебные ссылки - выход, переход на главную $TPL_REPL['url_go2index'] = HTTP.DOMAIN.PATH.'index.php?'.SID; # на главную $TPL_REPL['url_go2out'] = HTTP.DOMAIN.PATH.'admin/'.SCRIPT_FILENAME.'?m='.base64_encode('exit').SID; # выход # код код код # Шаблон верхней шапки | БЕЗ ЛОГИКИ - ПРОСТОЙ $TPL->parse('admin/header'); # код код код =) типа того upd. Все обработанные шаблоны накапливаются в специальной буфере шаблонизатора, а в конце вся страничка выводится так: PHP: <?php $TPL->show();
Быстрые шаблоны. Вся логика у меня - в обработчике шаблонов. Только с классами я пока не очень дружу, изаю preg_replace и str_replace Такие шаблоны очень легко править.
Hight А у меня специального буффера нету. Этот буффер сам по себе является самой обычной переменной, просто в него данные добавляются через append. Вообще юзаю простейший класик с несколькими методами: set, get, is_set, append и всё. Методы загрузки темплейта идут в самом ядре, т.к. им нужно знать что за класс вызывает подгрузку темплейта и на основании этого идёт соответствующий пусть А в index.php есть один простой вызов echo $core->load('sys_layout.htm'); [vs] С PHP вставками ничуть не труднее. У меня вообще шаблон требует только того, что-бы ему передали данные, которые ему надо вывести И то, обычно всегда стоит проверка на то, что они вообще есть. Довольно удобная структура и избавляет от кучи проверок
PHP: public function pageAction() { $this->setLayout('default.phtml'); $this->getLayout()->title = 'Страница'; //... $this->list = array(1, 2, 3); //... $this->setView('page.phtml'); } default.phtml Код (Text): <h1><?php print $title?></h1> <p> <?php print $this->getContents()?> </p> page.phtml Код (Text): <ul> <?php foreach ($list as $item):?> <li><?php print $item?></li> <?php endforeach?> </ul>
Psih На практике у меня примерно так: PHP: <? ... $template=file_get_contents('page.tpl'); $template=str_replace('{MENU}',$menu,$template); ...
хе =) PHP: <?php # Выборка в буфер private function get_tpl($template = NULL) { if($template == NULL) $this->_log('<b>Error. Class: Templates. Method: get_tpl(). Undefined argument "template".</b>'); if(!file_exists(ROOT_PATH.'templates/'.STYLE.'/'.$template.'.tpl')) $this->_log('<b>Error. Class: Templates. Method: get_tpl(). The file "'.$template.'.tpl" does not exist.</b>'); $this->buffer[$template] = @file_get_contents(ROOT_PATH.'templates/'.STYLE.'/'.$template.'.tpl') or $this->_log('<b>Error. Class: Templates. Method: get_tpl(). Can`t read the file "'.$template.'.tpl".</b>'); $this->get_tpl_counter += 1; # Накручиваем счётчик } в модуле делаю раз: PHP: <?php # Шаблон верхней шапки $TPL->parse('header'); и всё.
Никогда не понимал... объясните.. вы присваиваете переменной пустоту и тут же ее проверяете... и задаете условие есл она пустота, то ошибка...
Чего не понятно?! Если я случайно забыл передать в метод параметр мне об это сообщат. Метод _log() сделает die(); с выводом ошибки по умолчанию.
Так надо. Мой 'наворот' ещё и ошибки в файл пишет. И меня это радует. =) Смотри код метода _log(); PHP: <?php # Логирование private function _log($log_message = 'Class: Templates. Method: _log(). Default message.', $die = true) { if($this->allow_log) { if(!file_exists($this->log_file)) echo '<b>Class: Templates. Method: _log(). The file "'.$this->log_file.'" does not exist.</b> <br />'; if(!$handle = @fopen($this->log_file, 'a')) echo '<b>Class: Templates. Method: _log(). Can not open the file "'.$this->log_file.'".</b> <br />'; if(@fwrite($handle, "[".date("j m Y")."] [".date("H:i:s")."] [".$_SERVER["REMOTE_ADDR"]."] [".$_SERVER["SCRIPT_FILENAME"]."] [".str_replace("\r\n", NULL, $log_message)."] \r\n") === false) echo '<b>Class: Templates. Method: _log(). Can`t write in the file "'.$this->log_file.'".</b> <br />'; fclose($handle); } if($this->allow_show_log_messages) echo $log_message." <br /> \r\n"; if($die) die('<b>Class: Templates. The script is stopped.</b>'); } upd. А в какой-то теме говорили, что ООП не надо. Надо-надо. 8)
Hight, а стандартный PHP-лог чем не устраивает? Он ведь тоже в файл пишется. Зачем писать код, который уже встроен в PHP? Непонятно...
И, чтобы не быть голословным: В инклудах: PHP: <?php function make_template_address($component = "") { if ($component == "") { if (is_dir(SITE_ROOT_PATH.'templates/'.get_defalut_theme())) return SITE_ROOT_PATH.'templates/'.get_defalut_theme(); else die("Wrong component(templates path miss): ".$component); } else { if (is_dir(SITE_ROOT_PATH.'templates/'.get_defalut_theme().'/components/'.$component)) return SITE_ROOT_PATH.'templates/'.get_defalut_theme().'/components/'.$component; elseif (is_dir(SITE_ROOT_PATH.'components/'.$component.'/templates')) return SITE_ROOT_PATH.'components/'.$component.'/templates'; else die("Wrong component(templates path miss): ".$component); } } function make_smarty_template_address($component = "") { return make_template_address($component); } function &return_component_smarty_object($component_name, &$LANG = array()) { require_once SITE_ROOT_PATH."includes/core/smarty/Smarty.class.php"; $component_smarty = new Smarty; $component_smarty->template_dir = make_smarty_template_address($component_name).'/'; $component_smarty->compile_dir = make_smarty_template_address($component_name).'/compile/'; $component_smarty->config_dir = make_smarty_template_address($component_name).'/config/'; $component_smarty->cache_dir = make_smarty_template_address($component_name).'/cache/'; $component_smarty->compile_check = true; $component_smarty->caching = 0; $component_smarty->request_use_auto_globals = false; $component_smarty->error_reporting = E_ALL; $component_smarty->assign_by_ref('LANG', $LANG); global $base_url; $component_smarty->assign_by_ref('base_url', $base_url); return $component_smarty; } В компоненте: PHP: <?php $mod = explode("/", $_GET['mod']); $component_smarty =& return_component_smarty_object("news", $LANG); set_current_position(array(return_href('news') =>$LANG['MODULE_DESCRIPTION_BASE'])); //... // Main page // Try to get page number if (isset($mod[1])) $page = escape_page($mod[1]); else $page = 1; // Page Not Exists if ($page === null) { define('STATUS_CODE', 404); return; } $news_cache = new Cache_Lite(array('lifeTime' => 600)); if (!$news_categories =& $news_cache->get('news_categories')) { $result = mysql_query("SELECT id, title, description FROM news_categories"); $news_categories = array(); while ($row = mysql_fetch_assoc($result)) $news_categories[$row['id']] = array('title' => $row['title'], 'description' => $row['description']); $news_cache->save($news_categories, 'news_categories'); } $sql_query = "SELECT SQL_CALC_FOUND_ROWS id, category, author, title, annotation, date, views FROM news WHERE active='1' ORDER BY date DESC LIMIT ".floor(($page - 1) * NEWS_AT_HOME_PAGE).", ".NEWS_AT_HOME_PAGE; if (!$messages =& $news_cache->get($sql_query) || ($total =& $news_cache->get($sql_query.'total')) === false) { $result = mysql_query($sql_query); list($total) = mysql_fetch_row(mysql_query("SELECT FOUND_ROWS()")); $messages = array(); while ($row = mysql_fetch_assoc($result)) { $messages[] = array( 'ID' => $row['id'], 'TITLE' => $row['title'], 'ANNOTATION' => $row['annotation'], 'VIEWS' => ($row['views'] + 1), 'POSTER' => array('ID' => $row['author'], 'LOGIN' => ($row['author'] > 0)?get_user_profile_field('members_display_name', $row['author']):$row['author']), 'DATE' => $row['date'], 'CATEGORY' => array('ID' => $row['category'], 'TITLE' => $news_categories[$row['category']]['title'])); } $news_cache->save($messages, $sql_query); $news_cache->save($total, $sql_query.'total'); } if ($page > $total / NEWS_AT_HOME_PAGE) { define('STATUS_CODE', 404); return; } $component_smarty->assign_by_ref('messages', $messages); $total = ceil($total / NEWS_AT_HOME_PAGE); $page = min($page, $total); $component_smarty->assign_by_ref('end', $total); $component_smarty->assign_by_ref('current', $page); $component_smarty->display('main.tpl'); //... Код довольно старый, недавно была ревизия, так что и сам знаю что не самый оптимальный вариант