route.php 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. <?php namespace Laravel\Routing;
  2. use Closure;
  3. use Laravel\URI;
  4. use Laravel\Bundle;
  5. use Laravel\Request;
  6. use Laravel\Response;
  7. class Route {
  8. /**
  9. * The URI the route response to.
  10. *
  11. * @var string
  12. */
  13. public $uri;
  14. /**
  15. * The request method the route responds to.
  16. *
  17. * @var string
  18. */
  19. public $method;
  20. /**
  21. * The bundle in which the route was registered.
  22. *
  23. * @var string
  24. */
  25. public $bundle;
  26. /**
  27. * The action that is assigned to the route.
  28. *
  29. * @var mixed
  30. */
  31. public $action;
  32. /**
  33. * The parameters that will passed to the route callback.
  34. *
  35. * @var array
  36. */
  37. public $parameters;
  38. /**
  39. * Create a new Route instance.
  40. *
  41. * @param string $method
  42. * @param string $uri
  43. * @param array $action
  44. * @param array $parameters
  45. * @return void
  46. */
  47. public function __construct($method, $uri, $action, $parameters = array())
  48. {
  49. $this->uri = $uri;
  50. $this->method = $method;
  51. $this->action = $action;
  52. // Determine the bundle in which the route was registered. We will know
  53. // the bundle by using the bundle::handles method, which will return
  54. // the bundle assigned to that URI.
  55. $this->bundle = Bundle::handles($uri);
  56. // We'll set the parameters based on the number of parameters passed
  57. // compared to the parameters that were needed. If more parameters
  58. // are needed, we'll merge in defaults.
  59. $this->parameters($uri, $action, $parameters);
  60. }
  61. /**
  62. * Set the parameters array to the correct value.
  63. *
  64. * @param string $uri
  65. * @param array $action
  66. * @param array $parameters
  67. * @return void
  68. */
  69. protected function parameters($uri, $action, $parameters)
  70. {
  71. $defaults = (array) array_get($action, 'defaults');
  72. // If there are less parameters than wildcards, we will figure out how
  73. // many parameters we need to inject from the array of defaults and
  74. // merge them in into the main array for the route.
  75. if (count($defaults) > count($parameters))
  76. {
  77. $defaults = array_slice($defaults, count($parameters));
  78. $parameters = array_merge($parameters, $defaults);
  79. }
  80. $this->parameters = $parameters;
  81. }
  82. /**
  83. * Call a given route and return the route's response.
  84. *
  85. * @return Response
  86. */
  87. public function call()
  88. {
  89. // The route is responsible for running the global filters, and any
  90. // filters defined on the route itself, since all incoming requests
  91. // come through a route (either defined or ad-hoc).
  92. $response = Filter::run($this->filters('before'), array(), true);
  93. if (is_null($response))
  94. {
  95. $response = $this->response();
  96. }
  97. // We always return a Response instance from the route calls, so
  98. // we'll use the prepare method on the Response class to make
  99. // sure we have a valid Response isntance.
  100. $response = Response::prepare($response);
  101. Filter::run($this->filters('after'), array($response));
  102. return $response;
  103. }
  104. /**
  105. * Execute the route action and return the response.
  106. *
  107. * Unlike the "call" method, none of the attached filters will be run.
  108. *
  109. * @return mixed
  110. */
  111. public function response()
  112. {
  113. // If the action is a string, it is pointing the route to a controller
  114. // action, and we can just call the action and return its response.
  115. // We'll just pass the action off to the Controller class.
  116. $delegate = $this->delegate();
  117. if ( ! is_null($delegate))
  118. {
  119. return Controller::call($delegate, $this->parameters);
  120. }
  121. // If the route does not have a delegate, then it must be a Closure
  122. // instance or have a Closure in its action array, so we will try
  123. // to locate the Closure and call it directly.
  124. $handler = $this->handler();
  125. if ( ! is_null($handler))
  126. {
  127. return call_user_func_array($handler, $this->parameters);
  128. }
  129. }
  130. /**
  131. * Get the filters that are attached to the route for a given event.
  132. *
  133. * @param string $event
  134. * @return array
  135. */
  136. protected function filters($event)
  137. {
  138. $global = Bundle::prefix($this->bundle).$event;
  139. $filters = array_unique(array($event, $global));
  140. // Next we will check to see if there are any filters attached to
  141. // the route for the given event. If there are, we'll merge them
  142. // in with the global filters for the event.
  143. if (isset($this->action[$event]))
  144. {
  145. $assigned = Filter::parse($this->action[$event]);
  146. $filters = array_merge($filters, $assigned);
  147. }
  148. // Next we will attach any pattern type filters to the array of
  149. // filters as these are matched to the route by the route's
  150. // URI and not explicitly attached to routes.
  151. if ($event == 'before')
  152. {
  153. $filters = array_merge($filters, $this->patterns());
  154. }
  155. return array(new Filter_Collection($filters));
  156. }
  157. /**
  158. * Get the pattern filters for the route.
  159. *
  160. * @return array
  161. */
  162. protected function patterns()
  163. {
  164. $filters = array();
  165. // We will simply iterate through the registered patterns and
  166. // check the URI pattern against the URI for the route and
  167. // if they match we'll attach the filter.
  168. foreach (Filter::$patterns as $pattern => $filter)
  169. {
  170. if (URI::is($pattern, $this->uri))
  171. {
  172. $filters[] = $filter;
  173. }
  174. }
  175. return (array) $filters;
  176. }
  177. /**
  178. * Get the controller action delegate assigned to the route.
  179. *
  180. * If no delegate is assigned, null will be returned by the method.
  181. *
  182. * @return string
  183. */
  184. protected function delegate()
  185. {
  186. return array_get($this->action, 'uses');
  187. }
  188. /**
  189. * Get the anonymous function assigned to handle the route.
  190. *
  191. * @return Closure
  192. */
  193. protected function handler()
  194. {
  195. return array_first($this->action, function($key, $value)
  196. {
  197. return $value instanceof Closure;
  198. });
  199. }
  200. /**
  201. * Determine if the route has a given name.
  202. *
  203. * <code>
  204. * // Determine if the route is the "login" route
  205. * $login = Request::route()->is('login');
  206. * </code>
  207. *
  208. * @param string $name
  209. * @return bool
  210. */
  211. public function is($name)
  212. {
  213. return array_get($this->action, 'as') === $name;
  214. }
  215. /**
  216. * Register a controller with the router.
  217. *
  218. * @param string|array $controller
  219. * @param string|array $defaults
  220. * @return void
  221. */
  222. public static function controller($controllers, $defaults = 'index')
  223. {
  224. Router::controller($controllers, $defaults);
  225. }
  226. /**
  227. * Register a secure controller with the router.
  228. *
  229. * @param string|array $controllers
  230. * @param string|array $defaults
  231. * @return void
  232. */
  233. public static function secure_controller($controllers, $defaults = 'index')
  234. {
  235. Router::controller($controllers, $defaults, true);
  236. }
  237. /**
  238. * Register a GET route with the router.
  239. *
  240. * @param string|array $route
  241. * @param mixed $action
  242. * @return void
  243. */
  244. public static function get($route, $action)
  245. {
  246. Router::register('GET', $route, $action);
  247. }
  248. /**
  249. * Register a POST route with the router.
  250. *
  251. * @param string|array $route
  252. * @param mixed $action
  253. * @return void
  254. */
  255. public static function post($route, $action)
  256. {
  257. Router::register('POST', $route, $action);
  258. }
  259. /**
  260. * Register a PUT route with the router.
  261. *
  262. * @param string|array $route
  263. * @param mixed $action
  264. * @return void
  265. */
  266. public static function put($route, $action)
  267. {
  268. Router::register('PUT', $route, $action);
  269. }
  270. /**
  271. * Register a DELETE route with the router.
  272. *
  273. * @param string|array $route
  274. * @param mixed $action
  275. * @return void
  276. */
  277. public static function delete($route, $action)
  278. {
  279. Router::register('DELETE', $route, $action);
  280. }
  281. /**
  282. * Register a route that handles any request method.
  283. *
  284. * @param string|array $route
  285. * @param mixed $action
  286. * @return void
  287. */
  288. public static function any($route, $action)
  289. {
  290. Router::register('*', $route, $action);
  291. }
  292. /**
  293. * Register a group of routes that share attributes.
  294. *
  295. * @param array $attributes
  296. * @param Closure $callback
  297. * @return void
  298. */
  299. public static function group($attributes, Closure $callback)
  300. {
  301. Router::group($attributes, $callback);
  302. }
  303. /**
  304. * Register many request URIs to a single action.
  305. *
  306. * @param array $routes
  307. * @param mixed $action
  308. * @return void
  309. */
  310. public static function share($routes, $action)
  311. {
  312. Router::share($routes, $action);
  313. }
  314. /**
  315. * Register a HTTPS route with the router.
  316. *
  317. * @param string $method
  318. * @param string|array $route
  319. * @param mixed $action
  320. * @return void
  321. */
  322. public static function secure($method, $route, $action)
  323. {
  324. Router::secure($method, $route, $action);
  325. }
  326. /**
  327. * Register a route filter.
  328. *
  329. * @param string $name
  330. * @param mixed $callback
  331. * @return void
  332. */
  333. public static function filter($name, $callback)
  334. {
  335. Filter::register($name, $callback);
  336. }
  337. /**
  338. * Calls the specified route and returns its response.
  339. *
  340. * @param string $method
  341. * @param string $uri
  342. * @return Response
  343. */
  344. public static function forward($method, $uri)
  345. {
  346. return Router::route(strtoupper($method), $uri)->call();
  347. }
  348. }