Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php和decorator模式中的路由_Php_Design Patterns_Url Routing_Decorator - Fatal编程技术网

Php和decorator模式中的路由

Php和decorator模式中的路由,php,design-patterns,url-routing,decorator,Php,Design Patterns,Url Routing,Decorator,我不知道我是否正确使用了术语“路由”,但情况如下: 我创建了一个.htaccess文件来“处理”(如果我的术语正确,则不知道)我的应用程序的url,如下所示: RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.+)$ index.php?url=$1 [QSA,L] 现在我有这个: http://appname/controller/

我不知道我是否正确使用了术语“路由”,但情况如下:

我创建了一个
.htaccess
文件来“处理”(如果我的术语正确,则不知道)我的应用程序的url,如下所示:

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f

RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
现在我有这个:

http://appname/controller/method/parameter
http://appname/$url[0]/$url[1]/$url[2]
我所做的是:

  • 如果url中未指定默认控制器,请设置默认控制器
  • 设置控制器包装器
  • 我是这样做的

    $target = new $url[0]()
    $controller = new Controller($target)
    
    该方法的问题是,我无法使用在控制器构造函数中传递的对象中的方法:

    我是这样决定的:

    class Controller {
      protected $target;
      protected $view;
    
      public function __construct($target, $view) {
        $this->target = $target;
        $this->view = $view;
      }
    
      public function __call($method, $arguments) {
        if (method_exists($this->target, $method)) {
            return call_user_func_array(array($this->target, $method), $arguments);
        }
      }
    }
    
    这很好,问题出现在我做路由的索引中,在这里

    if(isset($url[2])){
        if(method_exists($controller, $url[1])){
             $controller->$url[1]($url[2])
        }
    } else {
        if(method_exists($controller, $url[1])){
             $controller->$url[1]()
        }
    }
    
    其中
    $controller=新控制器($target)


    问题是该方法不存在,尽管我可以直接使用它而不检查方法是否存在,但我如何解决这个问题?

    正如您已经发现的,当它被一个神奇的
    \u调用
    方法处理时,您无法使用
    方法\u存在。但是,您可以向控制器添加一个额外的公共方法来解决此问题:

    class Controller {
      protected $target;
      protected $view;
    
      public function __construct($target, $view) {
        $this->target = $target;
        $this->view = $view;
      }
    
      public function hasMethod($method) {
        return is_callable(array($this->target, $method));
      }
    
      public function __call($method, $arguments) {
        if (!is_callable(array($this->target, $method))) {
            throw new \BadMethodCallException("Method `$method` is not callable");
        }
    
        return call_user_func_array(array($this->target, $method), $arguments);
      }
    }
    
    所以


    编辑:将
    method\u exists
    更改为
    可调用
    ,以确保只有公共方法返回true。

    正如您已经发现的,当它被magic
    \u调用
    方法处理时,您无法使用
    method\u exists
    。但是,您可以向控制器添加一个额外的公共方法来解决此问题:

    class Controller {
      protected $target;
      protected $view;
    
      public function __construct($target, $view) {
        $this->target = $target;
        $this->view = $view;
      }
    
      public function hasMethod($method) {
        return is_callable(array($this->target, $method));
      }
    
      public function __call($method, $arguments) {
        if (!is_callable(array($this->target, $method))) {
            throw new \BadMethodCallException("Method `$method` is not callable");
        }
    
        return call_user_func_array(array($this->target, $method), $arguments);
      }
    }
    
    所以


    编辑:将
    method\u exists
    更改为
    is\u callable
    ,以确保只有公共方法返回true。

    使用
    is\u callable()
    而不是
    method\u exists()
    将返回正确的结果。

    使用
    is\u callable()
    而不是
    method\u exists()
    ,它将返回正确的结果。

    简短回答:您做错了。现在再长一点

    这里的主要问题是您试图将路由机制固定在控制器中。现代MVC模式中的控制器负责从用户输入中获取信息,并将其应用于模型层和/或当前视图以更改其状态

    它应该而不是负责从原始输入数据中提取信息。这应该通过某种形式的路由机制来完成,在代码实际命中MVC三元组之前使用这种机制。最好是在应用程序的引导/启动阶段

    基本上你会做一些类似的事情:

    $uri = isset( $_GET['url'] ) ? $_GET['url'] : '/';
    $request = new Request;
    $request->setUrl( $url );
    
    $router = new Router;
    $router->route( $request );
    
    $class = $request->getParameter('controller');
    $method = $request->getParameter('action');
    
    if ( !class_exists( $class ))
    {
        $class  = 'ErrorController';
        $method = 'missingController';
    }
    
    if ( !is_callable( [$class, $method] ))
    {
        $class  = 'ErrorController';
        $method = 'missingAction';
    }
    
    $controller = new $class( /* inject some dependencies */ );
    $controller->{$method}( $request );
    
    这当然是一个简化且有些笨拙的例子请勿复制生产代码中的粘贴。


    简短回答:你做错了。现在再长一点

    这里的主要问题是您试图将路由机制固定在控制器中。现代MVC模式中的控制器负责从用户输入中获取信息,并将其应用于模型层和/或当前视图以更改其状态

    它应该而不是负责从原始输入数据中提取信息。这应该通过某种形式的路由机制来完成,在代码实际命中MVC三元组之前使用这种机制。最好是在应用程序的引导/启动阶段

    基本上你会做一些类似的事情:

    $uri = isset( $_GET['url'] ) ? $_GET['url'] : '/';
    $request = new Request;
    $request->setUrl( $url );
    
    $router = new Router;
    $router->route( $request );
    
    $class = $request->getParameter('controller');
    $method = $request->getParameter('action');
    
    if ( !class_exists( $class ))
    {
        $class  = 'ErrorController';
        $method = 'missingController';
    }
    
    if ( !is_callable( [$class, $method] ))
    {
        $class  = 'ErrorController';
        $method = 'missingAction';
    }
    
    $controller = new $class( /* inject some dependencies */ );
    $controller->{$method}( $request );
    
    这当然是一个简化且有些笨拙的例子请勿复制生产代码中的粘贴。


    这是误导性的-当在decorator上调用is_callable时,由于magic
    \u调用
    回退,它将始终返回true。它没有考虑这次通话的结果。在这种情况下,获得所需结果的唯一方法是询问装饰器的对象是否具有该方法。虽然在这个方法中使用
    is\u callable
    可能更好,尽管as
    方法存在,但是对于不可调用的受保护/私有方法,它将返回true。这是误导性的-is\u callable在装饰器上调用时总是返回true,因为有神奇的
    \u call
    回退。它没有考虑这次通话的结果。在这种情况下,获得所需结果的唯一方法是询问装饰器的对象是否具有该方法。虽然在该方法中使用
    是可调用的
    可能更好,但对于不可调用的受保护/私有方法,
    将返回true。请停止将路由机制强制进入控制器。你违反了,我把它换了。。我昨天意识到了:谢谢!!!请停止将路由机制强制进入控制器。你违反了,我把它换了。。我昨天意识到了:谢谢!!!我想知道
    $router->route($request)是什么意思你做了什么?它是否处理了
    $request
    ,然后将其返回变量?
    route()
    方法“准备”了
    请求
    实例。在实际的实现中,我将在
    路由器
    实例中导入可能的路由,并将其转换为正则表达式。在这种情况下,
    route()
    方法将遍历所有表达式,直到找到第一个匹配项。在这种情况下,从该regexp中提取的数据被分配给
    请求
    实例。基本上,
    route()
    方法准备了
    请求
    。我想在
    Request
    类中会有
    setUri
    函数和
    getParameter
    函数,而
    Router
    类准备了请求,大概它设置了相应的控制器和操作,。。因此,在
    请求
    调用
    获取参数
    之前,
    控制器和
    操作
    已经设置好了,所以我想象在
    路由器
    类中,它设置了一个
    请求
    数组,例如
    设置->请求('controller',$this->controller)
    ,就像这样吗?事实是,
    控制器