app('cache') 更安全,走容器 make() 流程,保证单例、动态适配配置;app()->cache 直接读属性,未注册时报错、可能重复实例化、绕过容器生命周期,仅适用于 provider 已加载的内部调用。
cache有什么区别">
app('cache') 是容器解析,app()->cache 是属性访问
两者表面都拿到缓存实例,但底层机制完全不同:app('cache') 走服务容器的 make() 流程,触发绑定逻辑、单例判断、依赖注入;而 app()->cache 是直接读取 Application 实例上的 cache 属性——这个属性只在 CacheServiceProvider 注册后才被设置,且不经过容器解析链。
app()->cache 在未注册前会报错 Class 'cache' not found
常见于命令行或早期启动阶段(比如在 AppServiceProvider::register() 里就调用):app()->cache 会尝试访问一个尚未赋值的属性,PHP 报 Undefined property: Illuminate\Foundation\Application::$cache 或更隐蔽的 Target class [cache] does not exist(因 Laravel 的魔术方法兜底失败)。而 app('cache') 即使在 provider 注册前调用,只要容器已初始化,就能按需触发 CacheServiceProvider::register() 并完成绑定。
单例行为不一致:app('cache') 保证单例,app()->cache 可能重复实例化
app('cache') 始终受容器 singleton 绑定控制($this->app->singleton('cache', ...)),多次调用返回同一实例;app()->cache 则是“取属性值”,如果该属性曾被手动赋值过(比如测试中写了 app()->cache = new FileStore(...)),后续再读就是那个值,完全绕过容器生命周期。容易导致:
- 测试环境 mock 失效(改了
app()->cache但没清容器缓存) - 多线程/并发请求中意外共享非线程安全的缓存驱动实例
- 升级 Laravel 后行为突变(新版可能延迟初始化该属性)
config:cache 后 app()->cache 可能失效
执行 php artisan config:cache 后,CacheServiceProvider 的注册时机和配置读取方式发生变化。某些自定义驱动若在 register() 阶段依赖未缓存的 config('cache.stores.redis'),会导致 app()->cache 属性设为空或错误实例;而 app('cache') 因每次调用都重新走完整解析流程,反而能动态适配缓存后的配置。
真正关键的不是写法短不短,而是你是否清楚自己在绕过容器还是依赖容器——多数时候,app('cache') 更安全,app()->cache 只适合确定 provider 已加载、且需要极轻微开销的内部调用场景。

















