You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony 5白标路由动态处理方案技术咨询

Symfony 5 动态白标(Whitelabel)路由解决方案

方案一:自定义路由加载器(推荐,适配Bundle架构)

通过扩展Symfony的路由加载机制,自动为每个白标复制主路由并生成带前缀的路由,支持从配置或数据库动态获取白标列表,无需硬编码。

步骤1:创建自定义RouteLoader

在你的Bundle中实现路由加载器类:

// src/YourBundle/Loader/WhitelabelRouteLoader.php
namespace YourBundle\Loader;

use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Loader\LoaderResolverInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Routing\Loader\AnnotationClassLoader;
use Symfony\Component\Routing\Annotation\RouteAnnotationReader;

class WhitelabelRouteLoader implements LoaderInterface
{
    private $loaded = false;
    private $params;

    public function __construct(ParameterBagInterface $params)
    {
        $this->params = $params;
    }

    public function load($resource, $type = null)
    {
        if ($this->loaded) {
            throw new \RuntimeException('该加载器已执行过加载操作');
        }

        $routeCollection = new RouteCollection();
        // 加载主控制器的注解路由
        $mainRoutes = $this->importMainRoutes();
        // 从配置获取白标列表(可替换为数据库查询逻辑)
        $whitelabels = $this->params->get('your_bundle.whitelabels');

        // 为每个白标生成对应路由
        foreach ($whitelabels as $label) {
            foreach ($mainRoutes as $routeName => $route) {
                if (str_starts_with($routeName, 'mainlabel_')) {
                    $newRouteName = str_replace('mainlabel_', "{$label}_", $routeName);
                    // 生成白标路由路径,可根据需求调整格式
                    $newPath = "/{$label}" . preg_replace('#^/mainlabel#', '', $route->getPath());

                    $newRoute = clone $route;
                    $newRoute->setPath($newPath);
                    $newRoute->setDefault('whitelabel', $label);

                    $routeCollection->add($newRouteName, $newRoute);
                }
            }
        }

        $this->loaded = true;
        return $routeCollection;
    }

    private function importMainRoutes()
    {
        $loader = new AnnotationClassLoader(new RouteAnnotationReader());
        // 替换为你的主控制器目录
        return $loader->load(__DIR__ . '/../Controller/MainController.php');
    }

    public function supports($resource, $type = null)
    {
        return $type === 'whitelabel';
    }

    public function getResolver() { return null; }
    public function setResolver(LoaderResolverInterface $resolver) {}
}

步骤2:注册路由加载器

在Bundle的services.yaml中配置:

# src/YourBundle/Resources/config/services.yaml
services:
    YourBundle\Loader\WhitelabelRouteLoader:
        arguments:
            $params: '@parameter_bag'
        tags:
            - { name: routing.loader }

步骤3:配置白标列表

在Bundle配置文件中添加白标配置:

# config/packages/your_bundle.yaml
your_bundle:
    whitelabels: ['whitelabel_alpha', 'whitelabel_beta', 'whitelabel_gamma']

步骤4:加载自定义路由

在config/routes.yaml中引入:

# config/routes.yaml
your_bundle_whitelabel_routes:
    resource: .
    type: whitelabel

方案二:动态路由前缀+请求事件监听

无需生成大量路由,通过统一前缀占位符+事件验证白标合法性,适合路由数量较多的场景。

步骤1:添加带白标前缀的路由

修改主控制器的路由注解:

// src/YourBundle/Controller/MainController.php
/**
 * @Route("/{whitelabel}/test", name="whitelabel_test")
 * @Route("/mainlabel/test", name="mainlabel_test")
 * @return Response
 */
public function test(Request $request, string $whitelabel = null)
{
    if ($whitelabel) {
        // 处理白标专属逻辑
    }
    // 原有业务逻辑
}

步骤2:创建请求事件监听器

验证白标合法性:

// src/YourBundle/EventListener/WhitelabelListener.php
namespace YourBundle\EventListener;

use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class WhitelabelListener
{
    private $params;

    public function __construct(ParameterBagInterface $params)
    {
        $this->params = $params;
    }

    public function onKernelRequest(RequestEvent $event)
    {
        $request = $event->getRequest();
        $whitelabel = $request->get('whitelabel');

        if (!$whitelabel) return;

        $validWhitelabels = $this->params->get('your_bundle.whitelabels');
        if (!in_array($whitelabel, $validWhitelabels)) {
            throw new NotFoundHttpException('无效的白标标识');
        }

        // 将白标信息存入请求属性,供后续控制器使用
        $request->attributes->set('whitelabel', $whitelabel);
    }
}

步骤3:注册事件监听器

# src/YourBundle/Resources/config/services.yaml
services:
    YourBundle\EventListener\WhitelabelListener:
        arguments:
            $params: '@parameter_bag'
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

解决现有转发方案的问题:通过路由名获取控制器

如果坚持使用转发控制器,可通过RouterInterface获取路由对应的控制器信息:

use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Routing\Exception\RouteNotFoundException;

// 在控制器中注入RouterInterface
public function whitelabelForward(Request $request, RouterInterface $router)
{
    $whitelabel = $request->attributes->get('whitelabel');
    $action = $request->attributes->get('action');
    $id = $request->attributes->get('id');

    $mainRouteName = 'mainlabel' . ($action ? "_$action" : '');
    $params = $id ? ['id' => $id] : [];

    try {
        $route = $router->getRouteCollection()->get($mainRouteName);
        if (!$route) throw new RouteNotFoundException();

        $controllerStr = $route->getDefault('_controller');
        // 解析控制器字符串
        if (is_array($controllerStr)) {
            [$controllerClass, $controllerMethod] = $controllerStr;
        } else {
            [$controllerClass, $controllerMethod] = explode('::', $controllerStr);
        }

        return $this->forward("$controllerClass::$controllerMethod", array_merge($params, [
            'whitelabel' => $whitelabel,
        ]));
    } catch (RouteNotFoundException $e) {
        throw new NotFoundHttpException();
    }
}

注意:生产环境路由集合会被缓存,新增白标后需执行bin/console cache:clear清除缓存。

内容的提问来源于stack exchange,提问作者StevieStef

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 01:22:03