自定义模块写了 preference,setup:di:compile 也成功,但断点始终进不到新类。这个问题先问一句:调用方实际请求的类型,真的是你替换的接口或类吗?
用最终 DI 配置验证,不要凭文件名猜
php bin/magento dev:di:info 'Magento\Vendor\Api\SomeInterface'
php bin/magento module:status Vendor_Module输出仍指向原实现,就检查 etc/di.xml、模块状态、sequence 和配置缓存。若只写在 etc/adminhtml/di.xml 或 etc/graphql/di.xml,全局调用不会读取该 area 配置。
Proxy、Factory 与 virtualType 会让你看错对象
调用方可能注入 Proxy、Factory、virtualType,或直接依赖另一个具体类。沿构造函数类型与 object manager 配置追踪实际实例,不要只在目标类构造函数打断点。已有 interceptor 时,也要看最终生成类和插件链。
generated 必须与当前代码同批生成
编译产物来自旧 release,源码来自新 release,会出现配置看起来对、运行时仍旧的混合状态。构建时清理旧 generated,安装依赖后编译,并随同一产物部署。线上不应边接流量边 compile。
如果只改一个方法行为,还应重新评估 preference 是否必要。Preference 会整体替换实现,冲突范围更大;能用 plugin、事件或组合完成时,升级风险通常更低。最终以 dev:di:info、实际实例类名和目标调用路径一致为准。

