Symfony从2.8升级到3.4后Twig的absolute_url生成错误URL
这个问题本质是Symfony 3.4对absolute_url()的依赖逻辑做了调整,和2.8版本的处理方式不一样了,我来拆解下:
核心原因
在Symfony 2.8里,absolute_url()会直接基于当前HTTP请求的实际访问路径来拼接完整URL——因为你的应用部署在/feature-abc/子目录下,请求的base URL自然包含这个路径,所以生成的绝对URL没问题。
但升级到3.4后,absolute_url()不再直接从当前请求取base路径,而是依赖框架配置的request_context.base_url参数。如果你的部署环境没有正确配置这个参数,框架就会默认使用根路径(/)来拼接绝对URL,自然就丢失了feature-abc这个子目录。
而asset()之所以还正常,是因为它的路径生成逻辑主要依赖framework.assets相关配置,和router的request context不是同一个体系,所以没受影响。
解决办法
根据你的部署场景,选下面一种方式配置即可:
1. 配置router的request context
在app/config/config.yml(或者对应环境的配置文件,比如config_prod.yml)里添加router的base_url配置:
framework: router: context: base_url: '/feature-abc'
这个配置会告诉框架,应用的基础路径是/feature-abc,absolute_url()生成URL时就会自动带上这个前缀。
2. 直接配置assets的基础URL
如果希望asset()和absolute_url()都统一基于部署的子目录,可以直接在assets配置里指定完整的基础URL:
framework: assets: base_urls: ['http://integration/feature-abc']
这样不管是asset('/image.png')还是absolute_url(asset('/image.png')),都会生成包含子目录的正确URL。
3. CLI场景下手动设置上下文
如果你的应用有命令行任务(比如定时脚本)需要生成绝对URL,还要额外在app/AppKernel.php里初始化请求上下文:
protected function initializeContainer() { parent::initializeContainer(); // 针对CLI环境手动设置base URL if (PHP_SAPI === 'cli') { $this->getContainer()->get('router')->getContext()->setBaseUrl('/feature-abc'); } }
因为CLI环境没有HTTP请求,框架无法自动识别部署路径,必须手动指定。
内容的提问来源于stack exchange,提问作者dz46

