执行 bin/magento setup:di:compile 时出现 Cannot instantiate interface Vendor\Module\Api\Data\RuleInterface。直观含义是 Object Manager 需要创建接口,却没有可实例化实现;真正原因可能是 preference 缺失、配置放错 area,或构造参数把数据接口当服务对象注入。

从谁要求实例化接口开始

bin/magento setup:di:compile -vvv 2>&1 | tee /tmp/di-compile.log
grep -Rni 'RuleInterface' app/code vendor/*/*/etc | head -n 100
grep -Rni 'function __construct' app/code/Vendor/Module | head -n 50

异常最后一行只是接口名。向上找第一个自定义类,确认它为何直接依赖该接口。Data Interface 通常由 Factory 或 Repository 返回,不应直接注入单个数据实例。

// 容易触发实例化接口
public function __construct(VendorModuleApiDataRuleInterface $rule) {}

// 需要新对象时注入工厂
public function __construct(
    VendorModuleApiDataRuleInterfaceFactory $ruleFactory
) {
    $this->ruleFactory = $ruleFactory;
}

服务接口需要全局 preference

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
 <preference for="VendorModuleApiRuleManagementInterface"
             type="VendorModuleModelRuleManagement" />
</config>

全局服务放在 etc/di.xml。若 preference 只在 etc/frontend/di.xml,CLI 编译或 Cron 看不到。只有确实需要不同 area 实现时才拆分。

实现类是否真的可实例化

  • 文件与类名大小写一致;
  • 没有漏写接口方法;
  • 构造函数的新依赖也能解析;
  • 所属模块已启用;
  • Composer autoload 能找到命名空间。
composer dump-autoload -o
bin/magento module:status Vendor_Module
php -r "require 'app/bootstrap.php'; var_dump(class_exists('Vendor\Module\Model\RuleManagement'));"

清生成代码不是第一步

旧生成代码可能干扰,但清 generated 只应发生在代码和 DI 配置正确之后。在维护窗口保存错误日志,再清理目标目录:

rm -rf generated/code/Vendor generated/metadata/*
bin/magento setup:di:compile

最后运行真正使用该服务的 CLI、后台页面或 API。编译成功只证明依赖图能生成,不证明业务实现与 area 行为正确。

检查编译环境是否加载了完整模块集合

构建机若缺少仅在生产安装的私有包,config.php 却启用了对应模块,也会表现为接口实现消失。比较 composer.lock、vendor/composer/installed.php 与 app/etc/config.php,确保编译发生在与运行环境一致的依赖集合中。

composer show vendor/module-name
grep -n "Vendor_Module" app/etc/config.php
sha256sum composer.lock

如果只有 production mode 编译失败,而 developer mode 页面暂时能打开,仍不能跳过编译上线。Developer mode 可能延迟到运行时才解析依赖,把故障推迟到某个低频接口。