一、前提背景
在Thinkphp框架里编写项目时,我创建了控制器Training_OthersAction.class.php
并创建了相对应的数据表,Training_Others表。
并使用以下方法,获取控制器名称,使用D方法进行模型实例化,用来更简单的获取数据表数据。
$this->getActionName();
$model = D ($name);
$list=$model->select();
后面担心在某些编译环境里,可能无法识别控制器里的下划线_,便将控制器名称和数据表名称都改为了TrainingOthers。
二、出现问题
但在后续的操作里,发现都无法获取到数据,并且直接显示系统报错,在打开debug后,显示问题是无法找到training_others数据表,该数据表不存在。
并且getActionName()获取的名字也一直是training_others,而不是我要的trainingothers。
下意识的我就判断是系统的缓存没有删除干净,就开始清除runtime文件及浏览器缓存。但问题仍然没有解决。
三、问题原因
在经过一系列的操作后,我发现该问题是因为Thinkphp框架的底层逻辑导致的。
它会自动将TrainingOthers 中间有大写字母的前面添加下划线,从而转变成
Training_others,以至于我无法找到该数据表,而显示报错。
所以只要将大写O更改为小写o,问题就自然解决了。
并且注意以后在thinkphp的框架中,少使用驼峰命名法。采取首字母大写,其它字母小写,或者下划线命名法最好。
四、底层代码解释
ThinkPHP 控制器名称转换机制
在 ThinkPHP 框架中,控制器名称 TrainingOthers
被编译后转化为小写下划线命名形式 training_others
是由于框架内部遵循了一种特定的命名规则和路径解析逻辑。这种转化主要基于 PHP 中类名到文件路径映射的需求以及框架约定优于配置的设计理念。
命名风格与路径匹配
ThinkPHP 使用的是 PSR-4 自动加载标准的一部分变体,在该标准下,类名通常采用 PascalCase 风格书写 (即首字母大写的驼峰法),而实际存储于磁盘上的文件则可能需要满足 UNIX 文件系统的大小写敏感特性。因此为了统一处理不同操作系统间对于大小写的差异性问题并简化路由解析流程中的复杂度,引入了一个中间环节——即将原始请求所指定的大写字母构成的控制器名字先转成全小字加底纹符串表示方法再做进一步查找操作。
具体来说:
- 当接收到 HTTP 请求指向某个具体的 Controller 动作时;
- 系统会依据预定义好的一套算法把 URL 参数里携带的那个部分自动调整成为适合本地环境使用的格式;比如这里提到的例子就是将原本应该是 “PascalCased”的字符串转变为“snake_cased”。
此过程不仅有助于增强跨平台兼容能力同时也方便开发者按照个人喜好来组织项目结构而不必担心因为命名习惯不一致而导致错误发生的情况出现。
// 示例代码展示如何实现此类变换功能的一个简单版本
function pascalToSnake($str){
$result = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $str));
return trim($result, "_");
}
echo(pascalToSnake("TrainingOthers")); // 输出结果为 'training_others'
以上函数演示了基本原理之一是如何通过正则表达式配合 preg_replace 函数完成从 Camel/Pascal Case 到 Snake Case 的转变工作。
总结
综上所述,ThinkPHP 将控制器名称如 TrainingOthers
编译为 training_others
主要是为了适应底层文件系统的要求、提高程序运行效率以及保持整个 MVC 架构的一致性和可维护性等方面考虑的结果。