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

Symfony应用PHP代码更新未生效,求助排查及解决办法

Symfony代码更新后浏览器无法加载变更的问题排查与解决

问题描述

更新Symfony应用的PHP代码后,浏览器无法看到变更,尝试以下操作均无效:

  • 执行php bin/console cache:clear清除缓存
  • 删除var/cache/目录
  • 通过控制台或浏览器执行opcache_reset();apcu_clear_cache();清除Opcache

即使在控制器中添加以下代码,网站仍返回旧文件内容,新增代码完全不执行:

<?php
echo '!!!';
exit;

但修改Twig文件可正常生效。

可疑点

1. Opcache及preload.php配置

当前php.ini相关配置如下:

opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=2
opcache.fast_shutdown=1
opcache.enable_cli=1
opcache.preload=/var/www/html/config/preload.php
opcache.preload_user=www-data

2. Symfony请求缓存实现

应用使用Symfony请求缓存,示例控制器代码如下:

class HomepageController extends AbstractController
{
    private const MAX_LIMIT_ARTICLES_PER_CATEGORY = 9;

    public function __invoke(Request $request): Response
    {
        $articles = [];
        // get articles from database... (removed)

        $response = new Response();
        $content = $this->renderView('Website/homepage.html.twig', ['articles' => $articles]);

        $response->setPublic();
        $response->setEtag(md5($content));

        if ($response->isNotModified($request)) {
            return $response;
        }

        $response->setContent($content);

        return $response;
    }
}

即使在该控制器中添加exit语句也不生效,仍返回旧内容。

补充信息

将.env.local中APP_DEBUG=false时,更新的PHP文件可正常加载;改回APP_DEBUG=true则问题重现。

原因分析

  1. Opcache预加载的核心问题:启用opcache.preload后,指定的preload.php会在PHP服务启动时将相关文件预加载到内存中,这些文件会常驻内存,不受常规opcache_reset()或文件删除操作影响。而APP_DEBUG=true时,Symfony会生成带调试标记的缓存文件,但预加载的是旧版本的文件,导致新代码无法被加载。
  2. 请求缓存并非根本原因:虽然控制器中使用了Etag缓存,但新增的exit语句未执行,说明请求根本未进入控制器逻辑,排除Symfony请求缓存的影响,问题出在PHP字节码缓存层面。

解决方案

针对Opcache预加载问题

  • 彻底解决方法:重启PHP-FPM(或Apache/Nginx对应的PHP服务),这会清除所有预加载的文件,让PHP重新加载更新后的代码。
  • 批量验证缓存文件(非预加载场景):若未启用预加载,可使用opcache_invalidate()函数批量验证文件,示例代码如下:
<?php
$directory = new RecursiveDirectoryIterator('/var/www/html/src');
$iterator = new RecursiveIteratorIterator($directory);
foreach ($iterator as $file) {
    if ($file->isFile() && $file->getExtension() === 'php') {
        opcache_invalidate($file->getPathname(), true);
    }
}

注意:该方法对预加载的文件无效,因为预加载文件不受opcache_invalidate()影响,必须重启服务。

调试模式下的临时优化

在开发环境中,建议关闭opcache.preload,或者设置opcache.validate_timestamps=1并将opcache.revalidate_freq设为0,确保PHP每次请求都检查文件更新:

opcache.validate_timestamps=1
opcache.revalidate_freq=0

内容的提问来源于stack exchange,提问作者Wojciech A.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 19:25:20