简体   繁体   中英

Mezzio: How can I use subdomains in routes?

So, I have several subdomains for my project with mezzio framework (zend expressive):

  • example.com
  • journal.example.com
  • account.example.com

How can I use it in routes?

This example does not work:

$app->get('journal.example.com', Journal\Handler\HomePageHandler::class, 'journal.home');

Disclaimer

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.

Possible solution

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.

Subdomain routes configuration

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,
    ],
];

Routing middleware

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);
    }
}

Pipeline

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);
// [..]

Finish

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM