Permalink
Browse files

Working on controller inspector.

  • Loading branch information...
taylorotwell committed Oct 19, 2013
1 parent 07f400a commit 98c14a9f90ada608418490e4cfacd51f4ebda384
Showing with 222 additions and 0 deletions.
  1. +137 −0 src/Illuminate/Routing/ControllerInspector.php
  2. +85 −0 src/Illuminate/Routing/Router.php
@@ -0,0 +1,137 @@
<?php namespace Illuminate\Routing;
use ReflectionClass, ReflectionMethod;
class ControllerInspector {
/**
* An array of HTTP verbs.
*
* @var array
*/
protected $verbs = array(
'any', 'get', 'post', 'put',
'delete', 'head', 'options'
);
/**
* Get the routable methods for a controller.
*
* @param string $controller
* @param string $prefix
* @return array
*/
public function getRoutable($controller, $prefix)
{
$routable = array();
$reflection = new ReflectionClass($controller);
// To get the routable methods, we will simply spin through all methods on the
// controller instance checking to see if it belongs to the given class and
// is a publicly routable method. If so, we will add it to this listings.
foreach ($reflection->getMethods() as $method)
{
if ($this->isRoutable($method, $reflection->name))
{
$data = $this->getMethodData($method, $prefix);
// If the routable method is an index method, we will create a special index
// route which is simply the prefix and the verb and does not contain any
// the wildcard place-holders that each "typical" routes would contain.
if ($data['plain'] == $prefix.'/index')
{
$routable[$method->name][] = $data;
$routable[$method->name][] = $this->getIndexData($data, $prefix);
}
// If the routable method is not a special index method, we will just add in
// the data to the returned results straight away. We do not need to make
// any special routes for this scenario but only just add these routes.
else
{
$routable[$method->name][] = $data;
}
}
}
return $routable;
}
/**
* Determine if the given controller method is routable.
*
* @param ReflectionMethod $method
* @param string $controller
* @return bool
*/
public function isRoutable(ReflectionMethod $method, $controller)
{
if ($method->class == 'Illuminate\Routing\Controller') return false;
return $method->isPublic() and starts_with($method->name, $this->verbs);
}
/**
* Get the method data for a given method.
*
* @param ReflectionMethod $method
* @return array
*/
public function getMethodData(ReflectionMethod $method, $prefix)
{
$verb = $this->getVerb($name = $method->name);
$uri = $this->addUriWildcards($plain = $this->getPlainUri($name, $prefix));
return compact('verb', 'plain', 'uri');
}
/**
* Get the routable data for an index method.
*
* @param array $data
* @param string $prefix
* @return array
*/
protected function getIndexData($data, $prefix)
{
return array('verb' => $data['verb'], 'plain' => $prefix, 'uri' => $prefix);
}
/**
* Extract the verb from a controller action.
*
* @param string $name
* @return string
*/
public function getVerb($name)
{
return head(explode('_', snake_case($name)));
}
/**
* Determine the URI from the given method name.
*
* @param string $name
* @param string $prefix
* @return string
*/
public function getPlainUri($name, $prefix)
{
return $prefix.'/'.implode('-', array_slice(explode('_', snake_case($name)), 1));
}
/**
* Add wildcards to the given URI.
*
* @param string $uri
* @return string
*/
public function addUriWildcards($uri)
{
return $uri.'/{v1?}/{v2?}/{v3?}/{v4?}/{v5?}';
}
}
@@ -217,6 +217,81 @@ public function match($methods, $uri, $action)
return $this->addRoute($methods, $uri, $action);
}
/**
* Register an array of controllers with wildcard routing.
*
* @param array $controllers
* @return void
*/
public function controllers(array $controllers)
{
foreach ($controllers as $uri => $name)
{
$this->controller($uri, $name);
}
}
/**
* Route a controller to a URI with wildcard routing.
*
* @param string $uri
* @param string $controller
* @param array $names
* @return \Illuminate\Routing\Route
*/
public function controller($uri, $controller, $names = array())
{
$routable = $this->getInspector()->getRoutable($controller, $uri);

This comment has been minimized.

@crynobone

crynobone Oct 19, 2013

Contributor

Do we need to create a new instance of ControllerInspecter every time we call Route::controller(), it does seem that we could cache the instance (as we do with ControllerDispatcher), but I could be wrong.

This comment has been minimized.

@taylorotwell

taylorotwell via email Oct 19, 2013

Author Member
// When a controller is routed using this method, we use Reflection to parse
// out all of the routable methods for the controller, then register each
// route explicitly for the developers, so reverse routing is possible.
foreach ($routable as $method => $routes)
{
foreach ($routes as $route)
{
$this->registerInspected($route, $controller, $method, $names);
}
}
$this->addFallthroughRoute($controller, $uri);
}
/**
* Register an inspected controller route.
*
* @param array $route
* @param string $controller
* @param string $method
* @param array $names
* @return void
*/
protected function registerInspected($route, $controller, $method, &$names)
{
$action = array('uses' => $controller.'@'.$method);
// If a given controller method has been named, we will assign the name to the
// controller action array, which provides for a short-cut to method naming
// so you don't have to define an individual route for these controllers.
$action['as'] = array_pull($names, $method);
$this->{$route['verb']}($route['uri'], $action);
}
/**
* Add a fallthrough route for a controller.
*
* @param string $controller
* @param string $uri
* @return void
*/
protected function addFallthroughRoute($controller, $uri)
{
$missing = $this->any($uri.'/{_missing}', $controller.'@missingMethod');
$missing->where('_missing', '(.*)');
}
/**
* Route a resource to a controller.
*
@@ -1319,6 +1394,16 @@ public function setControllerDispatcher(ControllerDispatcher $dispatcher)
$this->controllerDispatcher = $dispatcher;
}
/**
* Get a controller inspector instance.
*
* @return \Illuminate\Routing\ControllerInspector
*/
public function getInspector()
{
return new ControllerInspector;
}
/**
* Get the response for a given request.
*

0 comments on commit 98c14a9

Please sign in to comment.