Skip to content

Commit

Permalink
Fix #158: New locales based on pattern, add generateWithCurrent() (#156)
Browse files Browse the repository at this point in the history
* New locales based on pattern
* Add generateWithCurrent() method
* Update docs

Co-authored-by: Alexander Makarov <sam@rmcreative.ru>
Co-authored-by: Sergei Predvoditelev <sergey.predvoditelev@gmail.com>
  • Loading branch information
3 people committed Dec 29, 2021
1 parent 0880079 commit 645ef95
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 36 deletions.
42 changes: 25 additions & 17 deletions README.md
Expand Up @@ -167,8 +167,7 @@ Route::get('/api[/v{version}]')
->defaults(['version' => 1]);
```

In the above we specify that if version parameter is not provided during either URL matching or URL generation
explicitly then it will be `1`.
In the above we specify that if "version" is not obtained from URL during matching then it will be `1`.

Besides action, additional middleware to execute before the action itself could be defined:

Expand Down Expand Up @@ -279,13 +278,17 @@ $request = $container->get(ServerRequestFactory::class)->createFromGlobals();
$responseFactory = $container->get(ResponseFactoryInterface::class);
$notFoundHandler = new NotFoundHandler($responseFactory);
$collector = $container->get(RouteCollectorInterface::class);
$collector->addRoute(Route::get('/test/{id:\w+}')->action(static function (CurrentRoute $currentRoute, RequestHandlerInterface $next) use ($responseFactory) {
$id = $currentRoute->getArgument('id');
$response = $responseFactory->createResponse();
$response->getBody()->write('You are at test with argument ' . $id);

return $response;
})->name('test'));
$collector->addRoute(
Route::get('/test/{id:\w+}')
->action(static function (CurrentRoute $currentRoute, RequestHandlerInterface $next) use ($responseFactory) {
$id = $currentRoute->getArgument('id');
$response = $responseFactory->createResponse();
$response->getBody()->write('You are at test with argument ' . $id);

return $response;
})
->name('test')
);
$router = new UrlMatcher(new RouteCollection($collector));
$route = $router->match($request);
$response = $route->process($request, $notFoundHandler);
Expand All @@ -304,27 +307,32 @@ function getUrl(UrlGeneratorInterface $urlGenerator, $parameters = [])
}
```

### Creating locale-based URLs

Locale based URLs can be configured the following:
Absolute URL cold be generated using `UrlGeneratorInterface::generateAbsolute()`:

```php
use Yiisoft\Router\UrlGeneratorInterface;

$urlGenerator->setLocales(['en' => 'en-US', 'ru' => 'ru-RU', 'uz' => 'uz-UZ']);
$urlGenerator->setLocaleParameterName('_locale');
function getUrl(UrlGeneratorInterface $urlGenerator, $parameters = [])
{
return $urlGenerator->generateAbsolute('test', $parameters);
}
```

Then that is how locale URL could be obtained for it:
Also, there is a handy `UrlGeneratorInterface::generateFromCurrent()` method. It allows generating a URL that is
a modified version of the current URL:

```php
use Yiisoft\Router\UrlGeneratorInterface;

function getLocaleUrl(UrlGeneratorInterface $urlGenerator, string $locale)
function getUrl(UrlGeneratorInterface $urlGenerator, $id)
{
return $urlGenerator->generate('test', ['_locale' => $locale]);
return $urlGenerator->generateFromCurrent(['id' => 42]);
}
```

In the above, ID will be replaced with 42 and the rest of the parameters will stay the same. That is useful for
modifying URLs for filtering and/or sorting.

## Obtaining current route information

For such a route:
Expand Down
8 changes: 8 additions & 0 deletions src/CurrentRoute.php
Expand Up @@ -26,6 +26,8 @@ final class CurrentRoute
* Current Route arguments.
*
* @var string[]
*
* @psalm-var array<string, string>
*/
private array $arguments = [];

Expand Down Expand Up @@ -83,6 +85,8 @@ public function getUri(): ?UriInterface
* @param Route $route
* @param string[] $arguments
*
* @psalm-param array<string,string> $arguments
*
* @internal
*/
public function setRouteWithArguments(Route $route, array $arguments): void
Expand All @@ -109,6 +113,10 @@ public function setUri(UriInterface $uri): void
throw new LogicException('Can not set URI since it was already set.');
}

