直接用PHP写一个小页面并不困难:接收参数、查询数据库,再把结果输出到浏览器就能运行。但当项目逐渐增加登录、权限、商品、订单、接口、缓存和日志以后,如果所有代码都混在几个PHP文件里,维护很快就会变得麻烦。

ThinkPHP解决的就是这类问题。它不是一个安装之后就能直接发布文章的CMS,也不是某套固定的网站模板,而是一套PHP Web开发框架。开发者仍然需要编写自己的业务代码,只不过路由、请求处理、数据库操作、配置管理等通用工作已经有了一套相对完整的组织方式。

ThinkPHP是什么?国内常用PHP开发框架介绍

ThinkPHP到底是什么

ThinkPHP是一个开源PHP框架,当前主要版本为ThinkPHP 8系列。官方项目说明中,ThinkPHP 8基于PHP 8.0及以上环境构建,并使用Composer管理相关依赖。

如果把一个网站拆开来看,请求进入服务器以后通常要经历很多步骤:

用户访问URL
↓
路由判断请求交给谁
↓
控制器接收请求
↓
执行业务逻辑
↓
查询或写入数据库
↓
返回HTML或JSON

不用框架时,这些事情也可以自己实现;使用ThinkPHP以后,则可以按照框架已有的规则组织代码。开发人员主要把精力放在“订单怎么处理”“用户怎么登录”这类业务问题上,而不用每个项目都重新设计一遍基础结构。

先看懂ThinkPHP的项目目录

通过Composer创建一个ThinkPHP项目以后,会看到一些比较固定的目录。理解这些目录,比一开始记大量函数更有用。

目录主要用途
app应用业务代码,例如控制器、模型等
config应用配置
route路由定义
public网站公开入口及静态资源
runtime运行过程中生成的缓存、日志等数据
vendorComposer安装的框架及第三方依赖

这种结构带来的好处不是“文件看起来整齐”,而是不同职责有了相对明确的位置。接手别人项目时,至少知道路由应该去哪里找,业务控制器大致在哪里,配置也不需要散落在代码各处。

路由决定一个URL由谁处理

ThinkPHP中的路由,可以理解成URL和程序处理逻辑之间的映射。

例如希望访问:

/article/100

时读取编号为100的文章,可以为它定义对应路由,再交给文章控制器处理。

这样做以后,对外展示的URL和内部PHP文件不需要形成简单的一一对应关系。开发REST API时,也可以根据GET、POST等不同请求方式设置不同处理逻辑。

路由的价值在项目变大以后会更明显。商品、用户、订单和文章拥有各自的URL规则,比在一个入口文件中不断判断参数更容易维护。

控制器负责接住请求

路由确定目标以后,请求通常会进入控制器。控制器更像业务流程的入口:接收参数,调用需要的业务或数据逻辑,然后决定返回什么。

例如一个简单方法可能是:

public function hello($name = 'ThinkPHP')
{
    return 'Hello ' . $name;
}

实际项目当然不会这么简单。一个订单接口可能需要先检查登录状态,再验证提交参数,查询商品库存,创建订单,最后返回JSON。

需要注意的是,控制器并不适合塞进所有业务代码。项目稍微复杂一些以后,通常还会把数据库模型、服务逻辑和验证规则继续拆开,否则只是从“所有代码写在一个PHP文件”变成“所有代码写在一个控制器”。

数据库和ORM是ThinkPHP常用的一部分

Web项目很难绕过数据库。ThinkPHP生态中的ThinkORM负责数据库与ORM相关能力,可以通过查询构造器或模型完成常见的数据操作。

例如查询一个用户,可以写成类似:

$user = Db::name('user')
    ->where('id', 100)
    ->find();

相比自己拼接SQL,这种写法在大量常规增删改查场景中更容易统一代码风格。

进一步使用模型以后,还可以把用户、文章、订单等业务实体单独组织起来,处理字段转换、关联关系和数据操作。

不过ORM也不是要求开发者从此完全不懂SQL。遇到复杂查询、索引设计、慢查询和大数据量处理时,数据库本身的知识仍然非常重要。框架减少的是重复代码,而不是替代数据库能力。

中间件适合处理重复的请求逻辑

很多网站都有一些几乎每个接口都需要做的事情,例如检查用户是否登录、记录请求日志、判断接口访问频率或者统一增加响应信息。

如果在每个控制器里都写一遍,不但重复,而且以后修改规则时容易漏掉。ThinkPHP提供中间件机制,可以在请求正式进入业务逻辑前后统一处理这些事情。

例如后台管理系统可以让一组路由统一经过身份认证中间件。认证失败直接返回登录提示,通过以后才进入具体控制器。

这类机制也是使用框架和“几个PHP文件直接写到底”之间比较明显的区别。框架真正提供的是一套组织大型代码的办法。

不只有传统MVC网站

早期接触ThinkPHP的人,经常会把它和MVC联系在一起:Model负责数据,View负责页面,Controller负责请求。

这个理解没有问题,但现在使用ThinkPHP并不意味着一定要采用传统的服务端模板网站。

例如Vue、React或者小程序负责前端界面,ThinkPHP只提供JSON API,这时项目可能几乎不使用传统View层。后台管理系统、移动端接口、企业内部系统和前后端分离项目,都可以使用同一套框架基础能力。

所以ThinkPHP更准确的理解应该是PHP后端开发框架,而不是“用来套HTML模板的工具”。

为什么不少国内PHP项目选择它

ThinkPHP的一个现实特点,是中文资料和国内开发生态比较成熟。很多CMS、商城、后台系统以及企业项目曾经或者仍然建立在ThinkPHP之上,因此国内PHP开发人员接手已有项目时,经常会碰到它。

框架本身也提供了Web项目中经常需要的路由、中间件、请求与响应、配置、日志、缓存、验证以及数据库相关基础设施,不需要为了每个常见需求重新选择一套完全不同的实现。

当前ThinkPHP 8要求PHP 8.0及以上版本,官方后续8.1.x更新还在继续改进路由、请求响应以及ORM,并增加了对较新PHP版本的兼容。

对于已经熟悉PHP语法,又希望从零散PHP脚本进入结构化项目开发的人,ThinkPHP的学习路线也比较直观:先学路由和控制器,再理解请求、数据库、模型、中间件和验证,基本就能够开始完成普通业务系统。

参考资料

  1. ThinkPHP官方网站

  2. ThinkPHP 8 GitHub项目

  3. ThinkPHP核心框架仓库

  4. ThinkPHP官方开发文档