要求parent :: __ construct()的最优雅方式

时间:2018-02-18 09:56:43

标签: php oop

说我有以下控制器结构:

class Controller {

    public function __construct(){
       $this->accessControl();
    }
}

class Account extends Controller {

   public function __construct(User $user){

      parent::__construct();
      $this->user = $user;
   }
}

如何要求其他开发人员在其子控制器中显式调用parent::__construct()?它包含访问控制等关键的东西

到目前为止,我决定将所有函数从父构造函数包装到init()方法中,该方法将initialized属性设置为TRUE,然后在路由器中检查此属性。如果它不是TRUE - 抛出异常。

public $initialized = false;

class Controller {

    public function __construct(){
       $this->init();
    }
}

protected function init(){
   $this->accessControl();
   $this->initialized = true;
}

class Router {
    public function process($path){
       $controller = new User();
       if(!$controller instanceof Controller || !$controller->initialized){
          throw new Exception('Error');
       }
    }
}

味道不好吗?

2 个答案:

答案 0 :(得分:2)

Symfony\Console命令需要相同,其中构造函数必须添加命令名称和定义

They handle it like this在添加命令的单个位置。所以你在路由器中检查控制器的方法是一样的。 我得到它,而不是把责任抽象到Controller或者反思。

另一方面,应该在安全层级上检查accessControl(),而不是在路由器中。

您使用什么框架?

您可以使用EventSubscriber和框架事件将其与路由器分离吗?

答案 1 :(得分:0)

是的,闻起来很糟糕。

  

如何要求其他开发人员显式调用parent :: __ construct()   他们的孩子控制员?

首先,您应该相信您的开发人员。另一个问题是如何确保所有控制器都具有访问控制。为了确保这一点,您必须通过测试覆盖所有控制器。因此,应该测试每个控制器,检查未经授权的用户是否可以访问它。

  

到目前为止,我决定将所有函数从父构造函数包装到   将init()属性设置为TRUE的initialized方法,然后选中此项   路由器中的属性。

实际上,您的init函数没有价值,因为您刚刚从__construct移动了代码(现在您必须确保开发人员调用init函数 - - 看,只改名称;))。您也可以在initialized本身设置__construct

if(!$controller instanceof Controller || !$controller->initialized){
    throw new Exception('Error');
}

因此,您最终会强制您的开发人员检查控制器是否已初始化,在每个地方都将使用它。

我猜你不能让代码万无一失。您必须信任开发人员做正确的事情并教育新的团队成员。当然,您应该使用测试覆盖所有代码,因为在实践中,这是确保开发人员做出正确事情的唯一方法。

有一个很好的播客,对你的问题是切实的:"Type Safety Roundtable with Ryan Tablada and Matt Machuga"