Yii2模块化需按业务域而非技术层划分,每个模块自治、可测试、可独立演进;模块间通过事件、接口契约或HTTP调用通信;配置、迁移、数据库均须模块内聚隔离。

Yii2模块化不是“加个文件夹就完事”,而是围绕业务边界做清晰切分,同时守住单体应用的协作效率底线。重构的关键不在拆得多细,而在每个模块是否真正自治、可测试、可独立演进。
按业务域而非技术层划分模块
避免把“Controller”“Model”“View”机械地按功能类型拆开。正确做法是识别核心业务实体与流程,例如电商系统中:
- 订单模块:包含订单创建、状态流转、退款逻辑、关联的订单模型和管理视图
- 商品模块:覆盖SKU管理、分类树、库存校验、详情页渲染
- 用户中心模块:聚合登录、资料编辑、收货地址、积分账户,不拆成“AuthModule”+“ProfileModule”
每个模块内部保持完整MVC结构,控制器命名空间明确指向自身(如 app\modules\order\controllers\OrderController),避免跨模块调用模型或服务类。
模块间通信必须收敛、可控
禁止在A模块控制器里直接写 Yii::$app->getModule('user')->findIdentity($id)。推荐三种安全方式:
-
事件总线:用
yii\base\Event发布/监听业务事件(如OrderPlacedEvent),由监听器触发用户积分更新 -
接口契约:在
common/interfaces下定义UserQueryService接口,订单模块只依赖接口,具体实现由用户模块提供并注册到DI容器 -
HTTP轻量调用:仅限跨库或强隔离场景,通过 Guzzle 调用
/api/v1/users/{id},配合缓存与熔断
模块配置与参数必须内聚
模块专属配置不能塞进主应用的 params.php。应在模块根目录下建 config/ 子目录,并在 Module.php 的 init() 中加载:
public function init()
{
parent::init();
$this->params = array_merge(
require __DIR__ . '/config/params.php',
YII_ENV_DEV ? require __DIR__ . '/config/params-local.php' : []
);
}
访问时统一用 $this->params['order.auto_cancel_hours'],不走 Yii::$app->params 全局池,防止命名冲突与环境误覆盖。
迁移与数据库必须模块隔离
每个模块应有自己独立的 migration 目录和执行路径:
- 迁移文件放在
modules/order/migrations/ - 执行命令限定作用域:
php yii migrate --migrationPath=@order/migrations - 数据库连接若需分离,应在模块配置中显式指定新组件名(如
'db_order' => [...]),并在模块内通过Yii::$app->get('db_order')获取,绝不复用主db组件
这样即使未来要分库,也只需改模块配置,不影响其他模块运行。


















