So, I have several subdomains for my project with mezzio framework (zend expressive):
How can I use it in routes?
This example does not work:
$app->get('journal.example.com', Journal\Handler\HomePageHandler::class, 'journal.home');
This answer provides a solution to the question of routing requests to subdomains to a specific RequestHandler. However, is not a good practice, since it introduces difficulties like the overhead in routes configuration and maintaining two routes configurations. In addition, it does not solve the subdomain-specific path routing (eg http://journal.example.com/new or http://journal.example.com/list ).
Using the same application across various subdomains can mean challenges in session handling and so forth. Using the same domain for one application makes these issues obsolete.
Since routes are not aware of the host, a plain solution in the routes configuration is not possible. It can be achieved by using a routing middleware.
Define routes in config/autoload/subdomain-routes.global.php
<?php
declare(strict_types=1);
return [
'subdomain_routes' => [
'mezzio-subdomains.localhost' => \App\Handler\HomePageHandler::class,
'account.mezzio-subdomains.localhost' => \Account\Handler\HomepageHandler::class,
'journal.mezzio-subdomains.localhost' => \Journal\Handler\HomepageHandler::class,
],
];
The routing middleware uses a SuperFactory src/App/Service/SuperFactory.php
to retrieve the services from the container.
<?php
declare(strict_types=1);
namespace App\Service;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use Psr\Container\ContainerInterface;
use Psr\Http\Server\RequestHandlerInterface;
class SuperFactory
{
private ContainerInterface $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function create(string $serviceClass) : RequestHandlerInterface
{
if ($this->container->has($serviceClass)) {
return $this->container->get($serviceClass);
}
throw new ServiceNotFoundException(sprintf(
'Unable to resolve service "%s" to a factory; are you certain you provided it during configuration?',
$serviceClass
));
}
}
The routing middleware src/App/Middleware/SubdomainRouter.php
returns the response of the RequestHandler, if a matching subdomain is found.
<?php
declare(strict_types=1);
namespace App\Middleware;
use App\Service\SuperFactory;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class SubdomainRouter implements MiddlewareInterface
{
private array $subdomainRoutes;
private SuperFactory $superFactory;
public function __construct(array $subdomainRoutes, SuperFactory $superFactory)
{
$this->subdomainRoutes = $subdomainRoutes;
$this->superFactory = $superFactory;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
{
$host = $request->getUri()->getHost();
if (array_key_exists($host, $this->subdomainRoutes)) {
$handler = $this->superFactory->create($this->subdomainRoutes[$host]);
return $handler->handle($request);
}
return $handler->handle($request);
}
}
The routing middleware must be placed in the pipeline before Mezzio\Router\Middleware\RouteMiddleware
.
// [..]
// Add this line
$app->pipe(App\Middleware\SubdomainRouter::class);
// The following route is already defined in the skeleton
$app->pipe(RouteMiddleware::class);
// [..]
Now requests to http://mezzio-subdomains.localhost/ , http://account.mezzio-subdomains.localhost/ and http://journal.mezzio-subdomains.localhost/ are routed as configured.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.