Yii扩展目录结构需严格遵循规范:src/存PSR-4类,composer.json定义name、type为yii2-extension、autoload及Yii依赖,README.md必备;不支持自动加载非类文件;推荐分分支维护Yii2/3兼容;组件/行为需手动注册,小部件可直用;发布前须验证composer.json、安装可用性及稳定性设置。

怎么组织 Yii 扩展的目录结构
Yii 扩展不是随便放几个文件就能被识别的,核心在于 composer.json 的配置和入口点约定。没按规范组织,composer require 装上也加载不了。
必须包含这些部分:
-
src/:所有 PHP 类(如MyWidget.php、MyBehavior.php)放这里,类名需严格匹配 PSR-4 命名空间(比如"mycompany/yii2-myext": "src/") -
composer.json:至少定义name(格式必须是vendor/name)、type(固定为yii2-extension)、autoload和require(标明依赖的 Yii 版本,如"yiisoft/yii2": "~2.0.40 || ^2.1.0") -
README.md:虽然不强制,但缺它会导致 Packagist 同步失败或用户无法快速理解用途
常见错误:src/ 下直接放 index.php 或把配置文件(如 config/main.php)塞进去——Yii 不会自动加载这些,它们不属于扩展运行时逻辑。
如何让扩展支持 Yii 2 和 Yii 3 共存
别硬写两套代码。Yii 3 是完全重构,命名空间、依赖注入方式都变了,强行兼容只会让扩展越来越难维护。
更实际的做法是分分支、分包:
- 主分支(
master或main)只支持 Yii 3,用psr/container、yiisoft/di等新生态 - 单独开
2.x分支维护 Yii 2 支持,依赖仍用yiisoft/yii2 - 如果真要单包双支持,必须用条件加载:在
src/Extension.php中通过class_exists('Yii')或检查Yii::getVersion()动态返回不同实现——但这样会让测试和类型提示失效,不推荐
性能影响不大,但开发成本翻倍。多数成熟扩展(如 yii2-grid)已明确放弃双版本支持,你也不用扛这个包袱。
怎么注册组件、行为、小部件让应用能直接用
Yii 不会自动扫描扩展里的类。你得告诉框架“这个类该在哪用、怎么用”。关键靠三类注册方式:
- 组件:在扩展里提供一个配置数组(如
MyExtension::getConfig()),让用户在config/web.php的'components'里手动注册,例如:'myService' => ['class' => MyService::class] - 行为:不能自动挂载,必须由用户在目标类中显式附加,比如在
ActiveRecord子类里加behaviors()方法返回['myBehavior' => MyBehavior::class] - 小部件:只要类继承
yiiaseWidget并放在src/下,用户就能直接在视图里调用= MyWidget::widget(['option' => 1]) ?>,无需额外注册
容易踩的坑:Bootstrap 类(实现 yiiaseBootstrapInterface)看起来很酷,能自动执行初始化,但它只在应用启动时运行一次,且无法传参;多数场景下不如文档写清楚“请在 config 里配一下”来得可靠。
发布前必须验证的 3 个点
很多人本地能跑就直接 git push && composer publish,结果别人装不上。以下三项不验,90% 概率出问题:
- 运行
composer validate:检查composer.json格式是否合法、name是否符合vendor/name规则、autoload路径是否存在 - 用
composer install --no-dev在空目录下测试安装,再手动新建一个最小 Yii 2/3 应用,require你的扩展,确认new MyExtMyClass()不报Class not found - 检查
composer.json的minimum-stability:如果是dev,别人require时得加@dev后缀;想默认可用,得打正式 tag(如v1.0.0)并设"minimum-stability": "stable"
最常被忽略的是 autoload 路径拼写错误——比如 "autoload": {"psr-4": {"mycompany\myext\": "src/"} 写成 "MyCompany\MyExt\",大小写不一致在 Linux 下直接 500。










