Поэтому я настраиваю систему с большим количеством писем и заменой переменных внутри нее, поэтому я пишу класс для управления заменой переменных для шаблонов, хранящихся в базе данных.
Вот краткий пример:
// template is stored in db, so that's how this would get loaded in $template = "Hello, %customer_name%, thank you for contacting %website_name%"; // The array of replacements is built manually and passed to the class // with actual values being called from db $replacements = array('%customer_name%'=>'Bob', '%website_name%'=>'Acme'); $rendered = str_replace(array_keys($replacements), $replacements, $template);
Теперь это хорошо работает и подходит для замены одного варна, основного материала. Тем не менее, есть места, где должен быть цикл for, и я теряюсь, как его реализовать.
Идея в том, что будет такой шаблон:
"привет,% customer_name%, спасибо за запрос информации о {products}"
Где {продукты} будет массивом, переданным шаблону, который зацикливается на запрошенные продукты, с таким форматом, как:
Наш продукт% product_name% имеет стоимость% product_price%. Подробнее читайте в% product_url%.
Таким образом, приведенная в качестве примера версия будет следующей:
«привет, Боб, спасибо за запрос информации о:
Наш продукт WidgetA стоит 1 доллар США. Подробнее см. В примере / A
Наш продукт WidgetB стоит 2 доллара. Подробнее см. В примере / B
Наш продукт WidgetC стоит 3 доллара. Подробнее см. В примере / C.
Каков наилучший способ сделать это?
Ну, я действительно не вижу смысла в движке шаблонов, который использует repalcements / regex
PHP Является уже механизмом шаблонов, когда вы пишете <?php echo $var?>
Как это делает <{$var}>
или {$var}
Подумайте об этом так, PHP уже переводит <?php echo '<b>hello</b>'?>
<b>hello</b>
своим движком, поэтому зачем делать все это в 2 раза.
То, как я буду использовать механизм шаблонов,
Сначала создайте класс шаблона
class Template { var $vars = array(); function __set($key,$val) { $this->vars[$key] = $val; } function __get($key) { return isset($this->vars[$key]) ? $this->vars[$key] : false; } function output($tpl = false) { if($tpl === false) { die('No template file selected in Template::output(...)'); } if(!file_exists(($dir = 'templates/' . $tpl . '.php'))) { die(sprintf('Tpl file does not exists (%s)',$dir)); } new TemplateLoader($dir,$this->vars); return true; } }
Это то, что вы используете в своем логине, таком как index.php, вы установите данные так же, как stdClass, просто скачайте его, если вы не уверены. и когда вы запускаете команду вывода, она отправляет данные и tpl в следующий класс ниже.
А затем создайте автономный класс для компиляции файла tpl внутри.
class TemplateLoader { private $vars = array(); private $_vars = array(); //hold vars set within the tpl file function __construct($file,$variables) { $this->vars = $variables; //Start the capture; ob_start(); include $file; $contents = ob_get_contents(); ob_end_clean(); //Clean it //Return here if you wish echo $contents; } function __get($key) { return isset($this->vars[$key]) ? $this->vars[$key] : (isset($this->_vars[$key]) ? $this->_vars[$key] : false) : false; } function __set($key,$val) { $this->_vars[$key] = $val; return true; } function bold($key) { return '<strong>' . $this->$key . '</string>'; } }
Причина, по которой мы сохраняем это отдельно, заключается в том, что у нее есть собственное пространство для запуска, вы просто загружаете свой файл tpl в качестве include в свой конструктор, чтобы его можно было загружать только один раз, а затем, когда файл включен, он имеет доступ ко всем данным и методы в TemplateLoader.
<?php require_once 'includes/Template.php'; require_once 'includes/TemplateLoader.php'; $Template = new Template(); $Template->foo = 'somestring'; $Template->bar = array('some' => 'array'); $Template->zed = new stdClass(); // Showing Objects $Template->output('index'); // loads templates/index.php ?>
Теперь мы не хотим смешивать html с этой страницей, потому что, разделяя php и view / templates, вы убедитесь, что все ваши php завершено, потому что когда вы отправляете html или используете html, он останавливает выполнение определенных аспектов вашего скрипта.
header <h1><?php $this->foo;?></h1> <ul> <?php foreach($this->bar as $this->_foo):?> <li><?php echo $this->_foo; ?></li> <?php endforeach; ?> </ul> <p>Testing Objects</p> <?php $this->sidebar = $this->foo->show_sidebar ? $this->foo->show_sidebar : false;?> <?php if($this->sidebar):?> Showing my sidebar. <?php endif;?> footer
Теперь мы видим, что они смешивали html с php, но это нормально, потому что в ehre вы должны использовать только базовые вещи, такие как Foreach, For и т. Д. И переменные.
ПРИМЕЧАНИЕ. В классе TemplateLoader вы можете добавить функцию типа ..
function bold($key) { return '<strong>' . $this->$key . '</string>'; }
Это позволит вам увеличить ваши действия в ваших шаблонах так жирно, курсивом, atuoloop, css_secure, stripslashs ..
У вас все еще есть обычные инструменты, такие как stripslashes / htmlentites и т. Д.
Вот небольшой пример смелости.
$this->bold('foo'); //Returns <strong>somestring</string>
Вы можете добавить много инструментов в класс TempalteLoader, например inc (), чтобы загрузить другие tpl-файлы, вы можете разработать вспомогательную систему, чтобы вы могли пойти $this->helpers->jquery->googleSource
Если у вас есть еще вопросы, не стесняйтесь спрашивать меня.
Пример сохранения в вашей базе данных.
<?php if(false != ($data = mysql_query('SELECT * FROM tpl_catch where item_name = \'index\' AND item_save_time > '.time() - 3600 .' LIMIT 1 ORDER BY item_save_time DESC'))) { if(myslq_num_rows($data) > 0) { $row = mysql_fetch_assc($data); die($row[0]['item_content']); }else { //Compile it with the sample code in first section (index.php) //Followed by inserting it into the database then print out the content. } } ?>
Если вы хотите сохранить ваши файлы tpl, включая PHP , это не проблема, в шаблоне, где вы передаете имя файла tpl, просто найдите db вместо файловой системы
$products = array('...'); function parse_products($matches) { global $products; $str = ''; foreach($products as $product) { $str .= str_replace('%product_name%', $product, $matches[1]); // $matches[1] is whatever is between {products} and {/products} } return $str; } $str = preg_replace_callback('#\{products}(.*)\{/products}#s', 'parse_products', $str);
Идея состоит в том, чтобы найти строку между {products} и {products}, передать ее какой-либо функции, делать все, что вам нужно с ней, итерировать массив $ products. Независимо от возвращаемой функции заменяет целые «{products} [все здесь] {/ products}».
Строка ввода будет выглядеть так:
Requested products: {products}%product_name%{/products}