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.8 Red Velvet API

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