Php 动态路由器和控制消息

Php 动态路由器和控制消息,php,events,exception,design-patterns,Php,Events,Exception,Design Patterns,我正在研究的系统使用动态路由器+dep.injection模式,具体来说: 路由器对象使用配置来实例化模块对象。模块是独立的,可能有很多 路由器对象的一个实例是注入模块构造函数的依赖项,并用作API引用/指针(可能与问题无关,但为了清楚起见,在这里) 模块使用API添加将输入模式链接到特定模块方法的规则 路由器接收输入,对照规则集检查输入,并调用匹配的模块方法 结果由路由器收集并传递到输出处理器 模块构造器: class module { public function __constr

我正在研究的系统使用动态路由器+dep.injection模式,具体来说:

  • 路由器对象使用配置来实例化模块对象。模块是独立的,可能有很多
  • 路由器对象的一个实例是注入模块构造函数的依赖项,并用作API引用/指针(可能与问题无关,但为了清楚起见,在这里)
  • 模块使用API添加将输入模式链接到特定模块方法的规则
  • 路由器接收输入,对照规则集检查输入,并调用匹配的模块方法
  • 结果由路由器收集并传递到输出处理器
  • 模块构造器:

    class module {
        public function __construct(&$router) {
            $router->addRoute('some-input-pattern', array($this, 'someMethod'));
        }
    
        public function someMethod() {
             return 'some arbitrary result';
        }
    }
    
    无论这看起来多么简单,在某些情况下,模块和路由器需要就与任意返回值无关的内容进行通信

    例如,有时模块必须触发事件或异常,而这些事件或异常必须由模块本身处理。它可以起源于任何模块方法,并且必须由特定的模块方法处理。(在每个方法中都有大量的try/catch块似乎并不正确,唯一可以处理任何异常的“入口点”在模块外部和路由器中。模块抛出,模块句柄,但只有路由器可以真正捕获。听起来不对。)

    在其他情况下,有些事件需要由路由器本身处理。例如,模块可以请求路由器继续运行,就好像它收到了一种特殊类型的输入,而忽略了真正的输入。然后,路由器必须根据规则集重新检查它,并调用适当的方法

       public function someMethod(){
             ...
             throw routerRestartException('special-input');
       }
    
    在其他情况下,事件可能不需要处理,只需要将其传递到输出,例如仅人眼错误

       public function someMethod(){
             ...
             throw humanEyesException("You can't do that!");
       }
    
    这有效地让我想到了两个通信方面,因为路由器和模块交换任意返回数据和特殊控制消息

    到目前为止,系统控制消息方面是通过模块抛出异常和路由器捕获来实现的。这需要模块注册两种类型的方法——一种用于处理输入,另一种用于处理异常,这可能很难闻

    有些异常似乎会影响流控制,我认为使用异常进行流控制也不是一种好的做法

    问题是,在路由器对象及其相关模块之间构建这种双向通信是否有最佳实践或模式

    编辑

    一个思路是:通过将模块内异常处理与路由器分离来改善这种情况的一种方法是对自定义异常使用观察者模式:

    public function __construct(&$router){
        ...
        dbTableNotFoundException::addObserver(array($this, 'installSchema'));
    }
    

    为了让模块对其他模块和API事件做出反应,我将使用Observer模式。您的API可以提供多个可观察主题(这些可以是API可以为每个可观察主题提供取消/注册和通知程序的类)

    public function __construct(&$router){
        ...
        dbTableNotFoundException::addObserver(array($this, 'installSchema'));
    }