【问题标题】:Dependency injection in base and derived classes基类和派生类中的依赖注入
【发布时间】:2012-03-08 14:49:45
【问题描述】:

我有一个抽象的基础控制器类,所有的动作控制器都派生自它。

构造时的基本 Controller 类初始化 View 对象。这个 View 对象被所有的动作控制器使用。每个动作控制器都有不同的依赖关系(这通过使用 DI 容器来解决)。

问题是Controller基类还需要一些依赖(或参数), 例如,查看文件夹的路径。问题是 - 在哪里以及如何将参数传递给基本 Controller 类?

$dic = new Dic();

// Register core objects: request, response, config, db, ...

class View
{
    // Getters and setters
    // Render method
}

abstract class Controller
{
    private $view;

    public function __construct()
    {
        $this->view = new View;

        // FIXME: How / from where to get view path?
        // $this->view->setPath();
    }

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

class Foo_Controller extends Controller
{
    private $db;

    public function __construct(Db $db)
    {
        $this->db = $db;
    }

    public function barAction()
    {
        $this->getView()->some_var = 'test';
    }
}

require_once 'controllers/Foo_Controller.php';

// Creates object with dependencies which are required in __construct()
$ctrl = $dic->create('Foo_Controller');

$ctrl->barAction();

【问题讨论】:

  • 私人 $view;为什么 $view 是私有的?你什么时候知道要加载哪个视图路径?在动作控制器内部?那么这很容易做到。

标签: php dependency-injection base-class


【解决方案1】:

这只是一个基本示例。为什么 $view 是私有的?有充分的理由吗?

class View {
  protected $path;
  protected $data = array();

  function setPath($path = 'standard path') {
    $this->path = $path;
  }

  function __set($key, $value) {
    $this->data[$key] = $value;
  }

  function __get($key) {
    if(array_key_exists($key, $this->data)) {
      return $this->data[$key];
    }
  }
}

abstract class Controller {
    private $view;

    public function __construct($path)
    {
       $this->view = new View;

       $this->view->setPath($path);
    }

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

class Foo_Controller extends Controller {
    private $db;


    public function __construct(Db $db, $path)
    {
        // call the parent constructor.
        parent::__construct($path);
        $this->db = $db;
    }

    public function barAction()
    {
        $this->getView()->some_var = 'test';
    }

    public function getAction() {
      return $this->getView()->some_var;
    }
}

class DB {

}

$con = new DB;
$ctrl = new Foo_Controller($con, 'main');

$ctrl->barAction();
print $ctrl->getAction();

【讨论】:

  • 感谢您的快速答复! View 是私有的,因此不能从外部覆盖,只能通过 getView() 方法访问。抱歉,我忘了提到引导文件中只有一个视图路径(例如“views/”)定义为常量。从动作控制器的构造函数传递视图路径感觉是正确的。但是,如果路径没有改变,是否有其他解决方案(有利于 DI),因此每个动作控制器不需要调用父构造函数并重新传递相同的视图路径?
  • 最好的方法是在父抽象控制器中定义一个默认路径。私人 $view ->path = "somepath";
  • @Hemaulo 您正在覆盖动作控制器内的构造函数,请记住这一点。不调用parent::__controller,视图怎么调用?
  • 基本控制器类是框架的一部分,视图路径由应用程序定义。您的解决方案是最简单的方法,但视图路径将被硬编码和相对。绝对路径是首选,但每个应用程序位于不同的文件夹中。
  • 只有子类定义了自己的__construct()方法时才需要调用父构造函数。可以有没有依赖关系的控制器,因此没有构造函数,在这种情况下 parent::__construct() 将被自动调用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-20
  • 1970-01-01
  • 2014-11-04
  • 1970-01-01
  • 1970-01-01
  • 2020-03-17
  • 1970-01-01
相关资源
最近更新 更多