url.php 8.5 KB

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