CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Team
    • Issues (Github)
    • YouTube Channel
    • Get Involved
    • Bakery
    • Featured Resources
    • Newsletter
    • Certification
    • My CakePHP
    • CakeFest
    • Facebook
    • Twitter
    • Help & Support
    • Forum
    • Stack Overflow
    • IRC
    • Slack
    • Paid Support
CakePHP

C CakePHP 3.7 Red Velvet API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 3.7
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Namespaces

  • Cake
    • Auth
      • Storage
    • Cache
      • Engine
    • Collection
      • Iterator
    • Command
    • Console
      • Exception
    • Controller
      • Component
      • Exception
    • Core
      • Configure
        • Engine
      • Exception
      • Retry
    • Database
      • Driver
      • Exception
      • Expression
      • Schema
      • Statement
      • Type
    • Datasource
      • Exception
    • Error
      • Middleware
    • Event
      • Decorator
    • Filesystem
    • Form
    • Http
      • Client
        • Adapter
        • Auth
      • Cookie
      • Exception
      • Middleware
      • Session
    • I18n
      • Formatter
      • Middleware
      • Parser
    • Log
      • Engine
    • Mailer
      • Exception
      • Transport
    • Network
      • Exception
    • ORM
      • Association
      • Behavior
        • Translate
      • Exception
      • Locator
      • Rule
    • Routing
      • Exception
      • Filter
      • Middleware
      • Route
    • Shell
      • Helper
      • Task
    • TestSuite
      • Fixture
      • Stub
    • Utility
      • Exception
    • Validation
    • View
      • Exception
      • Form
      • Helper
      • Widget
  • None

Classes

  • Dispatcher
  • DispatcherFactory
  • DispatcherFilter
  • RouteBuilder
  • Router

