ThinkPHP 开发完整教程
ThinkPHP 是一个开源的、快速、简单的面向对象的轻量级 PHP 开发框架,遵循 Apache2 开源协议发布,是为了敏捷 Web 应用开发和简化企业级应用开发而诞生的。
本教程将分为以下几个部分:
- 第一章:环境准备与安装
- PHP 环境要求
- 安装 ThinkPHP
- 验证安装
- 第二章:目录结构与核心概念
- 项目目录结构详解
- MVC 架构模式
- 路由
- 控制器
- 视图
- 模型
- 第三章:数据库操作
- 配置数据库连接
- 创建数据表
- 模型定义
- 增删改查 操作
- 查询构造器
- 第四章:视图与模板引擎
- 模板文件定义
- 变量输出
- 模板标签
- 条件判断与循环
- 包含与继承
- 第五章:表单与数据验证
- 创建表单
- 接收表单数据
- 数据验证
- 数据入库
- 第六章:实战案例:简易留言板
- 需求分析
- 数据库设计
- 功能实现
- 完整代码示例
- 第七章:进阶与学习资源
- 配置文件
- 中间件
- 规范与最佳实践
- 官方文档与社区
第一章:环境准备与安装
PHP 环境要求
ThinkPHP 对 PHP 版本有基本要求,目前最新版本(如 ThinkPHP 8.0)通常要求 PHP 7.2.5 或更高版本,推荐使用 PHP 8.x 以获得最佳性能和特性支持。
你需要一个 PHP 运行环境,最常见的选择是:
- 集成环境包(推荐新手):
- phpStudy (Windows): 功能强大,集成度高。
- MAMP (macOS): 官方稳定,易于使用。
- XAMPP (跨平台): 老牌集成环境。
- 手动安装:通过包管理器(如 Homebrew)或源码编译安装 Nginx/Apache + MySQL + PHP。
安装 ThinkPHP
ThinkPHP 提供了多种安装方式,最推荐的是使用 Composer。
什么是 Composer? Composer 是 PHP 的依赖管理工具,它允许你声明项目所依赖的库,并帮你把它们安装到你的项目中。
安装步骤:
-
安装 Composer:
- 如果你的环境中没有 Composer,请访问 getcomposer.org 下载并安装。
- 重要:安装时请务必选择 "Add to PATH" 选项,以便在命令行中直接使用
composer命令。
-
使用 Composer 创建项目:
- 打开你的终端(命令行工具)。
- 切换到你希望存放项目的目录(
D:\www或/var/www/html)。 - 执行以下命令,这将创建一个名为
myapp的新项目,并下载最新版本的 ThinkPHP:composer create-project topthink/think myapp
- 等待 Composer 自动下载所有依赖,这可能需要几分钟时间。
-
项目目录结构: 安装完成后,你的
myapp目录结构如下:myapp ├── app # 应用目录 │ ├── controller # 控制器目录 │ ├── model # 模型目录 │ └── view # 视图目录 ├── config # 配置目录 ├── public # WEB 访问目录(入口文件) ├── route # 路由目录 ├── runtime # 运行时目录(日志、缓存等) ├── vendor # Composer 依赖目录 └── think # 命令行工具
验证安装
ThinkPHP 默认安装后,有一个简单的欢迎页面。
-
配置虚拟主机(推荐):
- 在你的 Web 服务器(Nginx/Apache)中,将网站根目录指向
myapp/public目录。 - Nginx 配置示例:
server { listen 80; server_name myapp.com; # 替换成你的域名 root "D:/www/myapp/public"; # 指向 public 目录 index index.php index.html; location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=$1 last; break; } } location ~ \.php { fastcgi_pass 127.0.0.1:9000; # 你的 PHP-FPM 地址 fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } - Apache 配置:确保开启了
mod_rewrite模块,并创建一个.htaccess文件在public目录下(ThinkPHP 已自带)。
- 在你的 Web 服务器(Nginx/Apache)中,将网站根目录指向
-
直接访问:
-
如果你没有配置虚拟主机,可以直接通过 URL 访问:
http://localhost/你的项目路径/myapp/public/ -
ThinkPHP 8.0 默认路由是关闭的,所以直接访问根目录可能会看到欢迎页,如果看不到,尝试访问:
http://localhost/你的项目路径/myapp/public/index.php -
看到 "ThinkPHP" 欢迎页面或 "欢迎使用 ThinkPHP!" 字样,说明安装成功!
-
第二章:目录结构与核心概念
项目目录结构详解
app/: 应用的核心目录,大部分业务代码都在这里。controller/: 控制器,负责接收请求、调用模型、返回响应。model/: 模型,负责与数据库交互,处理数据。view/: 视图,负责展示数据,即 HTML 模板。
config/: 配置文件目录,存放数据库、路由、应用等配置。public/: 对外访问的目录,存放入口文件index.php、静态资源(CSS, JS, 图片)。route/: 路由定义目录,可以在这里定义 URL 到控制器的映射。runtime/: 运行时目录,存放日志、缓存、会话等,需要设置 Web 服务器可写权限。vendor/: Composer 依赖库,不要手动修改。think/: 命令行工具,用于命令行操作。
MVC 架构模式
ThinkPHP 遵循经典的 MVC 设计模式:
- Model (模型):代表数据和业务逻辑,在 ThinkPHP 中,模型通常对应数据库中的一张表,负责数据的增删改查。
- View (视图):负责数据的展示,通常是 HTML 文件,但也可以是 JSON、XML 等,视图从模型获取数据并呈现给用户。
- Controller (控制器):是模型和视图之间的协调者,它接收用户的请求(例如通过 URL),调用相应的模型处理数据,然后将处理结果传递给视图进行渲染,最后返回给用户。
流程:用户请求 -> Controller -> 调用 Model 获取数据 -> Controller 将数据传递给 View -> View 渲染成页面 -> 返回给用户。
路由
路由是 URL 到具体控制器方法的映射,ThinkPHP 的路由非常灵活。
-
定义路由:在
route/app.php文件中定义。// 基本路由 use think\facade\Route; Route::get('hello', 'index/hello'); // 访问 /hello 会执行 Index 控制器的 hello 方法 Route::post('save', 'index/save'); // 访问 /save 且为 POST 请求 -
URL 访问:在 ThinkPHP 8.0 中,默认开启了路由,所以访问
http://your-domain/hello就会匹配到上面的路由。
控制器
控制器是业务逻辑的核心。
-
创建控制器:在
app/controller目录下创建一个 PHP 文件,Index.php。// app/controller/Index.php namespace app\controller; use think\Request; use think\facade\View; class Index { public function hello($name = 'ThinkPHP') { // 向模板传值 View::assign('name', $name); // 渲染模板 return View::fetch(); } } -
方法:控制器中的每一个公共方法都可以通过路由访问。
视图
视图负责展示数据。
- 创建视图文件:在
app/view目录下创建与控制器和方法对应的目录和文件,上面的hello方法对应的视图文件是app/view/index/hello.html。<!-- app/view/index/hello.html --> <!DOCTYPE html> <html> <head> <title>你好</title> </head> <body> <h1>Hello, {$name}!</h1> </body> </html> - 模板引擎语法:
{$name}:输出变量。{volist name="list" id="vo"}:循环遍历数组。
模型
模型用于操作数据库。
-
创建模型:在
app/model目录下创建一个 PHP 文件,User.php。// app/model/User.php namespace app\model; use think\Model; class User extends Model { // 设置数据表名(如果与模型名不同) protected $name = 'user'; // 设置主键 protected $pk = 'id'; // 设置字段信息(可选) protected $schema = [ 'id' => 'int', 'name' => 'string', 'email' => 'string', 'create_time' => 'datetime', 'update_time' => 'datetime', ]; } -
使用模型:在控制器中调用模型。
use app\model\User; $user = User::find(1); echo $user->name;
第三章:数据库操作
配置数据库连接
在 config/database.php 文件中配置你的数据库信息。
// config/database.php
return [
// 默认使用的数据库连接配置
'default' => env('database.driver', 'mysql'),
// 自定义时间查询规则
'time_query_rule' => [],
// 自动写入时间戳字段
'auto_timestamp' => true,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
// 数据库连接配置信息
'connections' => [
'mysql' => [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => env('database.hostname', '127.0.0.1'),
// 数据库名
'database' => env('database.database', 'test'),
// 用户名
'username' => env('database.username', 'root'),
// 密码
'password' => env('database.password', 'root'),
// 端口
'hostport' => env('database.hostport', '3306'),
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8mb4
'charset' => env('database.charset', 'utf8mb4'),
// 数据库表前缀
'prefix' => env('database.prefix', ''),
],
],
];
提示:ThinkPHP 支持使用
.env文件来管理环境变量,更安全方便。
创建数据表
在你的 MySQL 数据库中创建一个表,user 表。
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL COMMENT '用户名', `email` varchar(100) NOT NULL COMMENT '邮箱', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `email` (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
模型定义
参考上一节的“模型”部分,创建 app/model/User.php 文件。
增删改查 操作
在控制器中,你可以非常方便地进行 CRUD 操作。
// app/controller/User.php
namespace app\controller;
use app\model\User;
use think\facade\View;
class User
{
// 查询所有用户
public function index()
{
$users = User::select(); // select() 查询所有
View::assign('users', $users);
return View::fetch();
}
// 查询单个用户
public function read($id)
{
$user = User::find($id); // find() 查询单个
if (!$user) {
return '用户不存在';
}
View::assign('user', $user);
return View::fetch();
}
// 新增用户
public function save()
{
// 从请求中获取数据
$data = request()->post();
// 使用模型创建并保存
$user = User::create($data);
return '用户创建成功,ID: ' . $user->id;
}
// 更新用户
public function update($id)
{
$user = User::find($id);
if (!$user) {
return '用户不存在';
}
// 获取要更新的数据
$data = request()->put();
// 保存
$user->save($data);
return '用户更新成功';
}
// 删除用户
public function delete($id)
{
$user = User::find($id);
if (!$user) {
return '用户不存在';
}
$user->delete();
return '用户删除成功';
}
}
查询构造器
除了模型提供的静态方法,你还可以使用查询构造器进行更复杂的查询。
// 在控制器方法中
use think\facade\Db; // 引入 Db 门面
// 查询 name 为 '张三' 的用户
$user = Db::name('user')->where('name', '张三')->find();
// 查询年龄大于 18 的用户数量
$count = Db::name('user')->where('age', '>', 18)->count();
// 分页查询
$list = Db::name('user')
->where('status', 1)
->order('id', 'desc')
->paginate(10); // 每页10条
// 将分页数据传递给视图
View::assign('list', $list);
Db::name('user')中的user是不带前缀的表名。
第四章:视图与模板引擎
ThinkPHP 使用内置的模板引擎,语法简单易学。
模板文件定义
模板文件存放在 app/view 目录下,目录结构与控制器对应。app/controller/User.php 控制器的 index 方法的模板文件是 app/view/user/index.html。
变量输出
-
简单变量:
{$name} -
数组变量:
// 控制器中 $data = ['name' => 'Tom', 'age' => 20]; View::assign('data', $data); // 模板中 姓名:{$data.name} 或 {$data['name']}<br> 年龄:{$data.age} -
对象属性:
// 控制器中 $user = User::find(1); View::assign('user', $user); // 模板中 用户名:{$user.name}
模板标签
- 注释:
{-- 这是注释内容 --}
条件判断与循环
-
if条件:{if condition="$age gt 18"} <p>已成年</p> {else /} <p>未成年</p> {/if}gt: 大于 (>)lt: 小于 (<)eq: 等于 ()neq: 不等于 ()
-
volist循环:{volist name="users" id="vo"} <p>ID: {$vo.id}, 姓名: {$vo.name}</p> {/volist}name: 循环的变量名。id: 循环中每个元素的临时变量名。
包含与继承
-
包含子模板:
{include file="public/header" /},常用于包含页头、页脚。 -
模板继承:用于构建基础布局页面。
-
定义基础模板 (
app/view/layout/base.html):<!DOCTYPE html> <html> <head> <title>{block name="title"}默认标题{/block}</title> </head> <body> {include file="public.header" /} <div class="content"> {block name="content"}这里是默认内容{/block} </div> {include file="public.footer" /} </body> </html> -
继承并填充内容 (
app/view/user/index.html):{extend name="layout/base" /} {block name="title"}用户列表{/block} {block name="content"} <h1>用户列表</h1> {volist name="users" id="vo"} <p>{$vo.name}</p> {/volist} {/block}
-
第五章:表单与数据验证
创建表单
在视图中创建一个表单。
<!-- app/view/user/create.html -->
<form action="{:url('user/save')}" method="post">
<div>
<label for="name">用户名:</label>
<input type="text" id="name" name="name" required>
</div>
<div>
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" required>
</div>
<button type="submit">提交</button>
</form>
{:url('user/save')}是 ThinkPHP 的 URL 生成助手,会自动根据路由配置生成正确的 URL。
接收表单数据
在控制器中,使用 request() 门面来获取数据。
// app/controller/User.php
use think\facade\Request;
public function save()
{
// 获取所有 POST 数据
$data = Request::post();
// ... 数据验证 ...
// 保存数据
try {
User::create($data);
return '创建成功';
} catch (\Exception $e) {
return '创建失败: ' . $e->getMessage();
}
}
数据验证
ThinkPHP 提供了强大的数据验证功能,有两种主要方式:
控制器内验证(简单)
public function save()
{
$data = Request::post();
$validate = new \think\Validate([
'name' => 'require|max:25',
'email' => 'require|email|unique:user',
]);
if (!$validate->check($data)) {
return $validate->getError(); // 返回第一个错误信息
}
// 验证通过,保存数据
User::create($data);
return '创建成功';
}
使用验证器(推荐,更规范)
-
创建验证器类:在
app目录下创建validate目录,然后创建User.php。// app/validate/User.php namespace app\validate; use think\Validate; class User extends Validate { protected $rule = [ 'name' => 'require|max:25', 'email' => 'require|email|unique:user', ]; protected $message = [ 'name.require' => '用户名不能为空', 'name.max' => '用户名最多不能超过25个字符', 'email.require' => '邮箱不能为空', 'email.email' => '邮箱格式不正确', 'email.unique' => '邮箱已存在', ]; } -
在控制器中使用验证器
// app/controller/User.php use app\validate\User; public function save() { $data = Request::post(); $validate = new User; if (!$validate->check($data)) { return $validate->getError(); } // 验证通过,保存数据 User::create($data); return '创建成功'; }
第六章:实战案例:简易留言板
让我们用学到的知识来做一个简单的留言板。
需求分析
- 留言列表页:展示所有留言。
- 发表留言页:一个表单,用于输入留言内容并提交。
- 数据存储:留言内容、作者、发布时间。
数据库设计
创建一个 message 表。
CREATE TABLE `message` ( `id` int(11) NOT NULL AUTO_INCREMENT, `author` varchar(50) NOT NULL COMMENT '留言人', `content` text NOT NULL COMMENT '留言内容', `create_time` datetime DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
功能实现
步骤 1:创建模型
app/model/Message.php
<?php
namespace app\model;
use think\Model;
class Message extends Model
{
protected $name = 'message';
}
步骤 2:创建控制器
app/controller/Message.php
<?php
namespace app\controller;
use app\model\Message;
use think\facade\View;
use think\facade\Request;
class Message
{
// 留言列表
public function index()
{
// 按创建时间倒序查询
$list = Message::order('create_time', 'desc')->select();
View::assign('list', $list);
return View::fetch();
}
// 显示发表留言页面
public function create()
{
return View::fetch();
}
// 处理留言提交
public function save()
{
$data = Request::only(['author', 'content']); // 只获取这两个字段
// 数据验证
$validate = new \think\Validate([
'author' => 'require|max:20',
'content' => 'require|min:5',
]);
if (!$validate->check($data)) {
return $validate->getError();
}
// 添加创建时间
$data['create_time'] = date('Y-m-d H:i:s');
// 保存
Message::create($data);
// 跳转到留言列表页
return redirect('@message/index')->with('success', '留言成功!');
}
}
步骤 3:创建视图
-
列表页
app/view/message/index.html<!DOCTYPE html> <html> <head> <title>留言板</title> <style>body { font-family: sans-serif; }</style> </head> <body> <h1>留言板</h1> <a href="{:url('message/create')}">发表新留言</a> <hr> {volist name="list" id="msg"} <div style="border: 1px solid #ccc; padding: 10px; margin-bottom: 10px;"> <p><strong>{$msg.author}</strong> @ {$msg.create_time}</p> <p>{$msg.content}</p> </div> {/volist} </body> </html> -
发表页
app/view/message/create.html<!DOCTYPE html> <html> <head> <title>发表留言</title> </head> <body> <h1>发表留言</h1> {if session('success')} <p style="color: green;">{session('success')}</p> {/if} <form action="{:url('message/save')}" method="post"> <div> <label for="author">昵称:</label> <input type="text" id="author" name="author" required> </div> <div> <label for="content">内容:</label> <textarea id="content" name="content" rows="5" required></textarea> </div> <button type="submit">提交</button> </form> </body> </html>
步骤 4:配置路由
在 route/app.php 中添加路由,让 URL 更友好。
use think\facade\Route;
// 留言板相关路由
Route::get('message', 'Message/index');
Route::get('message/create', 'Message/create');
Route::post('message', 'Message/save'); // 提交表单用 POST
你可以通过访问 /message 来查看留言板,通过 /message/create 来发表留言了。
第七章:进阶与学习资源
配置文件
ThinkPHP 的配置非常灵活,所有配置都在 config 目录下,你可以通过修改这些文件来改变框架的行为,例如数据库、缓存、会话、日志等,也可以在应用中动态修改配置。
中间件
中间件是在请求到达控制器之前或响应返回给客户端之前执行的一段代码,常用于用户认证、权限控制、日志记录等,你可以创建一个 Auth 中间件来检查用户是否登录。
规范与最佳实践
- 命名空间:遵循 PSR-4 自动加载规范,文件名和类名保持一致。
- 控制器:尽量保持控制器“瘦”,只负责流程控制和调用模型/服务,复杂的业务逻辑应放到服务层或模型中。
- 安全:永远不要直接相信用户输入,对数据进行严格的过滤和验证,防止 SQL 注入、XSS 攻击等。
- 代码风格:遵循 PSR-12 编码规范,保持代码整洁。
官方文档与社区
- ThinkPHP 官方文档:https://www.kancloud.cn/manual/thinkphp6_0/content
- 这是最重要的学习资源详尽,更新及时,遇到任何问题,第一反应应该是查阅官方文档。
- ThinkPHP 论坛:https://forum.thinkphp.cn/
官方社区,可以提问、交流、分享。
- GitHub:https://github.com/top-think/think
框架源码,适合深入研究框架原理的开发者。
这份教程涵盖了 ThinkPHP 开发的核心内容,从零开始,由浅入深,祝你学习愉快,开发顺利!
