扩展PHP Smarty Singleton类

时间:2011-06-25 21:13:09

标签: php class smarty extend

我不确定如何提出这个问题。基本上我试图让我的视图对象从Smarty对象扩展出来。然后,我希望能够将视图对象扩展到我的控制器对象。

View对象会将我想要的模板变量分配给我的所有控制器。

我知道我现在有什么问题,但如果有人能指出我正确的方向,那就太棒了。我试着尽力说出来。

<?php

defined('SITE_ROOT') ? null : define('SITE_ROOT', $_SERVER['DOCUMENT_ROOT'].'/mvcsandbox');

require_once('Smarty/Smarty.class.php');

class View extends Smarty {

    public static $instance=NULL;

    public static function getInstance(){

        if ( self::$instance === null ){
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function __construct() {

        $this->template_dir = SITE_ROOT.'/Library/tmp/';
        $this->compile_dir  = SITE_ROOT.'/Library/tmp/';
        $this->config_dir   = SITE_ROOT.'/Library/tmp/';
        $this->cache_dir    = SITE_ROOT.'/Library/tmp/';

        $this->assign("var1", "This is from the view class");

    }

    public static function output() {

        self::display('test.tpl');

    }

}

class Controller1 extends View {

    public function init() {
        $this->assign("var2", "This is from the Controller1 class");
    }

}

class Controller1_index extends Controller1 {

    public function init() {
        $this->assign("var3", "This is from the Controller1_index class");
    }

}

//$view = View::getInstance();
$controller1 = Controller1::getInstance();
$controller1_index = Controller1_index::getInstance();

$controller1->init();
//$controller1_index->init();

$controller1->output();

&GT;

1 个答案:

答案 0 :(得分:5)

你的控制器不应该扩展iew ..它应该为视图提供数据。您也可能不希望有多个控制器用于不同的事情,并且在任何时候您可能需要从另一个控制器请求逻辑到这些控制器中的任何一个,因此使基本控制器成为单例并不是一个好主意。而是使用作为单例的前端控制器,然后使用实际处理模块特定控制器逻辑的动作控制器。

class Controller {
   // put any shared logic between all controllers here

}

class FrontController extends Controller {

  protected $request; // a model representing and http request
  protected $response; // a model representing a http response
  protected $view; // the view instance
  protected static $instance; // the FrontController instance

  protected function __construct();

  public static function getInstance();

  public function getRequest();

  public function getResponse();

  public function getView();

  public function execute($args);


}

class View {
  protecect $engine;

  public function __Construct($options)
  {
     // $options could contain overrides for smarty config
     $options = array_merge(array(
        'template_dir' = SITE_ROOT.'/Library/tmp/',
        'compile_dir'  = SITE_ROOT.'/Library/tmp/',
        'config_dir'   = SITE_ROOT.'/Library/tmp/',
        'cache_dir'    = SITE_ROOT.'/Library/tmp/',
     ), $options);

    $this->engine = new Smarty();

    foreach($options as $name => $value){
      $this->engine->$name = $value;
    }
  }

  public function getEngine(){
      return $this->engine;
  }

  // proxy method calls and accessors not directly defined on 
  // the View to the Smarty instance

  public function __get($key)
  {
    return $this->engine->$key;
  }

  public function __set($key, $value){
    $this->engine->$key = $value;
    return $this;
  }

  public function __call($method, $args){
     if(is_callable(array($this->engine, $method)){
       return call_user_func_array(array($this->engine, $method));
     }
  }

  public function render(){
    // render the entire smarty instance
  }

}

class ActionController extends Controller
{
   protected $view;

   public function init();

   public function setRequest();

   public function getRequest();

   public function getResponse();

   public function execute($request, $response);

   public function getView();

   public function __get($key){
     return $this->view->$key;
   }

   public function __set($key, $value){
     $this->view->$key = $value;
   }
}

因此,您的index.php将调用FrontController::getInstance()->execute();注入请求生命周期的任何选项,它需要通过选项注入execute。构造函数将预先配置视图,请求和响应实例。 Execute将确定要加载和运行的ActionController。它将加载该操作控制器并设置视图,然后确定该操作控制器中的哪个操作需要运行并执行它。

执行操作控制器后,您的前端控制器将调用View::render(),它将返回完整的html字符串以输出到浏览器并将其设置为响应对象上的内容以及使用该响应的方法用于设置标题和cookie等内容的对象。然后,前端控制器会在响应对象上调用类似sendResponse的内容,然后将标头和内容发送到浏览器。