私のアプリケーションのルーティング部分には、クラス 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';
}
}
}
}