PAYATHON 2026

Shopware 6 安装或更新插件时,如何检查并处理插件依赖?

数据阿明

Shopware 6 会校验插件依赖,但 Composer 下载了依赖包,并不意味着 Shopware 已递归安装并激活这些依赖插件。对于这条依赖链,应显式声明插件依赖,并按 PluginAaaa → PluginBbbb → PluginCccc 的顺序执行插件生命周期操作。

对于“依赖未激活,PluginCccc 仍能成功激活”的情况,需要结合具体 Shopware 版本和插件配置排查。现有材料缺少版本号、各插件的 composer.json 和异常堆栈,无法直接认定这是框架缺陷。

Composer 依赖与插件状态有什么区别?

Composer 负责包的下载、版本约束和自动加载配置。Shopware 中的插件安装、数据库迁移、激活及服务注册属于插件生命周期。文件存在,并不表示插件提供的服务已经进入当前应用的服务容器。Shopware 插件文档也分别介绍了通过 Composer 引入插件以及安装、激活插件的步骤。

这两种异常需要分开排查:

  • PluginBbbbBlahBlah::SAMPLE_CONST 引用失败:检查具体异常,确认是否属于类无法自动加载、命名空间错误或版本不匹配。单纯引用类常量,不足以证明必须激活插件。
  • 构造函数注入 PluginAaaaBlahBlah 失败:即使类能自动加载,对应服务仍可能没有注册,需要检查依赖插件状态和服务定义。

先检查依赖是否声明在插件自身的配置中

只在项目根目录通过 Composer 引入三个插件,不能完整表达它们之间的依赖关系。依赖应写在各插件自己的 composer.json 的 require 中,使用目标插件的 Composer 包名,也就是 name 字段,而不是插件技术名称或 PHP 类名。Shopware 依赖声明文档

例如,假设三个包名分别为 example/plugin-aaaa、example/plugin-bbbb 和 example/plugin-cccc,PluginBbbb 的配置片段可以是:

{
  "require": {
    "example/plugin-aaaa": "^1.0"
  }
}

PluginCccc 的配置片段可以是:

{
  "require": {
    "example/plugin-bbbb": "^1.0",
    "example/plugin-aaaa": "^1.0"
  }
}

问题中还出现了直接注入 PluginAaaa 类的代码。如果这段代码确实位于 PluginCccc,建议像示例中这样,将 PluginAaaa 也声明为直接依赖。

这些只是合并到现有配置中的示例片段。包名和 ^1.0 都需要替换为实际值,并保留原有的其他必需配置。

为什么需要核对 Shopware 版本?

在目前可查的 Shopware trunk 源码中,对 Composer 管理的插件,RequirementsValidator::validateRequirements() 会在非激活阶段提前返回,激活阶段仍会执行依赖校验。用于判断插件依赖是否满足的查询同时要求 installedAt 非空、active = true。RequirementsValidator 源码

PluginLifecycleService::activatePlugin() 的默认执行路径也会调用该校验器。PluginLifecycleService 源码

因此,安装和激活阶段的行为可能不同,不能笼统地说 Shopware 完全不检查依赖。上述源码属于开发分支,不能直接代表问题所用版本。排查时应对照安装版本检查:

  1. PluginBbbb 和 PluginCccc 各自的 require 是否完整。
  2. 依赖包名是否与目标插件的 name 完全一致,包类型是否正确声明为 shopware-platform-plugin。
  3. plugin:list 中三个插件的安装、激活和版本状态是否符合预期。
  4. 实际命令是否走了默认激活流程,是否存在定制代码绕过校验。

如何先安装并激活依赖插件?

如果三个插件都尚未安装,可以在项目根目录按顺序执行独立命令:

#!/usr/bin/env bash
set -e

php bin/console plugin:refresh
php bin/console plugin:install --activate PluginAaaa
php bin/console plugin:install --activate PluginBbbb
php bin/console plugin:install --activate PluginCccc
php bin/console plugin:list

set -e 让脚本在某一步返回失败状态时停止,避免继续处理后续插件。每个插件单独启动一次命令,也便于下一步使用前一步完成后的插件和容器状态。

如果插件已经安装但未激活,应根据实际状态使用 plugin:activate。更新已有插件时,要执行相应的 plugin:update,不能用再次安装代替更新流程。

自动部署时,可以由部署脚本解析插件自身的 require,建立依赖图,按拓扑顺序执行安装、更新和激活。Shopware 官方关于部署工具的说明也采用了依赖排序的方式。Shopware 部署依赖排序说明

如何在依赖不满足时阻止操作?

先修正依赖声明,并确认当前版本自带的激活校验能够生效。如果业务还要求“依赖未激活时,连安装也必须禁止”,可以增加明确的前置检查。

检查逻辑应至少包括:

  1. 找到 PluginAaaa 和 PluginBbbb 的插件记录。
  2. 确认 installedAt 非空,且 active 为 true。
  3. 检查其版本是否满足要求。
  4. 任一条件不满足时,抛出带有依赖名称和处理建议的异常。

只放在部署脚本中的检查,仅覆盖该部署入口。如果还要覆盖后台和其他调用入口,可以结合实际版本提供的 PluginPreInstallEvent、PluginPreActivateEvent、PluginPreUpdateEvent 等生命周期事件实现拦截;事件顺序和可用上下文应对照该版本源码确认。生命周期服务源码

这类检查器自身应只依赖 Shopware 核心服务,避免注入尚未激活的依赖插件服务,否则可能在输出友好提示之前就发生容器错误。自动安装依赖更适合交给统一部署流程,以便明确控制顺序和失败处理。

备注:内容仅供参考。