url.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <?php namespace Laravel; use Laravel\Routing\Router, Laravel\Routing\Route;
  2. class URL {
  3. /**
  4. * The cached base URL.
  5. *
  6. * @var string
  7. */
  8. public static $base;
  9. /**
  10. * Get the full URI including the query string.
  11. *
  12. * @return string
  13. */
  14. public static function full()
  15. {
  16. return static::to(URI::full());
  17. }
  18. /**
  19. * Get the full URL for the current request.
  20. *
  21. * @return string
  22. */
  23. public static function current()
  24. {
  25. return static::to(URI::current());
  26. }
  27. /**
  28. * Get the base URL of the application.
  29. *
  30. * @return string
  31. */
  32. public static function base()
  33. {
  34. if (isset(static::$base)) return static::$base;
  35. $base = 'http://localhost';
  36. // If the application URL configuration is set, we will just use that
  37. // instead of trying to guess the URL from the $_SERVER array's host
  38. // and script variables as this is more reliable.
  39. if (($url = Config::get('application.url')) !== '')
  40. {
  41. $base = $url;
  42. }
  43. elseif (isset($_SERVER['HTTP_HOST']))
  44. {
  45. $protocol = (Request::secure()) ? 'https://' : 'http://';
  46. // Basically, by removing the basename, we are removing everything after the
  47. // and including the front controller from the request URI. Leaving us with
  48. // the path in which the framework is installed.
  49. $script = $_SERVER['SCRIPT_NAME'];
  50. $path = str_replace(basename($script), '', $script);
  51. // Now that we have the base URL, all we need to do is attach the protocol
  52. // and the HTTP_HOST to build the full URL for the application. We also
  53. // trim off trailing slashes to clean the URL.
  54. $base = rtrim($protocol.$_SERVER['HTTP_HOST'].$path, '/');
  55. }
  56. return static::$base = $base;
  57. }
  58. /**
  59. * Generate an application URL.
  60. *
  61. * <code>
  62. * // Create a URL to a location within the application
  63. * $url = URL::to('user/profile');
  64. *
  65. * // Create a HTTPS URL to a location within the application
  66. * $url = URL::to('user/profile', true);
  67. * </code>
  68. *
  69. * @param string $url
  70. * @param bool $https
  71. * @return string
  72. */
  73. public static function to($url = '', $https = false)
  74. {
  75. if (filter_var($url, FILTER_VALIDATE_URL) !== false) return $url;
  76. $root = static::base().'/'.Config::get('application.index');
  77. // Since SSL is not often used while developing the application, we allow the
  78. // developer to disable SSL on all framework generated links to make it more
  79. // convenient to work with the site while developing locally.
  80. if ($https and Config::get('application.ssl'))
  81. {
  82. $root = preg_replace('~http://~', 'https://', $root, 1);
  83. }
  84. return rtrim($root, '/').'/'.ltrim($url, '/');
  85. }
  86. /**
  87. * Generate an application URL with HTTPS.
  88. *
  89. * @param string $url
  90. * @return string
  91. */
  92. public static function to_secure($url = '')
  93. {
  94. return static::to($url, true);
  95. }
  96. /**
  97. * Generate a URL to a controller action.
  98. *
  99. * <code>
  100. * // Generate a URL to the "index" method of the "user" controller
  101. * $url = URL::to_action('user@index');
  102. *
  103. * // Generate a URL to http://example.com/user/profile/taylor
  104. * $url = URL::to_action('user@profile', array('taylor'));
  105. * </code>
  106. *
  107. * @param string $action
  108. * @param array $parameters
  109. * @return string
  110. */
  111. public static function to_action($action, $parameters = array())
  112. {
  113. // This allows us to use true reverse routing to controllers, since
  114. // URIs may be setup to handle the action that do not follow the
  115. // typical Laravel controller URI conventions.
  116. $route = Router::uses($action);
  117. if ( ! is_null($route))
  118. {
  119. return static::explicit($route, $action, $parameters);
  120. }
  121. // If no route was found that handled the given action, we'll just
  122. // generate the URL using the typical controller routing setup
  123. // for URIs and turn SSL to false.
  124. else
  125. {
  126. return static::convention($action, $parameters);
  127. }
  128. }
  129. /**
  130. * Generate a action URL from a route definition
  131. *
  132. * @param array $route
  133. * @param string $action
  134. * @param array $parameters
  135. * @return string
  136. */
  137. protected static function explicit($route, $action, $parameters)
  138. {
  139. $https = array_get(current($route), 'https', false);
  140. return static::to(static::transpose(key($route), $parameters), $https);
  141. }
  142. /**
  143. * Generate an action URI by convention.
  144. *
  145. * @param string $action
  146. * @param array $parameters
  147. * @return string
  148. */
  149. protected static function convention($action, $parameters)
  150. {
  151. list($bundle, $action) = Bundle::parse($action);
  152. $bundle = Bundle::get($bundle);
  153. // If a bundle exists for the action, we will attempt to use it's "handles"
  154. // clause as the root of the generated URL, as the bundle can only handle
  155. // URIs that begin with that string.
  156. $root = $bundle['handles'] ?: '';
  157. $https = false;
  158. $parameters = implode('/', $parameters);
  159. // We'll replace both dots and @ signs in the URI since both are used
  160. // to specify the controller and action, and by convention should be
  161. // translated into URI slashes.
  162. $uri = $root.'/'.str_replace(array('.', '@'), '/', $action);
  163. $uri = static::to(str_finish($uri, '/').$parameters);
  164. return trim($uri, '/');
  165. }
  166. /**
  167. * Generate an application URL to an asset.
  168. *
  169. * @param string $url
  170. * @param bool $https
  171. * @return string
  172. */
  173. public static function to_asset($url, $https = null)
  174. {
  175. if (is_null($https)) $https = Request::secure();
  176. $url = static::to($url, $https);
  177. // Since assets are not served by Laravel, we do not need to come through
  178. // the front controller. So, we'll remove the application index specified
  179. // in the application config from the generated URL.
  180. if (($index = Config::get('application.index')) !== '')
  181. {
  182. $url = str_replace($index.'/', '', $url);
  183. }
  184. return $url;
  185. }
  186. /**
  187. * Generate a URL from a route name.
  188. *
  189. * <code>
  190. * // Create a URL to the "profile" named route
  191. * $url = URL::to_route('profile');
  192. *
  193. * // Create a URL to the "profile" named route with wildcard parameters
  194. * $url = URL::to_route('profile', array($username));
  195. * </code>
  196. *
  197. * @param string $name
  198. * @param array $parameters
  199. * @param bool $https
  200. * @return string
  201. */
  202. public static function to_route($name, $parameters = array())
  203. {
  204. if (is_null($route = Routing\Router::find($name)))
  205. {
  206. throw new \Exception("Error creating URL for undefined route [$name].");
  207. }
  208. // To determine whether the URL should be HTTPS or not, we look for the "https"
  209. // value on the route action array. The route has control over whether the URL
  210. // should be generated with an HTTPS protocol string or just HTTP.
  211. $https = array_get(current($route), 'https', false);
  212. $uri = trim(static::transpose(key($route), $parameters), '/');
  213. return static::to($uri, $https);
  214. }
  215. /**
  216. * Substitute the parameters in a given URI.
  217. *
  218. * @param string $uri
  219. * @param array $parameters
  220. * @return string
  221. */
  222. public static function transpose($uri, $parameters)
  223. {
  224. // Spin through each route parameter and replace the route wildcard segment
  225. // with the corresponding parameter passed to the method. Afterwards, we'll
  226. // replace all of the remaining optional URI segments.
  227. foreach ((array) $parameters as $parameter)
  228. {
  229. if ( ! is_null($parameter))
  230. {
  231. $uri = preg_replace('/\(.+?\)/', $parameter, $uri, 1);
  232. }
  233. }
  234. // If there are any remaining optional place-holders, we'll just replace
  235. // them with empty strings since not every optional parameter has to be
  236. // in the array of parameters that were passed.
  237. $uri = str_replace(array_keys(Router::$optional), '', $uri);
  238. return trim($uri, '/');
  239. }
  240. }