ThinkPHP目录结构严格遵循“命名空间路径=文件系统路径”原则:app下模块目录(如admin)须全小写,controller/model等子目录必须小写,类文件名须驼峰且与类名一致;public为唯一Web入口,config不可置于public内;多应用模式下各子目录需独立配置app_namespace。

ThinkPHP 项目目录结构不是“怎么好看怎么来”,而是直接决定自动加载是否生效、调试时错误是否可定位、上线后能否跨平台稳定运行。核心原则就一条:命名空间路径 = 文件系统路径,差一个字母或大小写,class not found 就立刻报给你看。
为什么 App\Controller\User 必须对应 app/controller/User.php
ThinkPHP(5/6/8)依赖 PSR-4 自动加载,框架通过命名空间字符串拼出文件路径。比如你写 new App\Controller\User(),它会按规则去拼:
- 把
App替换为APP_PATH(通常是app/) - 把
\转成/,得到app/controller/User.php - 然后检查这个路径是否存在、是否可读
一旦你把文件放在 app/controller/user.php(小写 u),或者类名写成 user,Linux 下直接 500;Windows 下即使能跑,开启 APP_DEBUG 也会报错。这不是 bug,是设计使然。
app/ 目录里哪些子目录必须小写?哪些必须驼峰?
目录名本身不参与类加载,但影响可维护性和团队协作。官方规范明确要求:
-
app/下的模块目录(如index、admin)全部小写 + 下划线,不能驼峰 —— 因为它们是路由和分组标识,不是命名空间一部分 -
app/index/controller/这种层级里的controller、model、view必须小写,这是固定约定,改了Loader就不认识 - 真正参与命名空间的只有类文件名:比如
UserController.php(首字母大写)、BaseModel.php,且文件内 class 名必须完全一致
常见踩坑:app/index/Controller/User.php(大写 Controller)—— 框架默认只认小写的 controller 目录,除非你手动重定义 app_namespace 配置。
config/ 和 public/ 的位置能不能动?
可以动,但动法有硬约束:
-
public/是 Web 可访问根目录,必须包含入口文件(如index.php)。你可以把它改成web/或html/,但入口文件中require的 ThinkPHP 核心路径、以及APP_PATH定义都得同步改 -
config/默认在项目根目录下,但 ThinkPHP 8 支持通过config_path配置项指定任意路径,只要is_dir()返回 true 且 PHP 有读取权限 - 千万别把
config/放进public/—— 里面可能有数据库密码,Web 直接可访问就等于裸奔
一个典型安全配置:config/ 和 app/ 并列放在 Web 不可达的上层目录,public/ 单独一层,入口文件用 __DIR__.'/../config/' 加载配置。
模块分组(app/admin/)和多应用(app/api/)怎么避免命名冲突?
ThinkPHP 6+ 的多应用模式下,每个子目录(如 api、admin)都是独立应用,各自有完整的 controller、model 目录。关键点在于:
- 每个子目录下的
config/app.php必须设置'app_namespace' => 'app\api'(对应目录名小写),否则命名空间解析会错乱 - 路由定义时,
api组的控制器要写成app\api\controller\User,不能漏掉api\这一级 - 如果用了多应用,
app/目录本身不再放公共控制器,所有逻辑必须收敛到各子应用内,否则route:list命令会混掉
最容易被忽略的是:多应用模式下,app/common 公共目录不会被自动加载,必须手动在 composer.json 中声明 autoload PSR-4 映射,否则 Common\Service\Upload 这类类永远找不到。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











