PHP兼容APCu与OPcache的关键是抽象用户缓存层:优先检测APCu,fallback至APC,禁用直接调用apc_或opcache_函数;OPcache仅缓存opcode,不提供用户数据缓存能力,二者职责分离。

PHP 同时兼容 APC(用户缓存)和 OPcache(字节码缓存)的关键在于:**不直接调用 apc_store 或 opcache_get_status,而是用抽象层隔离底层扩展差异**。APC 自 PHP 5.5 起已废弃,且 APCu(仅用户缓存)与 OPcache(仅 opcode 缓存)是两个独立扩展,不能混用同一套 API。
判断当前可用的用户缓存扩展
APCu 和 APC 的函数名高度重合(如 apc_store、apc_fetch),但 APCu 是 APC 的用户缓存子集,不带 opcode 功能;而 OPcache **完全不提供用户数据缓存能力**,opcache_get_status 只能查编译缓存状态,不能存取业务数据。
所以第一步是检测哪个用户缓存扩展可用:
- 优先检查
extension_loaded('apcu')—— APCu 是现代 PHP(7.0+)推荐的用户缓存方案 - 其次 fallback 到
extension_loaded('apc')(仅 PHP 5.4 及更早,且需启用 user cache) -
不要检查
opcache扩展是否存在来决定用户缓存逻辑 —— 它对apc_*()函数无影响,也无对应用户存取接口
统一封装 cache_set 和 cache_get 接口
避免在业务代码里散落 apcu_store / apc_store 调用,应封装一层适配器。示例简化版:
立即学习“PHP免费学习笔记(深入)”;
function cache_get($key) {
if (extension_loaded('apcu') && function_exists('apcu_fetch')) {
return apcu_fetch($key);
}
if (extension_loaded('apc') && function_exists('apc_fetch')) {
return apc_fetch($key);
}
return false;
}
function cache_set($key, $value, $ttl = 0) {
if (extension_loaded('apcu') && function_exists('apcu_store')) {
return apcu_store($key, $value, $ttl);
}
if (extension_loaded('apc') && function_exists('apc_store')) {
return apc_store($key, $value, $ttl);
}
return false;
}
注意:apcu_store 和 apc_store 的第三个参数含义一致(秒级 TTL),但 APC 在 TTL=0 时可能永不过期,而 APCu 会使用默认过期时间(取决于 apc.ttl 配置),行为略有差异。
OPcache 不参与用户数据缓存,但需留意它的干扰项
OPcache 本身不提供键值缓存,但以下情况容易误判为“OPcache 影响了缓存逻辑”:
-
opcache.enable_cli=1在 CLI 模式下开启后,可能导致脚本重载不生效,误以为cache_set失败(实际是脚本被 OPcache 缓存,未重新解析) -
opcache.revalidate_freq=0会让文件变更不触发重编译,开发时修改 PHP 文件却看不到效果,容易怀疑缓存写入失败 - 调用
opcache_invalidate()或opcache_reset()对用户缓存(APCu/APC)**完全无效**,它们只清 opcode 缓存
生产环境建议配置组合
PHP 7.0+ 应明确禁用 APC(已移除),只启用 APCu + OPcache:
- 确保
extension=apcu.so(Linux)或extension=php_apcu.dll(Windows)已加载 - 确认
apc.enabled=1未出现在 php.ini 中(APCu 不读这个配置) - OPcache 启用:设置
opcache.enable=1,并调优opcache.memory_consumption和opcache.max_accelerated_files - APCu 可选调优:
apc.shm_size=64M、apc.ttl=3600(避免大量短命 key 拖慢哈希表)
APCu 和 OPcache 共存无冲突,但它们解决的是不同层面的问题:一个缓业务数据,一个缓 PHP 脚本编译结果。混淆二者职责,是兼容写法出错的最常见根源。











