6

私のアプリケーションのルーティング部分には、クラス Route と Router があります。Route は、特定のマップされたルートに関する情報と、それらの情報を設定および取得するメソッドを保持するだけです。このように Closure を渡そうとしていますが、

Router::map('/', function(){}, array());

このように、2番目のパラメーター(クロージャー)を保存します

$route = new Route();
$route->setTarget($target);

※第2引数は$target変数

これを試すと

$target = $route->getTarget();
if($target instanceof Closure)
{
   echo 1;
}else
{
   echo 0;
}

それは0を出力しますが、試してみるとprint_r($target)

Closure Object ( ) 

クラスルート

class Route {

    /**
    * URL of this Route
    * @var string
    */
    private $url;

    /**
    * Accepted HTTP methods for this route
    * @var array
    */
    private $methods = array('GET','POST','PUT','DELETE');

    /**
    * Target for this route, can be anything.
    * @var mixed
    */
    private $target;

    /**
    * The name of this route, used for reversed routing
    * @var string
    */
    private $name;

    /**
    * Custom parameter filters for this route
    * @var array
    */
    private $filters = array();

    /**
    * Array containing parameters passed through request URL
    * @var array
    */
    private $params = array();

    public function getUrl() {
        return $this->url;
    }

    public function setUrl($url) {
        $url = (string) $url;

        // make sure that the URL is suffixed with a forward slash
        if(substr($url,-1) !== '/') $url .= '/';

        $this->url = $url;
    }

    public function getTarget() {
        return $this->target;
    }

    public function setTarget($target) {
        $this->target = $target;
    }

    public function getMethods() {
        return $this->methods;
    }

    public function setMethods(array $methods) {
        $this->methods = $methods;
    }

    public function getName() {
        return $this->name;
    }

    public function setName($name) {
        $this->name = (string) $name;
    }

    public function setFilters(array $filters) {
        $this->filters = $filters;
    }

    public function getRegex() {
        return preg_replace_callback("/:(\w+)/", array(&$this, 'substituteFilter'), $this->url);
    }

    private function substituteFilter($matches) {
        if (isset($matches[1]) && isset($this->filters[$matches[1]])) {
                return $this->filters[$matches[1]];
            }

            return "([\w-]+)";
    }

    public function getParameters() {
        return $this->parameters;
    }

    public function setParameters(array $parameters) {
        $this->parameters = $parameters;
    }




}

クラス ルーター

    class Router {

    /**
    * Array that holds all Route objects
    * @var array
    */ 
    private static $_routes = array();

    /**
     * Array to store named routes in, used for reverse routing.
     * @var array 
     */
    private static $_namedRoutes = array();

    /**
     * The base REQUEST_URI. Gets prepended to all route url's.
     * @var string
     */
    private static $_basePath = '';

    /**
     * Set the base url - gets prepended to all route url's.
     * @param string $base_url 
     */
    public function setBasePath($basePath) {
        static::$_basePath = (string) $basePath;
    }

    /**
    * Route factory method
    *
    * Maps the given URL to the given target.
    * @param string $routeUrl string
    * @param mixed $target The target of this route. Can be anything. You'll have to provide your own method to turn *      this into a filename, controller / action pair, etc..
    * @param array $args Array of optional arguments.
    */
    public static function map($routeUrl, $target, array $args = array()) {
        $route = new Route();

        $route->setUrl(static::$_basePath . $routeUrl);

        $route->setTarget($target);

        if(isset($args['methods'])) {
            $methods = explode(',', $args['methods']);
            $route->setMethods($methods);
        }

        if(isset($args['filters'])) {
            $route->setFilters($args['filters']);
        }

        if(isset($args['name'])) {
            $route->setName($args['name']);
            if (!isset(static::$_namedRoutes[$route->getName()])) {
                static::$_namedRoutes[$route->getName()] = $route;
            }
        }

        static::$_routes[] = $route;
    }

    /**
    * Matches the current request against mapped routes
    */
    public static function matchCurrentRequest() {
        $requestMethod = (isset($_POST['_method']) && ($_method = strtoupper($_POST['_method'])) && in_array($_method,array('PUT','DELETE'))) ? $_method : $_SERVER['REQUEST_METHOD'];
        $requestUrl = $_SERVER['REQUEST_URI'];

        // strip GET variables from URL
        if(($pos = strpos($requestUrl, '?')) !== false) {
            $requestUrl =  substr($requestUrl, 0, $pos);
        }

        return static::match($requestUrl, $requestMethod);
    }

    /**
    * Match given request url and request method and see if a route has been defined for it
    * If so, return route's target
    * If called multiple times
    */
    public static function match($requestUrl, $requestMethod = 'GET') {

        foreach(static::$_routes as $route) {

            // compare server request method with route's allowed http methods
            if(!in_array($requestMethod, $route->getMethods())) continue;

            // check if request url matches route regex. if not, return false.
            if (!preg_match("@^".$route->getRegex()."*$@i", $requestUrl, $matches)) continue;

            $params = array();

            if (preg_match_all("/:([\w-]+)/", $route->getUrl(), $argument_keys)) {

                // grab array with matches
                $argument_keys = $argument_keys[1];

                // loop trough parameter names, store matching value in $params array
                foreach ($argument_keys as $key => $name) {
                    if (isset($matches[$key + 1]))
                        $params[$name] = $matches[$key + 1];
                }

            }

            $route->setParameters($params);

            if($route)
            {
                static::respond($route);
            }
            return $route;



        }

        return false;
    }



    /**
     * Reverse route a named route
     * 
     * @param string $route_name The name of the route to reverse route.
     * @param array $params Optional array of parameters to use in URL
     * @return string The url to the route
     */
    public function generate($routeName, array $params = array()) {
        // Check if route exists
        if (!isset(static::$_namedRoutes[$routeName]))
            throw new Exception("No route with the name $routeName has been found.");

        $route = static::$_namedRoutes[$routeName];
        $url = $route->getUrl();

        // replace route url with given parameters
        if ($params && preg_match_all("/:(\w+)/", $url, $param_keys)) {

            // grab array with matches
            $param_keys = $param_keys[1];

            // loop trough parameter names, store matching value in $params array
            foreach ($param_keys as $i => $key) {
                if (isset($params[$key]))
                    $url = preg_replace("/:(\w+)/", $params[$key], $url, 1);
            }
        }

        return $url;
    }

    private static function respond($route)
    {
        $target = $route->getTarget();
        $path   = null;

        if($target instanceof Closure)
        {
            call_user_func($target);

        }else
        {
            if(is_string($target))
            {
                $target         = explode('@', $target);
                $target[0]      = explode(':', $target[0]);
                $controller     = $target[0][0];
                $method         = $target[0][1];
                $application    = $target[1];
                $path           = path('app') . $application . '/controllers/' . ucfirst($controller) . '.php'; 

            }

            if(is_array($target))
            {
                $controller     = $target['controller'];
                $method         = $target['method'];
                $application    = $target['application'];
                $path           = path('app') . $application . '/controllers/' . ucfirst($controller) . '.php'; 
            }


            if(file_exists($path))
            {
                $obj = require($path);
                $obj = new $controller();
                $obj->$method();
            }else
            {
                echo '404';
            }
        }
    }

}
4

1 に答える 1

22

コードで名前空間を使用していますか?

その場合、クロージャ クラス名を指定し\Closureて、グローバル ネーム スペースにエスケープする必要があります。

于 2013-06-25T18:41:43.500 に答える