1

我只是非常缓慢地开始沉迷于面向对象的编程,所以请对我温柔一点。

我有一个部分借用的 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');

我制作了以下代码示例(见下文)普遍适用,因此我不会在每个 PHP 文件中一直重复上述行(见前 3 行)。

我只想设置,例如:

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.


我已经尝试过运行良好的解决方案,但我不喜欢它的外观(它的结构方式)。

我所做的是:

  1. 在 config 中分配一个 var 并调用它$current_page_name(即派生当前 PHP 页面名称,如下所示:)basename($_SERVER['PHP_SELF'], ".php");,它返回,例如:category
  2. 在我使用的 PHP 文件中Template::defaults($current_page_name);
  3. 在我的自定义 Smarty 类中,我添加了以下内容:


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');
}

有没有办法让它更简洁和结构良好?我知道代码审查,但我希望你们好好看看它。

4

4 回答 4

2

看起来你还没有加载 Smarty,这就是错误发生的原因。您需要在课程开始前加入 Smarty。如果您遵循我的其他配置建议,您也应该从包含该配置开始。

在您的模板类中,只需添加以下函数:

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();

编辑:

单例在任何意义上都与全局相同,这将使您遇到相同的问题。但是您的问题是,如果您尝试使用模板的静态函数之一,则您处于“静态”模式,这意味着尚未运行构造函数。并且Smarty没有被分配。如果你想走这条路,你可以做以下两种想法之一:

  1. 使模板成为真正的单例,这意味着将构造函数设置为private添加一个函数 getInstance,它返回一个类的实例,然后使用该对象调用其中的函数(不应该是静态的),或者

  2. 让所有这些静态函数检查是否设置了 smarty,如果没有设置,则创建一个新的 smarty 实例,否则使用已经实例化的实例来运行其函数。

编辑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();

我注释掉了你可能想要做的事情,以使它成为一个围绕单例 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);

现在就试试。

于 2012-09-16T15:13:58.160 回答
0

You can get current file name in your defaults() function. Use this piece of code:

$currentFile = $_SERVER['REQUEST_URI'];
$parts = explode('/', $currentFile);
$fileName = array_pop($parts);
$viewName = str_replace('.php', '.tpl', $fileName);

$viewName is the name that you need.

于 2012-09-15T09:50:51.097 回答
0

这是我为 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 的基本方法。在更完整的版本中,您可能需要检查编译目录是否可写,或者文件模板是否存在等。

于 2012-09-17T00:05:38.990 回答
0

在尝试了几天来解决这个简单的问题后,我终于想出了可行且完全令人满意的解决方案。请记住,我只是面向对象编程的新手,这就是花了这么长时间的主要原因。

我的主要想法是不要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 代码。

于 2012-09-17T07:44:19.450 回答