Я просто очень медленно начинаю погружаться в объектно-ориентированное программирование, поэтому, пожалуйста, будьте осторожны.
У меня есть специальный класс для Smarty, который был частично заимствован. Вот как единственный пример отражает основную идею его использования в моем текущем проекте:
class Template { function Template() { global $Smarty; if (!isset($Smarty)) { $Smarty = new Smarty; } } public static function display($filename) { global $Smarty; if (!isset($Smarty)) { Template::create(); } $Smarty->display($filename); }
Затем в PHP я использую следующее для отображения шаблонов на основе приведенного выше примера:
Template::display('head.tpl'); Template::display('category.tpl'); Template::display('footer.tpl');
Я сделал следующий пример кода (см. Ниже) для работы повсеместно, поэтому я не буду повторять вышеприведенные строки (см. 3 предыдущих строки) все время в каждом файле PHP.
Я бы просто хотел установить, например:
Template::defauls();
который будет загружать:
Template::display('head.tpl'); Template::display('template_name_that_would_correspond_with_php_file_name.tpl'); Template::display('footer.tpl');
Как видите, Template::display('category.tpl');
всегда будет меняться в зависимости от файла PHP, имя которого соответствует имени шаблона, то есть, если, например, файл PHP называется stackoverflow.php
то шаблоном для него будет stackoverflow.tpl
.
Я пробовал свое решение, которое отлично работало, но мне не нравится, как он выглядит (как он структурирован).
Я сделал это:
$current_page_name
(которое выводит текущее имя страницы PHP, например: basename($_SERVER['PHP_SELF'], ".php");
), который возвращался, например: category
. Template::defaults($current_page_name);
public static function defaults($template) { global $Smarty; global $msg; global $note; global $attention; global $err; if (!isset($Smarty)) { Templates::create(); } Templates::assign('msg', $msg); Templates::assign('note', $note); Templates::assign('attention', $attention); Templates::assign('err', $err); Templates::display('head.tpl'); Templates::display($template . '.tpl'); Templates::display('footer.tpl'); }
Есть ли способ сделать его более кратким и хорошо структурированным? Я знаю о Code Review, но я бы хотел, чтобы вы, ребята, неплохо посмотрели на него.
Похоже, вы не загрузили Smarty, поэтому ошибка происходит. Вам нужно начать с включения Smarty до запуска класса. Если вы следуете моему другому варианту конфигурации, вы должны начать с включения этого.
В классе Template просто добавьте следующую функцию:
function defaults() { // Don't know if you need the assignes, havn't used Smarty, but if so, insert them here... Template::display( Config::get('header_template') ); //header_template set in the Config file Template::display( basename($_SERVER['PHP_SELF'], ".php") . '.tpl' ); Template::display( Config::get('footer_template') ); //footer_template set in the Config file }
Теперь вы сможете использовать его в любом файле:
$template = new Template(); $template->defaults();
РЕДАКТИРОВАТЬ:
Синглтон во всех смыслах такой же, как и глобальный, который будет поддерживать вашу проблему. Но ваша проблема заключается в том, что если вы попытаетесь использовать одну из статических функций Template, вы находитесь в «статическом» режиме, что означает, что конструктор не был запущен. И Smarty не был назначен. Если вы хотите пойти по этой дороге, вы можете сделать один из двух:
Сделайте шаблон реальным синглэном, что означает, что конструктор закрывается, добавляет функцию getInstance, которая возвращает экземпляр класса, а затем использует этот объект для вызова функций в нем (который не должен быть статическим) или
Сделайте все эти статические функции, если установлено smarty, и если это не так, создайте новый экземпляр smarty, иначе используйте тот, который уже создан для запуска его функции.
EDIT 2:
Вот правильный способ сделать синглтон:
class Singleton { private static $instance = null; // private static $smarty = null; private function __construct() { //self::$smarty = new Smarty(); } public static function getInstance() { if( self::$instance === null ) { self::$instance = self(); } return self::$instance; } public function doSomething() { //self::$smarty->doSomething(); } }
Он используется следующим образом:
$singleton = Singletong::getInstance(); $singleton->doSomething();
Я прокомментировал то, что вы, вероятно, захотите сделать, чтобы сделать эту оболочку singleton вокруг объекта Smarty. Надеюсь это поможет.
ИЗМЕНИТЬ 3:
Вот рабочая копия вашего кода:
class Template { private static $smarty_instance; private static $template_instance; private function Template() { self::$smarty_instance = new Smarty(); $this->create(); } public static function getInstance() { if( ! isset( self::$template_instance ) ) { self::$template_instance = new self(); } return self::$template_instance; } private function create() { self::$smarty_instance->compile_check = true; self::$smarty_instance->debugging = false; self::$smarty_instance->compile_dir = "/home/docs/public_html/domain.org/tmp/tpls"; self::$smarty_instance->template_dir = "/home/docs/public_html/domain.org"; return true; } public function setType($type) { self::$smarty_instance->type = $type; } public function assign($var, $value) { self::$smarty_instance->assign($var, $value); } public function display($filename) { self::$smarty_instance->display($filename); } public function fetch($filename) { return self::$smarty_instance->fetch($filename); } public function defaults($filename) { global $user_message; global $user_notification; global $user_attention; global $user_error; self::$smarty_instance->assign('user_message', $user_message); self::$smarty_instance->assign('user_notification', $user_notification); self::$smarty_instance->assign('user_attention', $user_attention); self::$smarty_instance->assign('user_error', $user_error); self::$smarty_instance->assign('current_page', $filename); self::$smarty_instance->display('head.tpl'); self::$smarty_instance->display($filename . '.tpl'); self::$smarty_instance->display('footer.tpl'); } }
При использовании этой функции вы должны использовать ее следующим образом:
$template = Template::getInstance(); $template->defaults($filename);
Попробуй это сейчас.
Вы можете получить текущее имя файла в своей функции по defaults()
. Используйте этот фрагмент кода:
$currentFile = $_SERVER['REQUEST_URI']; $parts = explode('/', $currentFile); $fileName = array_pop($parts); $viewName = str_replace('.php', '.tpl', $fileName);
$viewName
– это то имя, которое вам нужно.
Это быстрая обертка, которую я сделал для Smarty, надеюсь, что это даст вам некоторые идеи
class Template extends Smarty { public $template = null; public $cache = null; public $compile = null; public function var($name, $value, $cache) { $this->assign($name, $value, $cache); } public function render($file, $extends = false) { $this->prep(); $pre = null; $post = null; if ($extends) { $pre = 'extends:'; $post = '|header.tpl|footer.tpl'; } if ($this->prep()) { return $this->display($pre . $file . $post); } } public function prep() { if (!is_null($this->template)) { $this->setTemplateDir($this->template); return true; } if (!is_null($this->cache)) { $this->setCacheDir($this->cache); } if (!is_null($this->compile)) { $this->setCompileDir($this->compile); return true; } return false; } } Then you can use it like this $view = new Template(); $view->template = 'path/to/template/'; $view->compile = 'path/to/compile/' $view->cache = 'path/to/cache'; $view->assign('hello', 'world'); // or $view->var('hello', 'world'); $view->render('index.tpl'); //or $view->render('index.tpl', true); // for extends functionality
Я сделал это быстро, но просто чтобы показать вам основные способы использования smarty. В более полной версии вы, вероятно, захотите проверить, разрешен ли файл компиляции, или существуют ли шаблоны файлов и т. Д.
Попробовав в течение нескольких дней решить эту простую проблему, я, наконец, придумал рабочее и полностью удовлетворяющее решение. Помните, что я просто новичок в объектно-ориентированном программировании, и это главная причина, почему так долго.
Моя основная идея заключалась в том, чтобы не использовать global $Smarty
в моем исходном коде, который работал уже отлично. Мне нравится использовать мой Smarty как простой, как ввод, например: Template::assign('array', $array)
. Чтобы отображать значения по умолчанию, я придумал тривиальное решение (прочитал мой начальный пост), где теперь его можно использовать только Template::defaults(p());
отображать или присваивать все, что повторяется на каждой странице вашего проекта.
Для этого я лично остановился на следующем полностью работоспособном решении:
function p() { return basename($_SERVER['PHP_SELF'], ".php"); } require('/smarty/Smarty.class.php'); class Template { private static $smarty; static function Smarty() { if (!isset(self::$smarty)) { self::$smarty = new Smarty(); self::Smarty()->compile_check = true; self::Smarty()->debugging = false; self::Smarty()->plugins_dir = array( '/home/docs/public_html/domain.com/smarty/plugins', '/home/docs/public_html/domain.com/extensions/smarty'); self::Smarty()->compile_dir = "/home/docs/public_html/domain.com/cache"; self::Smarty()->template_dir = "/home/docs/public_html/domain.org"; } return self::$smarty; } public static function setType($type) { self::Smarty()->type = $type; } public static function assign($var, $value) { self::Smarty()->assign($var, $value); } public static function display($filename) { self::Smarty()->display($filename); } public static function fetch($filename) { self::Smarty()->fetch($filename); } public static function defaults($filename) { Template::assign('current_page_name', $filename); Template::display('head.tpl'); Template::display($filename . '.tpl'); Template::display('footer.tpl'); } }
Пожалуйста, используйте его, если вам это нравится в ваших проектах, но оставляйте комментарии в этом сообщении, если вы думаете, что я мог бы его улучшить, или у вас есть какие-либо предложения.
Первоначальная идея сделать все это – обучение и осуществление написания кода PHP в объектно-ориентированном стиле.