Traits

  • RequestActionTrait
   1: <?php
   2: /**
   3:  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
   4:  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
   5:  *
   6:  * Licensed under The MIT License
   7:  * For full copyright and license information, please see the LICENSE.txt
   8:  * Redistributions of files must retain the above copyright notice.
   9:  *
  10:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11:  * @link          https://cakephp.org CakePHP(tm) Project
  12:  * @since         0.2.9
  13:  * @license       https://opensource.org/licenses/mit-license.php MIT License
  14:  */
  15: namespace Cake\Routing;
  16: 
  17: use Cake\Core\Configure;
  18: use Cake\Http\ServerRequest;
  19: use Cake\Routing\Exception\MissingRouteException;
  20: use Cake\Utility\Inflector;
  21: use Exception;
  22: use Psr\Http\Message\ServerRequestInterface;
  23: use ReflectionFunction;
  24: use ReflectionMethod;
  25: use RuntimeException;
  26: use Throwable;
  27: 
  28: /**
  29:  * Parses the request URL into controller, action, and parameters. Uses the connected routes
  30:  * to match the incoming URL string to parameters that will allow the request to be dispatched. Also
  31:  * handles converting parameter lists into URL strings, using the connected routes. Routing allows you to decouple
  32:  * the way the world interacts with your application (URLs) and the implementation (controllers and actions).
  33:  *
  34:  * ### Connecting routes
  35:  *
  36:  * Connecting routes is done using Router::connect(). When parsing incoming requests or reverse matching
  37:  * parameters, routes are enumerated in the order they were connected. For more information on routes and
  38:  * how to connect them see Router::connect().
  39:  */
  40: class Router
  41: {
  42: 
  43:     /**
  44:      * Have routes been loaded
  45:      *
  46:      * @var bool
  47:      * @deprecated 3.5.0 Routes will be loaded via the Application::routes() hook in 4.0.0
  48:      */
  49:     public static $initialized = false;
  50: 
  51:     /**
  52:      * Default route class.
  53:      *
  54:      * @var string
  55:      */
  56:     protected static $_defaultRouteClass = 'Cake\Routing\Route\Route';
  57: 
  58:     /**
  59:      * Contains the base string that will be applied to all generated URLs
  60:      * For example `https://example.com`
  61:      *
  62:      * @var string
  63:      */
  64:     protected static $_fullBaseUrl;
  65: 
  66:     /**
  67:      * Regular expression for action names
  68:      *
  69:      * @var string
  70:      */
  71:     const ACTION = 'index|show|add|create|edit|update|remove|del|delete|view|item';
  72: 
  73:     /**
  74:      * Regular expression for years
  75:      *
  76:      * @var string
  77:      */
  78:     const YEAR = '[12][0-9]{3}';
  79: 
  80:     /**
  81:      * Regular expression for months
  82:      *
  83:      * @var string
  84:      */
  85:     const MONTH = '0[1-9]|1[012]';
  86: 
  87:     /**
  88:      * Regular expression for days
  89:      *
  90:      * @var string
  91:      */
  92:     const DAY = '0[1-9]|[12][0-9]|3[01]';
  93: 
  94:     /**
  95:      * Regular expression for auto increment IDs
  96:      *
  97:      * @var string
  98:      */
  99:     const ID = '[0-9]+';
 100: 
 101:     /**
 102:      * Regular expression for UUIDs
 103:      *
 104:      * @var string
 105:      */
 106:     const UUID = '[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}';
 107: 
 108:     /**
 109:      * The route collection routes would be added to.
 110:      *
 111:      * @var \Cake\Routing\RouteCollection
 112:      */
 113:     protected static $_collection;
 114: 
 115:     /**
 116:      * A hash of request context data.
 117:      *
 118:      * @var array
 119:      */
 120:     protected static $_requestContext = [];
 121: 
 122:     /**
 123:      * Named expressions
 124:      *
 125:      * @var array
 126:      */
 127:     protected static $_namedExpressions = [
 128:         'Action' => Router::ACTION,
 129:         'Year' => Router::YEAR,
 130:         'Month' => Router::MONTH,
 131:         'Day' => Router::DAY,
 132:         'ID' => Router::ID,
 133:         'UUID' => Router::UUID
 134:     ];
 135: 
 136:     /**
 137:      * Maintains the request object stack for the current request.
 138:      * This will contain more than one request object when requestAction is used.
 139:      *
 140:      * @var array
 141:      */
 142:     protected static $_requests = [];
 143: 
 144:     /**
 145:      * Initial state is populated the first time reload() is called which is at the bottom
 146:      * of this file. This is a cheat as get_class_vars() returns the value of static vars even if they
 147:      * have changed.
 148:      *
 149:      * @var array
 150:      */
 151:     protected static $_initialState = [];
 152: 
 153:     /**
 154:      * The stack of URL filters to apply against routing URLs before passing the
 155:      * parameters to the route collection.
 156:      *
 157:      * @var callable[]
 158:      */
 159:     protected static $_urlFilters = [];
 160: 
 161:     /**
 162:      * Default extensions defined with Router::extensions()
 163:      *
 164:      * @var array
 165:      */
 166:     protected static $_defaultExtensions = [];
 167: 
 168:     /**
 169:      * Get or set default route class.
 170:      *
 171:      * @param string|null $routeClass Class name.
 172:      * @return string|null
 173:      */
 174:     public static function defaultRouteClass($routeClass = null)
 175:     {
 176:         if ($routeClass === null) {
 177:             return static::$_defaultRouteClass;
 178:         }
 179:         static::$_defaultRouteClass = $routeClass;
 180:     }
 181: 
 182:     /**
 183:      * Gets the named route patterns for use in config/routes.php
 184:      *
 185:      * @return array Named route elements
 186:      * @see \Cake\Routing\Router::$_namedExpressions
 187:      */
 188:     public static function getNamedExpressions()
 189:     {
 190:         return static::$_namedExpressions;
 191:     }
 192: 
 193:     /**
 194:      * Connects a new Route in the router.
 195:      *
 196:      * Compatibility proxy to \Cake\Routing\RouteBuilder::connect() in the `/` scope.
 197:      *
 198:      * @param string $route A string describing the template of the route
 199:      * @param array|string $defaults An array describing the default route parameters. These parameters will be used by default
 200:      *   and can supply routing parameters that are not dynamic. See above.
 201:      * @param array $options An array matching the named elements in the route to regular expressions which that
 202:      *   element should match. Also contains additional parameters such as which routed parameters should be
 203:      *   shifted into the passed arguments, supplying patterns for routing parameters and supplying the name of a
 204:      *   custom routing class.
 205:      * @return void
 206:      * @throws \Cake\Core\Exception\Exception
 207:      * @see \Cake\Routing\RouteBuilder::connect()
 208:      * @see \Cake\Routing\Router::scope()
 209:      */
 210:     public static function connect($route, $defaults = [], $options = [])
 211:     {
 212:         static::$initialized = true;
 213:         static::scope('/', function ($routes) use ($route, $defaults, $options) {
 214:             /** @var \Cake\Routing\RouteBuilder $routes */
 215:             $routes->connect($route, $defaults, $options);
 216:         });
 217:     }
 218: 
 219:     /**
 220:      * Connects a new redirection Route in the router.
 221:      *
 222:      * Compatibility proxy to \Cake\Routing\RouteBuilder::redirect() in the `/` scope.
 223:      *
 224:      * @param string $route A string describing the template of the route
 225:      * @param array|string $url A URL to redirect to. Can be a string or a Cake array-based URL
 226:      * @param array $options An array matching the named elements in the route to regular expressions which that
 227:      *   element should match. Also contains additional parameters such as which routed parameters should be
 228:      *   shifted into the passed arguments. As well as supplying patterns for routing parameters.
 229:      * @return void
 230:      * @see \Cake\Routing\RouteBuilder::redirect()
 231:      * @deprecated 3.3.0 Use Router::scope() and RouteBuilder::redirect() instead.
 232:      */
 233:     public static function redirect($route, $url, $options = [])
 234:     {
 235:         deprecationWarning(
 236:             'Router::redirect() is deprecated. ' .
 237:             'Use Router::scope() and RouteBuilder::redirect() instead.'
 238:         );
 239:         if (is_string($url)) {
 240:             $url = ['redirect' => $url];
 241:         }
 242:         if (!isset($options['routeClass'])) {
 243:             $options['routeClass'] = 'Cake\Routing\Route\RedirectRoute';
 244:         }
 245:         static::connect($route, $url, $options);
 246:     }
 247: 
 248:     /**
 249:      * Generate REST resource routes for the given controller(s).
 250:      *
 251:      * Compatibility proxy to \Cake\Routing\RouteBuilder::resources(). Additional, compatibility
 252:      * around prefixes and plugins and prefixes is handled by this method.
 253:      *
 254:      * A quick way to generate a default routes to a set of REST resources (controller(s)).
 255:      *
 256:      * ### Usage
 257:      *
 258:      * Connect resource routes for an app controller:
 259:      *
 260:      * ```
 261:      * Router::mapResources('Posts');
 262:      * ```
 263:      *
 264:      * Connect resource routes for the Comment controller in the
 265:      * Comments plugin:
 266:      *
 267:      * ```
 268:      * Router::mapResources('Comments.Comment');
 269:      * ```
 270:      *
 271:      * Plugins will create lower_case underscored resource routes. e.g
 272:      * `/comments/comment`
 273:      *
 274:      * Connect resource routes for the Posts controller in the
 275:      * Admin prefix:
 276:      *
 277:      * ```
 278:      * Router::mapResources('Posts', ['prefix' => 'admin']);
 279:      * ```
 280:      *
 281:      * Prefixes will create lower_case underscored resource routes. e.g
 282:      * `/admin/posts`
 283:      *
 284:      * ### Options:
 285:      *
 286:      * - 'id' - The regular expression fragment to use when matching IDs. By default, matches
 287:      *    integer values and UUIDs.
 288:      * - 'prefix' - Routing prefix to use for the generated routes. Defaults to ''.
 289:      *   Using this option will create prefixed routes, similar to using Routing.prefixes.
 290:      * - 'only' - Only connect the specific list of actions.
 291:      * - 'actions' - Override the method names used for connecting actions.
 292:      * - 'map' - Additional resource routes that should be connected. If you define 'only' and 'map',
 293:      *   make sure that your mapped methods are also in the 'only' list.
 294:      * - 'path' - Change the path so it doesn't match the resource name. E.g ArticlesController
 295:      *   is available at `/posts`
 296:      *
 297:      * @param string|array $controller A controller name or array of controller names (i.e. "Posts" or "ListItems")
 298:      * @param array $options Options to use when generating REST routes
 299:      * @see \Cake\Routing\RouteBuilder::resources()
 300:      * @deprecated 3.3.0 Use Router::scope() and RouteBuilder::resources() instead.
 301:      * @return void
 302:      */
 303:     public static function mapResources($controller, $options = [])
 304:     {
 305:         deprecationWarning(
 306:             'Router::mapResources() is deprecated. ' .
 307:             'Use Router::scope() and RouteBuilder::resources() instead.'
 308:         );
 309:         foreach ((array)$controller as $name) {
 310:             list($plugin, $name) = pluginSplit($name);
 311: 
 312:             $prefix = $pluginUrl = false;
 313:             if (!empty($options['prefix'])) {
 314:                 $prefix = $options['prefix'];
 315:                 unset($options['prefix']);
 316:             }
 317:             if ($plugin) {
 318:                 $pluginUrl = Inflector::underscore($plugin);
 319:             }
 320: 
 321:             $callback = function ($routes) use ($name, $options) {
 322:                 /** @var \Cake\Routing\RouteBuilder $routes */
 323:                 $routes->resources($name, $options);
 324:             };
 325: 
 326:             if ($plugin && $prefix) {
 327:                 $path = '/' . implode('/', [$prefix, $pluginUrl]);
 328:                 $params = ['prefix' => $prefix, 'plugin' => $plugin];
 329:                 static::scope($path, $params, $callback);
 330: 
 331:                 return;
 332:             }
 333: 
 334:             if ($prefix) {
 335:                 static::prefix($prefix, $callback);
 336: 
 337:                 return;
 338:             }
 339: 
 340:             if ($plugin) {
 341:                 static::plugin($plugin, $callback);
 342: 
 343:                 return;
 344:             }
 345: 
 346:             static::scope('/', $callback);
 347: 
 348:             return;
 349:         }
 350:     }
 351: 
 352:     /**
 353:      * Parses given URL string. Returns 'routing' parameters for that URL.
 354:      *
 355:      * @param string $url URL to be parsed.
 356:      * @param string $method The HTTP method being used.
 357:      * @return array Parsed elements from URL.
 358:      * @throws \Cake\Routing\Exception\MissingRouteException When a route cannot be handled
 359:      * @deprecated 3.4.0 Use Router::parseRequest() instead.
 360:      */
 361:     public static function parse($url, $method = '')
 362:     {
 363:         deprecationWarning(
 364:             'Router::parse() is deprecated. ' .
 365:             'Use Router::parseRequest() instead. This will require adopting the Http\Server library.'
 366:         );
 367:         if (!static::$initialized) {
 368:             static::_loadRoutes();
 369:         }
 370:         if (strpos($url, '/') !== 0) {
 371:             $url = '/' . $url;
 372:         }
 373: 
 374:         return static::$_collection->parse($url, $method);
 375:     }
 376: 
 377:     /**
 378:      * Get the routing parameters for the request is possible.
 379:      *
 380:      * @param \Psr\Http\Message\ServerRequestInterface $request The request to parse request data from.
 381:      * @return array Parsed elements from URL.
 382:      * @throws \Cake\Routing\Exception\MissingRouteException When a route cannot be handled
 383:      */
 384:     public static function parseRequest(ServerRequestInterface $request)
 385:     {
 386:         if (!static::$initialized) {
 387:             static::_loadRoutes();
 388:         }
 389: 
 390:         return static::$_collection->parseRequest($request);
 391:     }
 392: 
 393:     /**
 394:      * Takes parameter and path information back from the Dispatcher, sets these
 395:      * parameters as the current request parameters that are merged with URL arrays
 396:      * created later in the request.
 397:      *
 398:      * Nested requests will create a stack of requests. You can remove requests using
 399:      * Router::popRequest(). This is done automatically when using Object::requestAction().
 400:      *
 401:      * Will accept either a Cake\Http\ServerRequest object or an array of arrays. Support for
 402:      * accepting arrays may be removed in the future.
 403:      *
 404:      * @param \Cake\Http\ServerRequest|array $request Parameters and path information or a Cake\Http\ServerRequest object.
 405:      * @return void
 406:      * @deprecatd 3.6.0 Support for arrays will be removed in 4.0.0
 407:      */
 408:     public static function setRequestInfo($request)
 409:     {
 410:         if ($request instanceof ServerRequest) {
 411:             static::pushRequest($request);
 412:         } else {
 413:             deprecationWarning(
 414:                 'Passing an array into Router::setRequestInfo() is deprecated. ' .
 415:                 'Pass an instance of ServerRequest instead.'
 416:             );
 417: 
 418:             $requestData = $request;
 419:             $requestData += [[], []];
 420:             $requestData[0] += [
 421:                 'controller' => false,
 422:                 'action' => false,
 423:                 'plugin' => null
 424:             ];
 425:             $request = new ServerRequest([
 426:                 'params' => $requestData[0],
 427:                 'url' => isset($requestData[1]['here']) ? $requestData[1]['here'] : '/',
 428:                 'base' => isset($requestData[1]['base']) ? $requestData[1]['base'] : '',
 429:                 'webroot' => isset($requestData[1]['webroot']) ? $requestData[1]['webroot'] : '/',
 430:             ]);
 431:             static::pushRequest($request);
 432:         }
 433:     }
 434: 
 435:     /**
 436:      * Push a request onto the request stack. Pushing a request
 437:      * sets the request context used when generating URLs.
 438:      *
 439:      * @param \Cake\Http\ServerRequest $request Request instance.
 440:      * @return void
 441:      */
 442:     public static function pushRequest(ServerRequest $request)
 443:     {
 444:         static::$_requests[] = $request;
 445:         static::setRequestContext($request);
 446:     }
 447: 
 448:     /**
 449:      * Store the request context for a given request.
 450:      *
 451:      * @param \Psr\Http\Message\ServerRequestInterface $request The request instance.
 452:      * @return void
 453:      * @throws \InvalidArgumentException When parameter is an incorrect type.
 454:      */
 455:     public static function setRequestContext(ServerRequestInterface $request)
 456:     {
 457:         $uri = $request->getUri();
 458:         static::$_requestContext = [
 459:             '_base' => $request->getAttribute('base'),
 460:             '_port' => $uri->getPort(),
 461:             '_scheme' => $uri->getScheme(),
 462:             '_host' => $uri->getHost(),
 463:         ];
 464:     }
 465: 
 466:     /**
 467:      * Pops a request off of the request stack. Used when doing requestAction
 468:      *
 469:      * @return \Cake\Http\ServerRequest The request removed from the stack.
 470:      * @see \Cake\Routing\Router::pushRequest()
 471:      * @see \Cake\Routing\RequestActionTrait::requestAction()
 472:      */
 473:     public static function popRequest()
 474:     {
 475:         $removed = array_pop(static::$_requests);
 476:         $last = end(static::$_requests);
 477:         if ($last) {
 478:             static::setRequestContext($last);
 479:             reset(static::$_requests);
 480:         }
 481: 
 482:         return $removed;
 483:     }
 484: 
 485:     /**
 486:      * Get the current request object, or the first one.
 487:      *
 488:      * @param bool $current True to get the current request, or false to get the first one.
 489:      * @return \Cake\Http\ServerRequest|null
 490:      */
 491:     public static function getRequest($current = false)
 492:     {
 493:         if ($current) {
 494:             $request = end(static::$_requests);
 495: 
 496:             return $request ?: null;
 497:         }
 498: 
 499:         return isset(static::$_requests[0]) ? static::$_requests[0] : null;
 500:     }
 501: 
 502:     /**
 503:      * Reloads default Router settings. Resets all class variables and
 504:      * removes all connected routes.
 505:      *
 506:      * @return void
 507:      */
 508:     public static function reload()
 509:     {
 510:         if (empty(static::$_initialState)) {
 511:             static::$_collection = new RouteCollection();
 512:             static::$_initialState = get_class_vars(get_called_class());
 513: 
 514:             return;
 515:         }
 516:         foreach (static::$_initialState as $key => $val) {
 517:             if ($key !== '_initialState') {
 518:                 static::${$key} = $val;
 519:             }
 520:         }
 521:         static::$_collection = new RouteCollection();
 522:     }
 523: 
 524:     /**
 525:      * Reset routes and related state.
 526:      *
 527:      * Similar to reload() except that this doesn't reset all global state,
 528:      * as that leads to incorrect behavior in some plugin test case scenarios.
 529:      *
 530:      * This method will reset:
 531:      *
 532:      * - routes
 533:      * - URL Filters
 534:      * - the initialized property
 535:      *
 536:      * Extensions and default route classes will not be modified
 537:      *
 538:      * @internal
 539:      * @return void
 540:      */
 541:     public static function resetRoutes()
 542:     {
 543:         static::$_collection = new RouteCollection();
 544:         static::$_urlFilters = [];
 545:         static::$initialized = false;
 546:     }
 547: 
 548:     /**
 549:      * Add a URL filter to Router.
 550:      *
 551:      * URL filter functions are applied to every array $url provided to
 552:      * Router::url() before the URLs are sent to the route collection.
 553:      *
 554:      * Callback functions should expect the following parameters:
 555:      *
 556:      * - `$params` The URL params being processed.
 557:      * - `$request` The current request.
 558:      *
 559:      * The URL filter function should *always* return the params even if unmodified.
 560:      *
 561:      * ### Usage
 562:      *
 563:      * URL filters allow you to easily implement features like persistent parameters.
 564:      *
 565:      * ```
 566:      * Router::addUrlFilter(function ($params, $request) {
 567:      *  if ($request->getParam('lang') && !isset($params['lang'])) {
 568:      *    $params['lang'] = $request->getParam('lang');
 569:      *  }
 570:      *  return $params;
 571:      * });
 572:      * ```
 573:      *
 574:      * @param callable $function The function to add
 575:      * @return void
 576:      */
 577:     public static function addUrlFilter(callable $function)
 578:     {
 579:         static::$_urlFilters[] = $function;
 580:     }
 581: 
 582:     /**
 583:      * Applies all the connected URL filters to the URL.
 584:      *
 585:      * @param array $url The URL array being modified.
 586:      * @return array The modified URL.
 587:      * @see \Cake\Routing\Router::url()
 588:      * @see \Cake\Routing\Router::addUrlFilter()
 589:      */
 590:     protected static function _applyUrlFilters($url)
 591:     {
 592:         $request = static::getRequest(true);
 593:         $e = null;
 594:         foreach (static::$_urlFilters as $filter) {
 595:             try {
 596:                 $url = $filter($url, $request);
 597:             } catch (Exception $e) {
 598:                 // fall through
 599:             } catch (Throwable $e) {
 600:                 // fall through
 601:             }
 602:             if ($e !== null) {
 603:                 if (is_array($filter)) {
 604:                     $ref = new ReflectionMethod($filter[0], $filter[1]);
 605:                 } else {
 606:                     $ref = new ReflectionFunction($filter);
 607:                 }
 608:                 $message = sprintf(
 609:                     'URL filter defined in %s on line %s could not be applied. The filter failed with: %s',
 610:                     $ref->getFileName(),
 611:                     $ref->getStartLine(),
 612:                     $e->getMessage()
 613:                 );
 614:                 throw new RuntimeException($message, $e->getCode(), $e);
 615:             }
 616:         }
 617: 
 618:         return $url;
 619:     }
 620: 
 621:     /**
 622:      * Finds URL for specified action.
 623:      *
 624:      * Returns a URL pointing to a combination of controller and action.
 625:      *
 626:      * ### Usage
 627:      *
 628:      * - `Router::url('/posts/edit/1');` Returns the string with the base dir prepended.
 629:      *   This usage does not use reverser routing.
 630:      * - `Router::url(['controller' => 'posts', 'action' => 'edit']);` Returns a URL
 631:      *   generated through reverse routing.
 632:      * - `Router::url(['_name' => 'custom-name', ...]);` Returns a URL generated
 633:      *   through reverse routing. This form allows you to leverage named routes.
 634:      *
 635:      * There are a few 'special' parameters that can change the final URL string that is generated
 636:      *
 637:      * - `_base` - Set to false to remove the base path from the generated URL. If your application
 638:      *   is not in the root directory, this can be used to generate URLs that are 'cake relative'.
 639:      *   cake relative URLs are required when using requestAction.
 640:      * - `_scheme` - Set to create links on different schemes like `webcal` or `ftp`. Defaults
 641:      *   to the current scheme.
 642:      * - `_host` - Set the host to use for the link. Defaults to the current host.
 643:      * - `_port` - Set the port if you need to create links on non-standard ports.
 644:      * - `_full` - If true output of `Router::fullBaseUrl()` will be prepended to generated URLs.
 645:      * - `#` - Allows you to set URL hash fragments.
 646:      * - `_ssl` - Set to true to convert the generated URL to https, or false to force http.
 647:      * - `_name` - Name of route. If you have setup named routes you can use this key
 648:      *   to specify it.
 649:      *
 650:      * @param string|array|null $url An array specifying any of the following:
 651:      *   'controller', 'action', 'plugin' additionally, you can provide routed
 652:      *   elements or query string parameters. If string it can be name any valid url
 653:      *   string.
 654:      * @param bool $full If true, the full base URL will be prepended to the result.
 655:      *   Default is false.
 656:      * @return string Full translated URL with base path.
 657:      * @throws \Cake\Core\Exception\Exception When the route name is not found
 658:      */
 659:     public static function url($url = null, $full = false)
 660:     {
 661:         if (!static::$initialized) {
 662:             static::_loadRoutes();
 663:         }
 664: 
 665:         $params = [
 666:             'plugin' => null,
 667:             'controller' => null,
 668:             'action' => 'index',
 669:             '_ext' => null,
 670:         ];
 671:         $here = $output = $frag = null;
 672: 
 673:         $context = static::$_requestContext;
 674:         // In 4.x this should be replaced with state injected via setRequestContext
 675:         $request = static::getRequest(true);
 676:         if ($request) {
 677:             $params = $request->getAttribute('params');
 678:             $here = $request->getRequestTarget();
 679:             $context['_base'] = $request->getAttribute('base');
 680:         } elseif (!isset($context['_base'])) {
 681:             $context['_base'] = Configure::read('App.base');
 682:         }
 683: 
 684:         if (empty($url)) {
 685:             $output = $context['_base'] . (isset($here) ? $here : '/');
 686:             if ($full) {
 687:                 $output = static::fullBaseUrl() . $output;
 688:             }
 689: 
 690:             return $output;
 691:         }
 692:         if (is_array($url)) {
 693:             if (isset($url['_ssl'])) {
 694:                 $url['_scheme'] = ($url['_ssl'] === true) ? 'https' : 'http';
 695:             }
 696: 
 697:             if (isset($url['_full']) && $url['_full'] === true) {
 698:                 $full = true;
 699:             }
 700:             if (isset($url['#'])) {
 701:                 $frag = '#' . $url['#'];
 702:             }
 703:             unset($url['_ssl'], $url['_full'], $url['#']);
 704: 
 705:             $url = static::_applyUrlFilters($url);
 706: 
 707:             if (!isset($url['_name'])) {
 708:                 // Copy the current action if the controller is the current one.
 709:                 if (empty($url['action']) &&
 710:                     (empty($url['controller']) || $params['controller'] === $url['controller'])
 711:                 ) {
 712:                     $url['action'] = $params['action'];
 713:                 }
 714: 
 715:                 // Keep the current prefix around if none set.
 716:                 if (isset($params['prefix']) && !isset($url['prefix'])) {
 717:                     $url['prefix'] = $params['prefix'];
 718:                 }
 719: 
 720:                 $url += [
 721:                     'plugin' => $params['plugin'],
 722:                     'controller' => $params['controller'],
 723:                     'action' => 'index',
 724:                     '_ext' => null
 725:                 ];
 726:             }
 727: 
 728:             // If a full URL is requested with a scheme the host should default
 729:             // to App.fullBaseUrl to avoid corrupt URLs
 730:             if ($full && isset($url['_scheme']) && !isset($url['_host'])) {
 731:                 $url['_host'] = parse_url(static::fullBaseUrl(), PHP_URL_HOST);
 732:             }
 733:             $context['params'] = $params;
 734: 
 735:             $output = static::$_collection->match($url, $context);
 736:         } else {
 737:             $plainString = (
 738:                 strpos($url, 'javascript:') === 0 ||
 739:                 strpos($url, 'mailto:') === 0 ||
 740:                 strpos($url, 'tel:') === 0 ||
 741:                 strpos($url, 'sms:') === 0 ||
 742:                 strpos($url, '#') === 0 ||
 743:                 strpos($url, '?') === 0 ||
 744:                 strpos($url, '//') === 0 ||
 745:                 strpos($url, '://') !== false
 746:             );
 747: 
 748:             if ($plainString) {
 749:                 return $url;
 750:             }
 751:             $output = $context['_base'] . $url;
 752:         }
 753:         $protocol = preg_match('#^[a-z][a-z0-9+\-.]*\://#i', $output);
 754:         if ($protocol === 0) {
 755:             $output = str_replace('//', '/', '/' . $output);
 756:             if ($full) {
 757:                 $output = static::fullBaseUrl() . $output;
 758:             }
 759:         }
 760: 
 761:         return $output . $frag;
 762:     }
 763: 
 764:     /**
 765:      * Finds URL for specified action.
 766:      *
 767:      * Returns a bool if the url exists
 768:      *
 769:      * ### Usage
 770:      *
 771:      * @see Router::url()
 772:      *
 773:      * @param string|array|null $url An array specifying any of the following:
 774:      *   'controller', 'action', 'plugin' additionally, you can provide routed
 775:      *   elements or query string parameters. If string it can be name any valid url
 776:      *   string.
 777:      * @param bool $full If true, the full base URL will be prepended to the result.
 778:      *   Default is false.
 779:      * @return bool
 780:      */
 781:     public static function routeExists($url = null, $full = false)
 782:     {
 783:         try {
 784:             $route = static::url($url, $full);
 785: 
 786:             return true;
 787:         } catch (MissingRouteException $e) {
 788:             return false;
 789:         }
 790:     }
 791: 
 792:     /**
 793:      * Sets the full base URL that will be used as a prefix for generating
 794:      * fully qualified URLs for this application. If no parameters are passed,
 795:      * the currently configured value is returned.
 796:      *
 797:      * ### Note:
 798:      *
 799:      * If you change the configuration value `App.fullBaseUrl` during runtime
 800:      * and expect the router to produce links using the new setting, you are
 801:      * required to call this method passing such value again.
 802:      *
 803:      * @param string|null $base the prefix for URLs generated containing the domain.
 804:      * For example: `http://example.com`
 805:      * @return string
 806:      */
 807:     public static function fullBaseUrl($base = null)
 808:     {
 809:         if ($base !== null) {
 810:             static::$_fullBaseUrl = $base;
 811:             Configure::write('App.fullBaseUrl', $base);
 812:         }
 813:         if (empty(static::$_fullBaseUrl)) {
 814:             static::$_fullBaseUrl = Configure::read('App.fullBaseUrl');
 815:         }
 816: 
 817:         return static::$_fullBaseUrl;
 818:     }
 819: 
 820:     /**
 821:      * Reverses a parsed parameter array into an array.
 822:      *
 823:      * Works similarly to Router::url(), but since parsed URL's contain additional
 824:      * 'pass' as well as 'url.url' keys. Those keys need to be specially
 825:      * handled in order to reverse a params array into a string URL.
 826:      *
 827:      * This will strip out 'autoRender', 'bare', 'requested', and 'return' param names as those
 828:      * are used for CakePHP internals and should not normally be part of an output URL.
 829:      *
 830:      * @param \Cake\Http\ServerRequest|array $params The params array or
 831:      *     Cake\Http\ServerRequest object that needs to be reversed.
 832:      * @return array The URL array ready to be used for redirect or HTML link.
 833:      */
 834:     public static function reverseToArray($params)
 835:     {
 836:         $url = [];
 837:         if ($params instanceof ServerRequest) {
 838:             $url = $params->getQueryParams();
 839:             $params = $params->getAttribute('params');
 840:         } elseif (isset($params['url'])) {
 841:             $url = $params['url'];
 842:         }
 843:         $pass = isset($params['pass']) ? $params['pass'] : [];
 844: 
 845:         unset(
 846:             $params['pass'],
 847:             $params['paging'],
 848:             $params['models'],
 849:             $params['url'],
 850:             $url['url'],
 851:             $params['autoRender'],
 852:             $params['bare'],
 853:             $params['requested'],
 854:             $params['return'],
 855:             $params['_Token'],
 856:             $params['_matchedRoute'],
 857:             $params['_name']
 858:         );
 859:         $params = array_merge($params, $pass);
 860:         if (!empty($url)) {
 861:             $params['?'] = $url;
 862:         }
 863: 
 864:         return $params;
 865:     }
 866: 
 867:     /**
 868:      * Reverses a parsed parameter array into a string.
 869:      *
 870:      * Works similarly to Router::url(), but since parsed URL's contain additional
 871:      * 'pass' as well as 'url.url' keys. Those keys need to be specially
 872:      * handled in order to reverse a params array into a string URL.
 873:      *
 874:      * This will strip out 'autoRender', 'bare', 'requested', and 'return' param names as those
 875:      * are used for CakePHP internals and should not normally be part of an output URL.
 876:      *
 877:      * @param \Cake\Http\ServerRequest|array $params The params array or
 878:      *     Cake\Http\ServerRequest object that needs to be reversed.
 879:      * @param bool $full Set to true to include the full URL including the
 880:      *     protocol when reversing the URL.
 881:      * @return string The string that is the reversed result of the array
 882:      */
 883:     public static function reverse($params, $full = false)
 884:     {
 885:         $params = static::reverseToArray($params);
 886: 
 887:         return static::url($params, $full);
 888:     }
 889: 
 890:     /**
 891:      * Normalizes a URL for purposes of comparison.
 892:      *
 893:      * Will strip the base path off and replace any double /'s.
 894:      * It will not unify the casing and underscoring of the input value.
 895:      *
 896:      * @param array|string $url URL to normalize Either an array or a string URL.
 897:      * @return string Normalized URL
 898:      */
 899:     public static function normalize($url = '/')
 900:     {
 901:         if (is_array($url)) {
 902:             $url = static::url($url);
 903:         }
 904:         if (preg_match('/^[a-z\-]+:\/\//', $url)) {
 905:             return $url;
 906:         }
 907:         $request = static::getRequest();
 908: 
 909:         if ($request) {
 910:             $base = $request->getAttribute('base');
 911:             if (strlen($base) && stristr($url, $base)) {
 912:                 $url = preg_replace('/^' . preg_quote($base, '/') . '/', '', $url, 1);
 913:             }
 914:         }
 915:         $url = '/' . $url;
 916: 
 917:         while (strpos($url, '//') !== false) {
 918:             $url = str_replace('//', '/', $url);
 919:         }
 920:         $url = preg_replace('/(?:(\/$))/', '', $url);
 921: 
 922:         if (empty($url)) {
 923:             return '/';
 924:         }
 925: 
 926:         return $url;
 927:     }
 928: 
 929:     /**
 930:      * Get or set valid extensions for all routes connected later.
 931:      *
 932:      * Instructs the router to parse out file extensions
 933:      * from the URL. For example, http://example.com/posts.rss would yield a file
 934:      * extension of "rss". The file extension itself is made available in the
 935:      * controller as `$this->request->getParam('_ext')`, and is used by the RequestHandler
 936:      * component to automatically switch to alternate layouts and templates, and
 937:      * load helpers corresponding to the given content, i.e. RssHelper. Switching
 938:      * layouts and helpers requires that the chosen extension has a defined mime type
 939:      * in `Cake\Http\Response`.
 940:      *
 941:      * A string or an array of valid extensions can be passed to this method.
 942:      * If called without any parameters it will return current list of set extensions.
 943:      *
 944:      * @param array|string|null $extensions List of extensions to be added.
 945:      * @param bool $merge Whether to merge with or override existing extensions.
 946:      *   Defaults to `true`.
 947:      * @return array Array of extensions Router is configured to parse.
 948:      */
 949:     public static function extensions($extensions = null, $merge = true)
 950:     {
 951:         $collection = static::$_collection;
 952:         if ($extensions === null) {
 953:             if (!static::$initialized) {
 954:                 static::_loadRoutes();
 955:             }
 956: 
 957:             return array_unique(array_merge(static::$_defaultExtensions, $collection->getExtensions()));
 958:         }
 959:         $extensions = (array)$extensions;
 960:         if ($merge) {
 961:             $extensions = array_unique(array_merge(static::$_defaultExtensions, $extensions));
 962:         }
 963: 
 964:         return static::$_defaultExtensions = $extensions;
 965:     }
 966: 
 967:     /**
 968:      * Provides legacy support for named parameters on incoming URLs.
 969:      *
 970:      * Checks the passed parameters for elements containing `$options['separator']`
 971:      * Those parameters are split and parsed as if they were old style named parameters.
 972:      *
 973:      * The parsed parameters will be moved from params['pass'] to params['named'].
 974:      *
 975:      * ### Options
 976:      *
 977:      * - `separator` The string to use as a separator. Defaults to `:`.
 978:      *
 979:      * @param \Cake\Http\ServerRequest $request The request object to modify.
 980:      * @param array $options The array of options.
 981:      * @return \Cake\Http\ServerRequest The modified request
 982:      * @deprecated 3.3.0 Named parameter backwards compatibility will be removed in 4.0.
 983:      */
 984:     public static function parseNamedParams(ServerRequest $request, array $options = [])
 985:     {
 986:         deprecationWarning(
 987:             'Router::parseNamedParams() is deprecated. ' .
 988:             '2.x backwards compatible named parameter support will be removed in 4.0'
 989:         );
 990:         $options += ['separator' => ':'];
 991:         if (!$request->getParam('pass')) {
 992:             return $request->withParam('named', []);
 993:         }
 994:         $named = [];
 995:         $pass = $request->getParam('pass');
 996:         foreach ((array)$pass as $key => $value) {
 997:             if (strpos($value, $options['separator']) === false) {
 998:                 continue;
 999:             }
1000:             unset($pass[$key]);
1001:             list($key, $value) = explode($options['separator'], $value, 2);
1002: 
1003:             if (preg_match_all('/\[([A-Za-z0-9_-]+)?\]/', $key, $matches, PREG_SET_ORDER)) {
1004:                 $matches = array_reverse($matches);
1005:                 $parts = explode('[', $key);
1006:                 $key = array_shift($parts);
1007:                 $arr = $value;
1008:                 foreach ($matches as $match) {
1009:                     if (empty($match[1])) {
1010:                         $arr = [$arr];
1011:                     } else {
1012:                         $arr = [
1013:                             $match[1] => $arr
1014:                         ];
1015:                     }
1016:                 }
1017:                 $value = $arr;
1018:             }
1019:             $named = array_merge_recursive($named, [$key => $value]);
1020:         }
1021: 
1022:         return $request
1023:             ->withParam('pass', $pass)
1024:             ->withParam('named', $named);
1025:     }
1026: 
1027:     /**
1028:      * Create a RouteBuilder for the provided path.
1029:      *
1030:      * @param string $path The path to set the builder to.
1031:      * @param array $options The options for the builder
1032:      * @return \Cake\Routing\RouteBuilder
1033:      */
1034:     public static function createRouteBuilder($path, array $options = [])
1035:     {
1036:         $defaults = [
1037:             'routeClass' => static::defaultRouteClass(),
1038:             'extensions' => static::$_defaultExtensions,
1039:         ];
1040:         $options += $defaults;
1041: 
1042:         return new RouteBuilder(static::$_collection, $path, [], [
1043:             'routeClass' => $options['routeClass'],
1044:             'extensions' => $options['extensions'],
1045:         ]);
1046:     }
1047: 
1048:     /**
1049:      * Create a routing scope.
1050:      *
1051:      * Routing scopes allow you to keep your routes DRY and avoid repeating
1052:      * common path prefixes, and or parameter sets.
1053:      *
1054:      * Scoped collections will be indexed by path for faster route parsing. If you
1055:      * re-open or re-use a scope the connected routes will be merged with the
1056:      * existing ones.
1057:      *
1058:      * ### Options
1059:      *
1060:      * The `$params` array allows you to define options for the routing scope.
1061:      * The options listed below *are not* available to be used as routing defaults
1062:      *
1063:      * - `routeClass` The route class to use in this scope. Defaults to
1064:      *   `Router::defaultRouteClass()`
1065:      * - `extensions` The extensions to enable in this scope. Defaults to the globally
1066:      *   enabled extensions set with `Router::extensions()`
1067:      *
1068:      * ### Example
1069:      *
1070:      * ```
1071:      * Router::scope('/blog', ['plugin' => 'Blog'], function ($routes) {
1072:      *    $routes->connect('/', ['controller' => 'Articles']);
1073:      * });
1074:      * ```
1075:      *
1076:      * The above would result in a `/blog/` route being created, with both the
1077:      * plugin & controller default parameters set.
1078:      *
1079:      * You can use `Router::plugin()` and `Router::prefix()` as shortcuts to creating
1080:      * specific kinds of scopes.
1081:      *
1082:      * @param string $path The path prefix for the scope. This path will be prepended
1083:      *   to all routes connected in the scoped collection.
1084:      * @param array|callable $params An array of routing defaults to add to each connected route.
1085:      *   If you have no parameters, this argument can be a callable.
1086:      * @param callable|null $callback The callback to invoke with the scoped collection.
1087:      * @throws \InvalidArgumentException When an invalid callable is provided.
1088:      * @return void
1089:      */
1090:     public static function scope($path, $params = [], $callback = null)
1091:     {
1092:         $options = [];
1093:         if (is_array($params)) {
1094:             $options = $params;
1095:             unset($params['routeClass'], $params['extensions']);
1096:         }
1097:         $builder = static::createRouteBuilder('/', $options);
1098:         $builder->scope($path, $params, $callback);
1099:     }
1100: 
1101:     /**
1102:      * Create prefixed routes.
1103:      *
1104:      * This method creates a scoped route collection that includes
1105:      * relevant prefix information.
1106:      *
1107:      * The path parameter is used to generate the routing parameter name.
1108:      * For example a path of `admin` would result in `'prefix' => 'admin'` being
1109:      * applied to all connected routes.
1110:      *
1111:      * The prefix name will be inflected to the underscore version to create
1112:      * the routing path. If you want a custom path name, use the `path` option.
1113:      *
1114:      * You can re-open a prefix as many times as necessary, as well as nest prefixes.
1115:      * Nested prefixes will result in prefix values like `admin/api` which translates
1116:      * to the `Controller\Admin\Api\` namespace.
1117:      *
1118:      * @param string $name The prefix name to use.
1119:      * @param array|callable $params An array of routing defaults to add to each connected route.
1120:      *   If you have no parameters, this argument can be a callable.
1121:      * @param callable|null $callback The callback to invoke that builds the prefixed routes.
1122:      * @return void
1123:      */
1124:     public static function prefix($name, $params = [], $callback = null)
1125:     {
1126:         if ($callback === null) {
1127:             $callback = $params;
1128:             $params = [];
1129:         }
1130:         $name = Inflector::underscore($name);
1131: 
1132:         if (empty($params['path'])) {
1133:             $path = '/' . $name;
1134:         } else {
1135:             $path = $params['path'];
1136:             unset($params['path']);
1137:         }
1138: 
1139:         $params = array_merge($params, ['prefix' => $name]);
1140:         static::scope($path, $params, $callback);
1141:     }
1142: 
1143:     /**
1144:      * Add plugin routes.
1145:      *
1146:      * This method creates a scoped route collection that includes
1147:      * relevant plugin information.
1148:      *
1149:      * The plugin name will be inflected to the underscore version to create
1150:      * the routing path. If you want a custom path name, use the `path` option.
1151:      *
1152:      * Routes connected in the scoped collection will have the correct path segment
1153:      * prepended, and have a matching plugin routing key set.
1154:      *
1155:      * @param string $name The plugin name to build routes for
1156:      * @param array|callable $options Either the options to use, or a callback
1157:      * @param callable|null $callback The callback to invoke that builds the plugin routes.
1158:      *   Only required when $options is defined
1159:      * @return void
1160:      */
1161:     public static function plugin($name, $options = [], $callback = null)
1162:     {
1163:         if ($callback === null) {
1164:             $callback = $options;
1165:             $options = [];
1166:         }
1167:         $params = ['plugin' => $name];
1168:         if (empty($options['path'])) {
1169:             $options['path'] = '/' . Inflector::underscore($name);
1170:         }
1171:         if (isset($options['_namePrefix'])) {
1172:             $params['_namePrefix'] = $options['_namePrefix'];
1173:         }
1174:         static::scope($options['path'], $params, $callback);
1175:     }
1176: 
1177:     /**
1178:      * Get the route scopes and their connected routes.
1179:      *
1180:      * @return \Cake\Routing\Route\Route[]
1181:      */
1182:     public static function routes()
1183:     {
1184:         if (!static::$initialized) {
1185:             static::_loadRoutes();
1186:         }
1187: 
1188:         return static::$_collection->routes();
1189:     }
1190: 
1191:     /**
1192:      * Get the RouteCollection inside the Router
1193:      *
1194:      * @return \Cake\Routing\RouteCollection
1195:      */
1196:     public static function getRouteCollection()
1197:     {
1198:         return static::$_collection;
1199:     }
1200: 
1201:     /**
1202:      * Set the RouteCollection inside the Router
1203:      *
1204:      * @param RouteCollection $routeCollection route collection
1205:      * @return void
1206:      */
1207:     public static function setRouteCollection($routeCollection)
1208:     {
1209:         static::$_collection = $routeCollection;
1210:         static::$initialized = true;
1211:     }
1212: 
1213:     /**
1214:      * Loads route configuration
1215:      *
1216:      * @deprecated 3.5.0 Routes will be loaded via the Application::routes() hook in 4.0.0
1217:      * @return void
1218:      */
1219:     protected static function _loadRoutes()
1220:     {
1221:         static::$initialized = true;
1222:         include CONFIG . 'routes.php';
1223:     }
1224: }
1225: 
Follow @CakePHP
#IRC
OpenHub
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Logos & Trademarks
  • Community
  • Team
  • Issues (Github)
  • YouTube Channel
  • Get Involved
  • Bakery
  • Featured Resources
  • Newsletter
  • Certification
  • My CakePHP
  • CakeFest
  • Facebook
  • Twitter
  • Help & Support
  • Forum
  • Stack Overflow
  • IRC
  • Slack
  • Paid Support

Generated using CakePHP API Docs