浏览代码

Allow setting default route class.

ADmad 11 年之前
父节点
当前提交
a15c2c42fa

+ 16 - 8
src/Routing/RouteBuilder.php

@@ -16,8 +16,8 @@ namespace Cake\Routing;
 
 use BadMethodCallException;
 use Cake\Core\App;
-use Cake\Routing\Route\Route;
 use Cake\Routing\Router;
+use Cake\Routing\Route\Route;
 use Cake\Utility\Inflector;
 use InvalidArgumentException;
 
@@ -339,12 +339,16 @@ class RouteBuilder {
  */
 	protected function _makeRoute($route, $defaults, $options) {
 		if (is_string($route)) {
-			$routeClass = 'Cake\Routing\Route\Route';
+			$routeClass = Router::defaultRouteClass();
 			if (isset($options['routeClass'])) {
-				$routeClass = App::className($options['routeClass'], 'Routing/Route');
+				$routeClass = $options['routeClass'];
 			}
-			if ($routeClass === false) {
-				throw new InvalidArgumentException(sprintf('Cannot find route class %s', $options['routeClass']));
+			$class = App::className($routeClass, 'Routing/Route');
+			if ($class === false) {
+				throw new InvalidArgumentException(sprintf(
+					'Cannot find route class %s',
+					$routeClass
+				));
 			}
 			unset($options['routeClass']);
 
@@ -367,7 +371,7 @@ class RouteBuilder {
 			$defaults += $this->_params;
 			$defaults += ['plugin' => null];
 
-			$route = new $routeClass($route, $defaults, $options);
+			$route = new $class($route, $defaults, $options);
 		}
 
 		if ($route instanceof Route) {
@@ -515,8 +519,12 @@ class RouteBuilder {
  * @return void
  */
 	public function fallbacks() {
-		$this->connect('/:controller', ['action' => 'index'], ['routeClass' => 'InflectedRoute']);
-		$this->connect('/:controller/:action/*', [], ['routeClass' => 'InflectedRoute']);
+		$routeClass = Router::defaultRouteClass();
+		if ($routeClass === 'Cake\Routing\Route\Route') {
+			$routeClass = 'InflectedRoute';
+		}
+		$this->connect('/:controller', ['action' => 'index'], compact('routeClass'));
+		$this->connect('/:controller/:action/*', [], compact('routeClass'));
 	}
 
 }

+ 20 - 0
src/Routing/Router.php

@@ -45,6 +45,13 @@ class Router {
 	public static $initialized = false;
 
 /**
+ * Default route class.
+ *
+ * @var bool
+ */
+	protected static $_defaultRouteClass = 'Cake\Routing\Route\Route';
+
+/**
  * Contains the base string that will be applied to all generated URLs
  * For example `https://example.com`
  *
@@ -143,6 +150,19 @@ class Router {
 	protected static $_urlFilters = [];
 
 /**
+ * Get or set default route class.
+ *
+ * @param string|null $routeClass Class name.
+ * @return string|void
+ */
+	public static function defaultRouteClass($routeClass = null) {
+		if ($routeClass == null) {
+			return static::$_defaultRouteClass;
+		}
+		static::$_defaultRouteClass = $routeClass;
+	}
+
+/**
  * Gets the named route patterns for use in config/routes.php
  *
  * @return array Named route elements

+ 32 - 2
tests/TestCase/Routing/RouterTest.php

@@ -50,9 +50,8 @@ class RouterTest extends TestCase {
 	public function tearDown() {
 		parent::tearDown();
 		Plugin::unload();
-		Router::fullBaseUrl('');
-		Configure::write('App.fullBaseUrl', 'http://localhost');
 		Router::reload();
+		Router::defaultRouteClass('Cake\Routing\Route\Route');
 	}
 
 /**
@@ -2665,6 +2664,37 @@ class RouterTest extends TestCase {
 	}
 
 /**
+ * Test setting default route class.
+ *
+ * @return void
+ */
+	public function testDefaultRouteClass() {
+		Router::connect('/:controller', ['action' => 'index']);
+		$result = Router::url(['controller' => 'FooBar', 'action' => 'index']);
+		$this->assertEquals('/FooBar', $result);
+
+		// This is needed because tests/boostrap.php sets App.namespace to 'App'
+		Configure::write('App.namespace', 'TestApp');
+
+		Router::defaultRouteClass('DashedRoute');
+		Router::connect('/cake/:controller', ['action' => 'cake']);
+		$result = Router::url(['controller' => 'FooBar', 'action' => 'cake']);
+		$this->assertEquals('/cake/foo-bar', $result);
+
+		$result = Router::url(['controller' => 'FooBar', 'action' => 'index']);
+		$this->assertEquals('/FooBar', $result);
+
+		Router::reload();
+		Router::defaultRouteClass('DashedRoute');
+		Router::scope('/', function($routes) {
+			$routes->fallbacks();
+		});
+
+		$result = Router::url(['controller' => 'FooBar', 'action' => 'index']);
+		$this->assertEquals('/foo-bar', $result);
+	}
+
+/**
  * Connect some fallback routes for testing router behavior.
  *
  * @return void

+ 20 - 0
tests/test_app/TestApp/Routing/Route/DashedRoute.php

@@ -0,0 +1,20 @@
+<?php
+namespace TestApp\Routing\Route;
+
+use Cake\Routing\Route\InflectedRoute;
+
+class DashedRoute extends InflectedRoute {
+
+	protected function _underscore($url) {
+		$url = parent::_underscore($url);
+
+		if (!empty($url['controller'])) {
+			$url['controller'] = str_replace('_', '-', $url['controller']);
+		}
+		if (!empty($url['plugin'])) {
+			$url['plugin'] = str_replace('_', '-', $url['plugin']);
+		}
+		return $url;
+	}
+
+}