Symfony中var目录设为符号链接在Apache下的vendor路径问题求助
环境信息
- 应用根目录:
/app var目录为符号链接,指向:/contents/var
应用目录结构:
[...] templates var -> /contents/var vendor
问题描述
Symfony在var/cache目录生成的缓存类中包含如下代码:
include_once \dirname(__DIR__, 4).'/vendor/symfony/kernel/ErrorHandler.php';
由于PHP的__DIR__会返回符号链接的源路径(即/contents/var/cache/...),而非应用实际的路径(/app/var/cache/...),导致路径计算错误,触发以下警告:
Warning: include_once(/contents/vendor/symfony/kernel/ErrorHandler.php): Failed to open stream: No such file or directory
实际vendor目录位于/app/vendor,但缓存代码错误指向了不存在的/contents/vendor。
限制条件
GitLab环境无法修改,需在现有环境框架下解决问题。
项目composer.json内容
{ "type": "project", "license": "proprietary", "minimum-stability": "stable", "prefer-stable": true, "require": { "php": ">=8.1", "ext-ctype": "*", "ext-iconv": "*", "api-platform/core": "^3.2", "doctrine/doctrine-bundle": "^2.10", "doctrine/doctrine-migrations-bundle": "^3.2", "doctrine/orm": "^2.16", "nelmio/cors-bundle": "^2.3", "phpdocumentor/reflection-docblock": "^5.3", "phpstan/phpdoc-parser": "^1.24", "symfony/apache-pack": "^1.0", "symfony/asset": "6.3.*", "symfony/console": "6.3.*", "symfony/dotenv": "6.3.*", "symfony/expression-language": "6.3.*", "symfony/flex": "^2", "symfony/framework-bundle": "6.3.*", "symfony/property-access": "6.3.*", "symfony/property-info": "6.3.*", "symfony/runtime": "6.3.*", "symfony/security-bundle": "6.3.*", "symfony/serializer": "6.3.*", "symfony/twig-bundle": "6.3.*", "symfony/validator": "6.3.*", "symfony/yaml": "6.3.*" }, "require-dev": { "symfony/maker-bundle": "^1.51" }, "config": { "allow-plugins": { "php-http/discovery": true, "symfony/flex": true, "symfony/runtime": true }, "sort-packages": true }, "autoload": { "psr-4": { "App\\": "src/" } }, "autoload-dev": { "psr-4": { "App\\Tests\\": "tests/" } }, "replace": { "symfony/polyfill-ctype": "*", "symfony/polyfill-iconv": "*", "symfony/polyfill-php72": "*", "symfony/polyfill-php73": "*", "symfony/polyfill-php74": "*", "symfony/polyfill-php80": "*", "symfony/polyfill-php81": "*" }, "scripts": { "auto-scripts": { "cache:clear": "symfony-cmd", "assets:install %PUBLIC_DIR%": "symfony-cmd" }, "post-install-cmd": [ "@auto-scripts" ], "post-update-cmd": [ "@auto-scripts" ] }, "conflict": { "symfony/symfony": "*" }, "extra": { "symfony": { "allow-contrib": "true", "require": "6.3.*" } } }
解决方案
方法1:强制指定缓存目录路径
在项目的.env或.env.local文件中添加环境变量,明确指定缓存目录的实际路径:
APP_CACHE_DIR=/app/var/cache
或者修改config/packages/framework.yaml,直接配置缓存目录:
framework: cache: directory: '%kernel.project_dir%/var/cache'
修改后执行php bin/console cache:clear重新生成缓存,此时Symfony会以项目根目录为基准生成路径,避免符号链接的影响。
方法2:明确指定Composer的vendor目录路径
在composer.json的config节点中添加vendor-dir配置,指定vendor目录的绝对路径:
"config": { "allow-plugins": { "php-http/discovery": true, "symfony/flex": true, "symfony/runtime": true }, "sort-packages": true, "vendor-dir": "/app/vendor" }
执行composer dump-autoload更新自动加载文件,确保生成的路径指向正确的vendor目录。
方法3:在启动脚本中切换到应用根目录
在GitLab CI/CD脚本中,先切换到/app目录再执行缓存清理和启动命令:
cd /app && php bin/console cache:clear --env=prod
这样PHP的__DIR__会基于当前工作目录计算路径,避免符号链接带来的路径偏差。
内容的提问来源于stack exchange,提问作者j0nnybrav0

