ThinkPHP面试题及答案(实战版)
一、基础概念与框架特性
问题:ThinkPHP5、6、8三个版本的核心差异是什么?实际项目中怎么选版本?
答案:
TP5是LTS版本(长期支持),兼容PHP5.6+,文档最完善,但没有内置容器和注解;
TP6要求PHP7.1+,引入了PSR规范容器、注解路由、中间件机制,重构了ORM,不过不再支持PHP5;
TP8是2024年新出的,要求PHP8.0+,优化了性能(比如减少反射调用),支持原生PHP枚举,还修复了TP6的一些老bug。
选版本看两点:一是服务器PHP版本(老服务器跑不了TP8),二是项目复杂度——简单CRUD用TP5够了,中大型项目要用到容器、注解就选TP6/8,新项目优先TP8(毕竟后续维护更久)。
问题:ThinkPHP的入口文件作用是什么?多应用模式下入口文件怎么配置?
答案:
入口文件(通常是public/index.php)是请求的唯一入口,主要做三件事:定义应用目录、加载框架引导文件、启动应用。
多应用模式(比如前台home、后台admin)不用改入口文件,只要在config/app.php里把app_multi_module设为true,然后在app目录下建home、admin两个子目录,每个目录里放自己的controller、model,访问时用URL区分(比如域名/home/index/index、域名/admin/index/login)。如果想做独立入口(比如admin单独用admin.php),可以复制index.php改名为admin.php,在里面加一句define(APP_MODULE,admin)指定默认应用。
二、路由与URL
问题:ThinkPHP的路由有哪几种定义方式?实际开发中怎么避免路由冲突?
答案:
常用三种:静态路由(比如about=index/about)、动态路由(比如user/:id=user/detail,:id是参数)、注解路由(TP6+支持,在控制器方法上写/**@route(user/info)*/)。
避免冲突有两个技巧:一是加路由分组,比如后台路由都放admin/分组下(Route::group(admin,function(){...})),前台路由不加前缀,自然区分;二是限定参数规则,比如动态路由user/:id可以加-pattern([id=\d+]),只匹配数字ID,避免和其他字符串路由冲突(比如user/add就不会被当成id=add)。
问题:URL重写怎么配置?为什么要做URL重写?
答案:
目的是去掉URL里的index.php(比如从域名/index.php/home/index变成域名/home/index),更友好也利于SEO。
配置分两步:一是服务器配置(以Nginx为例),在vhost配置里加try_filesuriuri//index.phpis_argsargs;Apache要开启mod_rewrite,加.htaccess文件;二是ThinkPHP里把config/app.php的url_html_suffix设为空(默认有.html后缀,可去掉)。
注意:如果是Windows本地用WAMP,要先在Apache的httpd.conf里把LoadModulerewrite_module前面的#去掉,不然重写不生效。
三、模型与ORM
问题:模型的关联查询(hasOne、hasMany、belongsTo)怎么用?举个实际业务场景例子。
答案:
比如用户表(user)、用户资料表(user_profile,存昵称、头像)、订单表(order):
user和user_profile是一对一(hasOne):user表有id,user_profile有user_id外键。在User模型里写publicfunctionprofile(){returnthis-hasOne(UserProfile::class,user_id,id);},查用户时用User::with(profile)-find(id)就能一起查出资料,避免多表查两次。
user和order是一对多(hasMany):order表有user_id,User模型里写publicfunctionorders(){returnthis-hasMany(Order::class,user_id,id);}