route.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. <?php namespace Laravel\Routing;
  2. use Closure;
  3. use Laravel\Arr;
  4. class Route {
  5. /**
  6. * The route key, including request method and URI.
  7. *
  8. * @var string
  9. */
  10. public $key;
  11. /**
  12. * The URIs the route responds to.
  13. *
  14. * @var array
  15. */
  16. public $uris;
  17. /**
  18. * The route callback or array.
  19. *
  20. * @var mixed
  21. */
  22. public $callback;
  23. /**
  24. * The parameters that will passed to the route callback.
  25. *
  26. * @var array
  27. */
  28. public $parameters;
  29. /**
  30. * Create a new Route instance.
  31. *
  32. * @param string $key
  33. * @param mixed $callback
  34. * @param array $parameters
  35. * @return void
  36. */
  37. public function __construct($key, $callback, $parameters = array())
  38. {
  39. $this->key = $key;
  40. $this->callback = $callback;
  41. $this->parameters = $parameters;
  42. // The extractor closure will retrieve the URI from a given route destination.
  43. // If the request is to the root of the application, a single forward slash
  44. // will be returned, otherwise the leading slash will be removed.
  45. $extractor = function($segment)
  46. {
  47. $segment = substr($segment, strpos($segment, ' ') + 1);
  48. return ($segment !== '/') ? trim($segment, '/') : $segment;
  49. };
  50. // Extract each URI out of the route key. Since the route key has the request
  51. // method, we will extract the method off of the string. If the URI points to
  52. // the root of the application, a single forward slash will be returned.
  53. // Otherwise, the leading slash will be removed.
  54. if (strpos($key, ', ') === false)
  55. {
  56. $this->uris = array($extractor($this->key));
  57. }
  58. else
  59. {
  60. $this->uris = array_map(function($segment) use ($extractor) { return $extractor($segment); }, explode(', ', $key));
  61. }
  62. // The route callback must be either a Closure, an array, or a string. Closures
  63. // obviously handle the requests to the route. An array can contain filters, as
  64. // well as a Closure to handle requests to the route. A string, delegates control
  65. // of the request to a controller method.
  66. if ( ! $this->callback instanceof \Closure and ! is_array($this->callback) and ! is_string($this->callback))
  67. {
  68. throw new \Exception('Invalid route defined for URI ['.$this->key.']');
  69. }
  70. }
  71. /**
  72. * Call the closure defined for the route, or get the route delegator.
  73. *
  74. * @return mixed
  75. */
  76. public function call()
  77. {
  78. // If the value defined for a route is a Closure, we simply call the closure with the
  79. // route's parameters and return the response.
  80. if ($this->callback instanceof Closure)
  81. {
  82. return call_user_func_array($this->callback, $this->parameters);
  83. }
  84. // Otherwise, we will assume the route is an array and will return the first value with
  85. // a key of "delegate", or the first instance of a Closure. If the value is a string, the
  86. // route is delegating the responsibility for handling the request to a controller.
  87. elseif (is_array($this->callback))
  88. {
  89. $callback = Arr::first($this->callback, function($key, $value)
  90. {
  91. return $key == 'delegate' or $value instanceof Closure;
  92. });
  93. return ($callback instanceof Closure) ? call_user_func_array($callback, $this->parameters) : new Delegate($callback);
  94. }
  95. // If a value defined for a route is a string, it means the route is delegating control
  96. // of the request to a controller. If that is the case, we will simply return the string
  97. // for the route caller to parse and delegate.
  98. elseif (is_string($this->callback))
  99. {
  100. return new Delegate($this->callback);
  101. }
  102. }
  103. /**
  104. * Get an array of filter names defined for the route.
  105. *
  106. * @param string $name
  107. * @return array
  108. */
  109. public function filters($name)
  110. {
  111. if (is_array($this->callback) and isset($this->callback[$name]))
  112. {
  113. return explode(', ', $this->callback[$name]);
  114. }
  115. return array();
  116. }
  117. /**
  118. * Determine if the route has a given name.
  119. *
  120. * @param string $name
  121. * @return bool
  122. */
  123. public function is($name)
  124. {
  125. return (is_array($this->callback) and isset($this->callback['name'])) ? $this->callback['name'] === $name : false;
  126. }
  127. /**
  128. * Determine if the route handles a given URI.
  129. *
  130. * @param string $uri
  131. * @return bool
  132. */
  133. public function handles($uri)
  134. {
  135. return in_array($uri, $this->uris);
  136. }
  137. /**
  138. * Magic Method to handle dynamic method calls to determine the name of the route.
  139. */
  140. public function __call($method, $parameters)
  141. {
  142. if (strpos($method, 'is_') === 0) { return $this->is(substr($method, 3)); }
  143. }
  144. }