Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/Illuminate/Foundation/Console/RouteListCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class RouteListCommand extends Command
*
* @var string[]
*/
protected $headers = ['Domain', 'Method', 'URI', 'Name', 'Action', 'Middleware'];
protected $headers = ['Domain', 'Method', 'URI', 'Name', 'Action', 'Aliases', 'Middleware'];

/**
* The terminal width resolver callback.
Expand Down Expand Up @@ -144,6 +144,7 @@ protected function getRouteInformation(Route $route)
'method' => implode('|', $route->methods()),
'uri' => $route->uri(),
'name' => $route->getName(),
'aliases' => $route->getName() ? app('router')->getRouteAliasesFor($route->getName()) : [],
'action' => ltrim($route->getActionName(), '\\'),
'middleware' => $this->getMiddleware($route),
'vendor' => $this->isVendorRoute($route),
Expand Down Expand Up @@ -421,13 +422,17 @@ protected function forCli($routes)
*/
protected function formatActionForCli($route)
{
['action' => $action, 'name' => $name] = $route;
['action' => $action, 'name' => $name, 'aliases' => $aliases] = $route;

$computed_aliases = $this->option('with-aliases') && sizeof($aliases) > 0
? (' ['.implode(', ', $aliases).']')
: '';

if ($action === 'Closure' || $action === ViewController::class) {
return $name;
return $name.$computed_aliases;
}

$name = $name ? "$name " : null;
$name = $name ? "$name $computed_aliases " : null;

$rootControllerNamespace = $this->laravel[UrlGenerator::class]->getRootControllerNamespace()
?? ($this->laravel->getNamespace().'Http\\Controllers');
Expand Down Expand Up @@ -505,6 +510,7 @@ protected function getOptions()
['path', null, InputOption::VALUE_OPTIONAL, 'Only show routes matching the given path pattern'],
['except-path', null, InputOption::VALUE_OPTIONAL, 'Do not display the routes matching the given path pattern'],
['reverse', 'r', InputOption::VALUE_NONE, 'Reverse the ordering of the routes'],
['with-aliases', 'a', InputOption::VALUE_NONE, 'Show routes with aliases'],
['sort', null, InputOption::VALUE_OPTIONAL, 'The column (domain, method, uri, name, action, middleware, definition) to sort by', 'uri'],
['except-vendor', null, InputOption::VALUE_NONE, 'Do not display routes defined by vendor packages'],
['only-vendor', null, InputOption::VALUE_NONE, 'Only display routes defined by vendor packages'],
Expand Down
1 change: 1 addition & 0 deletions src/Illuminate/Routing/AbstractRouteCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ public function compile()
'lockSeconds' => $route->locksFor(),
'waitSeconds' => $route->waitsFor(),
'withTrashed' => $route->allowsTrashedBindings(),
'aliases' => app('router')->getRouteAliasesFor($route->getName()) ?? [],
];
}

Expand Down
3 changes: 2 additions & 1 deletion src/Illuminate/Routing/CompiledRouteCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,8 @@ protected function newRoute(array $attributes)
->setWheres($attributes['wheres'])
->setBindingFields($attributes['bindingFields'])
->block($attributes['lockSeconds'] ?? null, $attributes['waitSeconds'] ?? null)
->withTrashed($attributes['withTrashed'] ?? false);
->withTrashed($attributes['withTrashed'] ?? false)
->setAliases($attributes['aliases'] ?? []);
}

/**
Expand Down
38 changes: 38 additions & 0 deletions src/Illuminate/Routing/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,13 @@ class Route
*/
protected $bindingFields = [];

/**
* List of route aliases.
*
* @var array
*/
protected $aliases = [];

/**
* The validators used by the routes.
*
Expand Down Expand Up @@ -1402,6 +1409,37 @@ public function prepareForSerialization()
unset($this->router, $this->container);
}

/**
* Add an alise for the route.
*
* @return void
*/
public function addAlias(string $alias)
{
$this->aliases[] = $alias;
}

/**
* Set the aliases for the route.
*
* @param array<string> $aliases
* @return $this
*/
public function setAliases(array $aliases)
{
$this->aliases = $aliases;

return $this;
}

/**
* Get the aliases for the route.
*/
public function getAliases(): array
{
return $this->aliases;
}

/**
* Dynamically access route parameters.
*
Expand Down
66 changes: 66 additions & 0 deletions src/Illuminate/Routing/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ class Router implements BindingRegistrar, RegistrarContract
*/
protected $groupStack = [];

/**
* Store of all registered route aliases.
*
* @var array
*/
protected $routeAliases = [];

/**
* The registered custom implicit binding callback.
*
Expand Down Expand Up @@ -1461,6 +1468,15 @@ public function setCompiledRoutes(array $routes)
->setContainer($this->container);

$this->container->instance('routes', $this->routes);

foreach ($this->routes as $route) {
$aliases = $route->getAliases();
if ($name = $route->getName()) {
if (sizeof($aliases) > 0) {
$this->alias($name, $aliases);
}
}
}
}

/**
Expand Down Expand Up @@ -1499,6 +1515,56 @@ public function setContainer(Container $container)
return $this;
}

/**
* Register route aliases.
*
* @param string $originalName
* @param string|array $aliasNames
* @return void
*/
public function alias(string $originalName, string|array $aliasNames): void
{
$aliasNames = is_array($aliasNames) ? $aliasNames : [$aliasNames];

foreach ($aliasNames as $aliasName) {
$this->routeAliases[$aliasName] = $originalName;
}
}

/**
* Get all the registered route aliases.
*
* @return array
*/
public function getRouteAliases(): array
{
return $this->routeAliases;
}

/**
* Resolve alias returning the original name.
*
* @param string $name
* @return string|null
*/
public function resolveAlias(string $name): ?string
{
return $this->routeAliases[$name] ?? null;
}

/**
* Get all aliases for a given route name.
*
* @param string $originalName
* @return array
*/
public function getRouteAliasesFor(string $originalName): array
{
return array_keys(
array_filter($this->routeAliases, fn ($original) => $original === $originalName)
);
}

/**
* Dynamically handle calls into the router instance.
*
Expand Down
6 changes: 6 additions & 0 deletions src/Illuminate/Routing/UrlGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,12 @@ public function route($name, $parameters = [], $absolute = true)
throw new InvalidArgumentException('Attribute [name] expects a string backed enum.');
}

if (is_null($this->routes->getByName($name))) {
if ($resolved = app('router')->resolveAlias($name)) {
$name = $resolved;
}
}

if (! is_null($route = $this->routes->getByName($name))) {
return $this->toRoute($route, $parameters, $absolute);
}
Expand Down
1 change: 1 addition & 0 deletions src/Illuminate/Support/Facades/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
* @method static bool hasMacro(string $name)
* @method static void flushMacros()
* @method static mixed macroCall(string $method, array $parameters)
* @method static void alias(string $originalName, string|array $aliasNames)
* @method static \Illuminate\Support\HigherOrderTapProxy|\Illuminate\Routing\Router tap(callable|null $callback = null)
* @method static \Illuminate\Routing\RouteRegistrar attribute(string $key, mixed $value)
* @method static \Illuminate\Routing\RouteRegistrar whereAlpha(array|string $parameters)
Expand Down
12 changes: 6 additions & 6 deletions tests/Foundation/Console/RouteListCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public function testSortRouteListAsc()
$this->app->call('route:list', ['--json' => true, '--sort' => 'domain,uri']);
$output = $this->app->output();

$expectedOrder = '[{"domain":null,"method":"GET|HEAD","uri":"example","name":null,"action":"Closure","middleware":["exampleMiddleware"]},{"domain":null,"method":"GET|HEAD","uri":"example-group","name":null,"action":"Closure","middleware":["web","auth"]},{"domain":"sub","method":"GET|HEAD","uri":"sub-example","name":null,"action":"Closure","middleware":["exampleMiddleware"]}]';
$expectedOrder = '[{"domain":null,"method":"GET|HEAD","uri":"example","name":null,"action":"Closure","aliases": [],"middleware":["exampleMiddleware"]},{"domain":null,"method":"GET|HEAD","uri":"example-group","name":null,"action":"Closure","aliases": [],"middleware":["web","auth"]},{"domain":"sub","method":"GET|HEAD","uri":"sub-example","name":null,"action":"Closure","aliases": [],"middleware":["exampleMiddleware"]}]';

$this->assertJsonStringEqualsJsonString($expectedOrder, $output);
}
Expand All @@ -87,7 +87,7 @@ public function testSortRouteListDesc()
$this->app->call('route:list', ['--json' => true, '--sort' => 'domain,uri', '--reverse' => true]);
$output = $this->app->output();

$expectedOrder = '[{"domain":"sub","method":"GET|HEAD","uri":"sub-example","name":null,"action":"Closure","middleware":["exampleMiddleware"]},{"domain":null,"method":"GET|HEAD","uri":"example-group","name":null,"action":"Closure","middleware":["web","auth"]},{"domain":null,"method":"GET|HEAD","uri":"example","name":null,"action":"Closure","middleware":["exampleMiddleware"]}]';
$expectedOrder = '[{"domain":"sub","method":"GET|HEAD","uri":"sub-example","name":null,"action":"Closure","aliases": [],"middleware":["exampleMiddleware"]},{"domain":null,"method":"GET|HEAD","uri":"example-group","name":null,"action":"Closure","aliases": [],"middleware":["web","auth"]},{"domain":null,"method":"GET|HEAD","uri":"example","name":null,"action":"Closure","aliases": [],"middleware":["exampleMiddleware"]}]';

$this->assertJsonStringEqualsJsonString($expectedOrder, $output);
}
Expand All @@ -97,7 +97,7 @@ public function testSortRouteListDefault()
$this->app->call('route:list', ['--json' => true]);
$output = $this->app->output();

$expectedOrder = '[{"domain":null,"method":"GET|HEAD","uri":"example","name":null,"action":"Closure","middleware":["exampleMiddleware"]},{"domain":null,"method":"GET|HEAD","uri":"example-group","name":null,"action":"Closure","middleware":["web","auth"]}, {"domain":"sub","method":"GET|HEAD","uri":"sub-example","name":null,"action":"Closure","middleware":["exampleMiddleware"]}]';
$expectedOrder = '[{"domain":null,"method":"GET|HEAD","uri":"example","name":null,"action":"Closure","aliases": [],"middleware":["exampleMiddleware"]},{"domain":null,"method":"GET|HEAD","uri":"example-group","name":null,"action":"Closure","aliases": [],"middleware":["web","auth"]}, {"domain":"sub","method":"GET|HEAD","uri":"sub-example","name":null,"action":"Closure","aliases": [],"middleware":["exampleMiddleware"]}]';

$this->assertJsonStringEqualsJsonString($expectedOrder, $output);
}
Expand All @@ -107,7 +107,7 @@ public function testSortRouteListPrecedence()
$this->app->call('route:list', ['--json' => true, '--sort' => 'definition']);
$output = $this->app->output();

$expectedOrder = '[{"domain":null,"method":"GET|HEAD","uri":"example","name":null,"action":"Closure","middleware":["exampleMiddleware"]},{"domain":"sub","method":"GET|HEAD","uri":"sub-example","name":null,"action":"Closure","middleware":["exampleMiddleware"]}, {"domain":null,"method":"GET|HEAD","uri":"example-group","name":null,"action":"Closure","middleware":["web","auth"]}]';
$expectedOrder = '[{"domain":null,"method":"GET|HEAD","uri":"example","name":null,"action":"Closure","aliases": [],"middleware":["exampleMiddleware"]},{"domain":"sub","method":"GET|HEAD","uri":"sub-example","name":null,"action":"Closure","aliases": [],"middleware":["exampleMiddleware"]}, {"domain":null,"method":"GET|HEAD","uri":"example-group","name":null,"action":"Closure","aliases": [],"middleware":["web","auth"]}]';

$this->assertJsonStringEqualsJsonString($expectedOrder, $output);
}
Expand Down Expand Up @@ -181,7 +181,7 @@ public function testMiddlewareGroupsExpandCorrectlySortedIfVeryVerbose()
$this->app->call('route:list', ['--json' => true, '-vv' => true]);
$output = $this->app->output();

$expectedOrder = '[{"domain":null,"method":"GET|HEAD","uri":"example","name":null,"action":"Closure","middleware":["exampleMiddleware"]},{"domain":null,"method":"GET|HEAD","uri":"example-group","name":null,"action":"Closure","middleware":["Middleware 5","Middleware 1","Middleware 4","Middleware 2","Middleware 3"]},{"domain":"sub","method":"GET|HEAD","uri":"sub-example","name":null,"action":"Closure","middleware":["exampleMiddleware"]}]';
$expectedOrder = '[{"domain":null,"method":"GET|HEAD","uri":"example","name":null,"action":"Closure","aliases": [],"middleware":["exampleMiddleware"]},{"domain":null,"method":"GET|HEAD","uri":"example-group","name":null,"action":"Closure","aliases": [],"middleware":["Middleware 5","Middleware 1","Middleware 4","Middleware 2","Middleware 3"]},{"domain":"sub","method":"GET|HEAD","uri":"sub-example","name":null,"action":"Closure","aliases": [],"middleware":["exampleMiddleware"]}]';

$this->assertJsonStringEqualsJsonString($expectedOrder, $output);
}
Expand All @@ -191,7 +191,7 @@ public function testFilterByMiddleware()
$this->app->call('route:list', ['--json' => true, '-v' => true, '--middleware' => 'auth']);
$output = $this->app->output();

$expectedOrder = '[{"domain":null,"method":"GET|HEAD","uri":"example-group","name":null,"action":"Closure","middleware":["web","auth"]}]';
$expectedOrder = '[{"domain":null,"method":"GET|HEAD","uri":"example-group","name":null,"action":"Closure","aliases": [],"middleware":["web","auth"]}]';

$this->assertJsonStringEqualsJsonString($expectedOrder, $output);
}
Expand Down
Loading