/**
* @return string[] Arguments.
* @psalm-return array<string, string>
*/
public function getArguments(): array
{
return $this->arguments;
Expand Down
3 changes: 3 additions & 0 deletions src/MatchingResult.php
Expand Up @@ -18,6 +18,7 @@ final class MatchingResult implements MiddlewareInterface

/**
* @var string[]
* @psalm-var array<string,string>
*/
private array $arguments = [];

Expand All @@ -42,6 +43,7 @@ public function withDispatcher(MiddlewareDispatcher $dispatcher): self

/**
* @param string[] $arguments
* @psalm-param array<string,string> $arguments
*/
public static function fromSuccess(Route $route, array $arguments): self
{
Expand Down Expand Up @@ -75,6 +77,7 @@ public function isMethodFailure(): bool

/**
* @return string[]
* @psalm-return array<string,string>
*/
public function arguments(): array
{
Expand Down
6 changes: 4 additions & 2 deletions src/Route.php
Expand Up @@ -6,6 +6,7 @@

use InvalidArgumentException;
use RuntimeException;
use Stringable;
use Yiisoft\Http\Method;
use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher;

Expand Down Expand Up @@ -38,6 +39,7 @@ final class Route

/**
* @var string[]
* @psalm-var array<string,string>
*/
private array $defaults = [];

Expand Down Expand Up @@ -208,7 +210,7 @@ public function override(): self
*
* @param array $defaults
*
* @psalm-param array<string,null|object|scalar> $defaults
* @psalm-param array<string,null|Stringable|scalar> $defaults
*
* @return self
*/
Expand Down Expand Up @@ -306,7 +308,7 @@ public function disableMiddleware(...$middlewareDefinition): self
* T is ('name'|'pattern') ? string :
* (T is 'host' ? string|null :
* (T is 'methods' ? array<array-key,string> :
* (T is 'defaults' ? string[] :
* (T is 'defaults' ? array<string,string> :
* (T is ('override'|'hasMiddlewares'|'hasDispatcher') ? bool :
* (T is 'dispatcherWithMiddlewares' ? MiddlewareDispatcher : mixed)
* )
Expand Down
53 changes: 36 additions & 17 deletions src/UrlGeneratorInterface.php
Expand Up @@ -4,54 +4,73 @@

namespace Yiisoft\Router;

use Stringable;

/**
* UrlGeneratorInterface allows generating URL given route name and parameters.
* It is preferred to type-hint against it in case you need to generate a URL.
* UrlGeneratorInterface allows generating URL given route name, arguments, and query parameters.
*/
interface UrlGeneratorInterface
{
/**
* Generates URL from named route and parameters.
* Generates URL from named route, arguments, and query parameters.
*
* @param string $name Name of the route.
* @param array $parameters Parameter-value set.
*
* @throws RouteNotFoundException In case there is no route with the name specified.
* @param array $arguments Argument-value set.
* @param array $queryParameters Parameter-value set.
*
* @return string URL generated.
*
* @psalm-param array<string,null|object|scalar> $parameters
* @psalm-param array<string,null|Stringable|scalar> $arguments
*
* @throws RouteNotFoundException In case there is no route with the name specified.
*/
public function generate(string $name, array $parameters = []): string;
public function generate(string $name, array $arguments = [], array $queryParameters = []): string;

/**
* Generates absolute URL from named route and parameters.
* Generates absolute URL from named route, arguments, and query parameters.
*
* @param string $name Name of the route.
* @param array $parameters Parameter-value set.
* @param array $arguments Argument-value set.
* @param array $queryParameters Parameter-value set.
* @param string|null $scheme Host scheme.
* @param string|null $host Host for manual setup.
*
* @throws RouteNotFoundException In case there is no route with the name specified.
*
* @return string URL generated.
*
* @psalm-param array<string,null|object|scalar> $parameters
* @psalm-param array<string,null|Stringable|scalar> $arguments
*/
public function generateAbsolute(
string $name,
array $parameters = [],
array $arguments = [],
array $queryParameters = [],
string $scheme = null,
string $host = null
): string;

/**
* Generate URL from the current route replacing some of its arguments with values specified.
*
* @param array $replacedArguments New argument values indexed by replaced argument names.
* @param string|null $fallbackRouteName Name of a route that should be used if current route
* can not be determined.
*
* @psalm-param array<string,null|Stringable|scalar> $replacedArguments
*/
public function generateFromCurrent(array $replacedArguments, ?string $fallbackRouteName = null): string;

public function getUriPrefix(): string;

public function setUriPrefix(string $name): void;

public function getLocales(): array;

public function setLocales(array $locales): void;

public function setLocaleParameterName(string $localeParameterName): void;
/**
* Set default argument value.
*
* @param string $name Name of argument to provide default value for.
* @param mixed $value Default value.
*
* @psalm-param null|Stringable|scalar $value
*/
public function setDefaultArgument(string $name, $value): void;
}

0 comments on commit 645ef95

Please sign in to comment.