Created
August 15, 2017 07:21
-
-
Save barryvdh/4356322e471d069e1c2a66bfac8f48e7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Libraries; | |
use ReflectionClass; | |
use ReflectionMethod; | |
use Illuminate\Support\Str; | |
/** | |
* @deprecated since version 5.2. | |
*/ | |
class ControllerInspector | |
{ | |
/** | |
* An array of HTTP verbs. | |
* | |
* @var array | |
*/ | |
protected $verbs = [ | |
'any', 'get', 'post', 'put', 'patch', | |
'delete', 'head', 'options', | |
]; | |
/** | |
* Get the routable methods for a controller. | |
* | |
* @param string $controller | |
* @param string $prefix | |
* @return array | |
*/ | |
public function getRoutable($controller, $prefix) | |
{ | |
$routable = []; | |
$reflection = new ReflectionClass($controller); | |
$methods = $reflection->getMethods(ReflectionMethod::IS_PUBLIC); | |
// 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 ($methods as $method) { | |
if ($this->isRoutable($method)) { | |
$data = $this->getMethodData($method, $prefix); | |
$routable[$method->name][] = $data; | |
// 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][] = $this->getIndexData($data, $prefix); | |
} | |
} | |
} | |
return $routable; | |
} | |
/** | |
* Determine if the given controller method is routable. | |
* | |
* @param \ReflectionMethod $method | |
* @return bool | |
*/ | |
public function isRoutable(ReflectionMethod $method) | |
{ | |
if ($method->class == 'Illuminate\Routing\Controller') { | |
return false; | |
} | |
return Str::startsWith($method->name, $this->verbs); | |
} | |
/** | |
* Get the method data for a given method. | |
* | |
* @param \ReflectionMethod $method | |
* @param string $prefix | |
* @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 ['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('_', Str::snake($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('_', Str::snake($name)), 1)); | |
} | |
/** | |
* Add wildcards to the given URI. | |
* | |
* @param string $uri | |
* @return string | |
*/ | |
public function addUriWildcards($uri) | |
{ | |
return $uri.'/{one?}/{two?}/{three?}/{four?}/{five?}'; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use App\Libraries\ControllerInspector; | |
Route::macro('controller', function($uri, $controller, $names = []){ | |
$prepended = $controller; | |
// First, we will check to see if a controller prefix has been registered in | |
// the route group. If it has, we will need to prefix it before trying to | |
// reflect into the class instance and pull out the method for routing. | |
$groupStack = Route::getGroupStack(); | |
if (! empty($groupStack)) { | |
$group = end($groupStack); | |
$prepended = isset($group['namespace']) && strpos($controller, '\\') !== 0 ? $group['namespace'].'\\'.$controller : $controller; | |
} | |
$routable = (new ControllerInspector()) | |
->getRoutable($prepended, $uri); | |
// 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) { | |
$action = ['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'] = Arr::get($names, $method); | |
Route::{$route['verb']}($route['uri'], $action); | |
} | |
} | |
$missing = Route::any($uri.'/{_missing}', $controller.'@missingMethod'); | |
$missing->where('_missing', '(.*)'); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment