重构《我讨厌PHP-PHP和MySQL初学者指南》第三版
《我讨厌PHP-PHP和MySQL初学者指南》
作者:Geticer 2022-2026
# 前言
## 首先,我的背景和为什么会有这本书?
我写代码有年头了。从最早的HTML表格布局,到后来的CSS,再到各种后端语言。PHP?说实话,第一次见到它的时候,我的反应是:“这玩意儿语法怎么这么奇怪?”
但你知道吗?就像那个总爱迟到却总能完成任务的同学一样,PHP虽然有时候让人头疼,但它确实能干活。而且干得还不错。
这本书不是那种正襟危坐的技术手册。我们不会从“PHP的历史与发展”开始(那太催眠了)。我们会从一个实际问题开始:帮“奶油百吉饼公司”建一个能接订单的网站。
## 那么,这本书是为谁写的呢?
这本书是为那些找不到对象的……等等……拿错了……
《我讨厌PHP》是为那些一直想知道“PHP能为他们做些什么”的站长和设计师准备的;那些**真正想用PHP“做”一些东西**而不是外包出去的人。
你最好要熟悉HTML和能写/看懂HTML代码。
你不需要成为一个“我都是用记事本写代码”的那种人——只要能打开文本编辑器并理解代码就足够了。复制/粘贴知识也是有帮助的。
与市场上的其他 PHP 书籍不同,我们不会涵盖 PHP 语言广阔世界的每一个方面。
我们要脚踏实地的掌握 PHP 语言的基础知识,熟悉它,并在实际生活中的例子中使用它……而不是“填鸭式教育”。
本书也适合在看《跟Wakaba酱一起学网站制作》到## 第六章的时候阅读,可替代该章节。
**重要声明:本书采用“先让它跑起来,再让它跑得更好”的教学法。这意味着前几章我们可能会写一些“不那么完美”的代码。别担心——后面我们会一起修复它们。**
## 更多学习的地方
本书只是带你进入PHP世界的第一步,更多的路得自己走,以下网站会对你有很大帮助。
- php.net
- Google
- Bing
- StackOverflow
- 知乎
- 掘金
以下书籍也会对你有帮助:
- 《跟Wakaba酱一起学网页制作》
- 《跟Wakaba酱一起学Git使用》
# Part 1:快速启动(1-3章) - 让读者在90分钟内看到成果
## 第1章:从“讨厌”到“理解”:PHP到底是什么?
### 1.1 开场:我为什么“讨厌”PHP
让我先说清楚:我不真的讨厌PHP。但就像你的某个亲戚一样,它有时候会让你忍不住翻白眼。
比如这个:
```php
```
为什么要有``?为什么每个语句要以分号结尾?为什么……
停。打住。
我们换个角度想:PHP就像一辆二手车。它可能有点吱吱响,座椅也有点破,但**它能把你从A点带到B点**。而且,最重要的是,几乎每个停车场(网络主机)都允许它停进去。
### 1.2 奶油百吉饼公司的需求
让我们认识一下我们的“客户”:
**【奶油百吉饼公司】**
- 老板:老王
- 需求:一个能展示产品和接订单的网站
- 现状:目前只有一张Word文档的产品清单
- 预算:请你吃一年的百吉饼
老王说:“我不懂技术,我就想顾客能在网上下单,我能看到订单。”
简单,对吧?我们开始吧。
### 1.3 跳过安装,直接开始
大多数编程书会用一章来讲安装。我们会用**两句话**:
1. 如果你有网络主机,它很可能已经装了PHP
2. 如果想在本地测试,装个XAMPP或MAMP(具体步骤见附录A)
现在,创建一个文件:`index.php`
```php
奶油百吉饼公司
欢迎来到奶油百吉饼公司!
我们卖全市最好吃的百吉饼。
```
看,这就是一个普通的HTML文件,只是扩展名是`.php`。把它上传到你的网站,访问看看。
> **等等,这跟HTML有什么区别?**
> 目前没区别。但马上就有了。
## 第2章:三行代码让网站“活”起来
### 2.1 第一行魔法:`echo` - 让PHP说话
老王说:“我希望网站能自动显示今天的日期。”
没问题。修改`index.php`:
```php
奶油百吉饼公司
欢迎来到奶油百吉饼公司!
今天是:
我们卖全市最好吃(且最新鲜)的百吉饼。
```
刷新页面。看到日期了吗?**这就是你的第一行PHP代码!**
``做了三件事:
1. ``:“好了,切回HTML模式”
> **小练习**:试试把`"Y年m月d日"`改成`"l"`(小写L)。看看显示什么?
### 2.2 第二行魔法:变量 - 数据的便签贴
老王说:“百吉饼价格经常变,能不能只在一个地方改价格?”
这就是变量的用武之地。变量就像便签贴,你可以在上面写东西,然后贴在任何地方。
```php
奶油百吉饼公司
欢迎来到奶油百吉饼公司!
今天是:
我们的产品
特别提醒:价格可能随时变动,当前价格仅对今天有效。
```
现在,如果你要调整价格,只需要改第一行的`$bagel_price = 15;`。其他所有地方会自动更新!
> **变量命名规则**:
> 1. 以`$`开头
> 2. 只能包含字母、数字和下划线
> 3. 不能以数字开头
> 4. 区分大小写(`$Price`和`$price`是两个变量)
>
> **建议**:用有意义的英文名,比如`$user_name`而不是`$a`。
### 2.3 第三行魔法:`include` - 避免重复劳动
老王看了网站说:“每个页面都要有公司Logo和导航栏吗?那要复制粘贴好多次……”
没错!这就是为什么我们需要`include`。
创建两个新文件:
**header.php**
```php
奶油百吉饼公司
🥯 奶油百吉饼公司
```
**footer.php**
```php
```
现在重写`index.php`:
```php
欢迎来到奶油百吉饼公司!
今天是:
我们的产品
特别提醒:价格可能随时变动,当前价格仅对今天有效。
```
创建一个新产品页`products.php`:
```php
产品目录
百吉饼系列
- 经典原味 - 15元
- 全麦健康 - 18元
- 蓝莓口味 - 20元
- 巧克力风味 - 22元
套餐优惠
- 早餐套餐(2百吉饼+咖啡):35元
- 家庭装(6个百吉饼):85元(省5元!)
```
看!现在如果你要改导航栏或页脚,只需要改`header.php`或`footer.php`一个文件。
### 2.4 一行CSS让网站变漂亮:MVP.css
老王说:“网站功能有了,但……有点丑。”
我们有解决方案!只需要在`header.php`的``里加一行:
```php
奶油百吉饼公司
```
刷新页面。哇!瞬间变专业了。
[MVP.css](https://andybrewer.github.io/mvp/)是一个极简的CSS框架,它:
- 让HTML元素自动变好看
- 响应式设计(手机电脑都能看)
- 只有12KB
- **完全不需要学习新语法**
> **设计理念**:先做出能用的东西,再让它变好看。MVP.css完美符合这个理念。
### 2.5 实战成果检查
到现在为止,我们只写了**三行真正的PHP代码**:
1. `echo`显示日期
2. `$变量`存储价格
3. `include`复用代码
但我们已经有了:
- 动态显示日期的首页
- 统一风格的所有页面
- 美观的界面(感谢MVP.css)
- 容易维护的代码结构
老王很满意!他说:“比我预想的快多了。不过……顾客怎么下单呢?”
问得好。这就是下一章的内容。
---
## 第3章:与用户对话:表单基础
### 3.1 创建第一个表单:订购百吉饼
创建`order.php`:
```php
订购百吉饼
返回首页
```
几个重点:
1. `action="process_order.php"`:表单提交后,数据会送到这个页面处理
2. `method="POST"`:用POST方式发送数据(更安全,不会显示在地址栏)
3. 每个输入框都有`name`属性:这是PHP接收数据的钥匙
### 3.2 处理表单数据:`$_POST`超全局变量
创建`process_order.php`:
```php
订单确认
感谢您的订单,!
订单详情:
总金额:元
我们会在15分钟内通过电话确认您的订单。
再下一单 | 返回首页
```
### 3.3 安全第一:`htmlspecialchars()`函数
注意到我们用了`htmlspecialchars()`吗?
```php
```
这行代码把`<`变成`<`,`>`变成`>`。为什么?
假设有人在姓名框里输入:
```html
```
没有`htmlspecialchars()`的话,这个脚本会执行!这就是XSS攻击(跨站脚本攻击)。
`htmlspecialchars()`确保所有HTML标签都被当作普通文本显示,而不是代码。
> **安全提醒**:在把用户输入显示到页面上时,**永远**使用`htmlspecialchars()`。我们会在Part 4详细讲安全。
### 3.4 表单验证:基础版
我们的表单有个问题:如果用户直接访问`process_order.php`,会报错(因为`$_POST`是空的)。
改进版`process_order.php`:
```php
错误:请通过表单提交订单。";
echo "返回订购页面
";
exit; // 停止执行后面的代码
}
// 检查必填字段
$errors = [];
if (empty($_POST['customer_name'])) {
$errors[] = "请填写姓名";
}
if (empty($_POST['quantity']) || $_POST['quantity'] < 1) {
$errors[] = "请填写有效的数量";
}
if (empty($_POST['phone'])) {
$errors[] = "请填写联系电话";
}
// 如果有错误
if (!empty($errors)) {
include 'header.php';
echo "表单错误
";
echo "";
foreach ($errors as $error) {
echo "- $error
";
}
echo "
";
echo "返回修改
";
include 'footer.php';
exit;
}
// 如果一切正常,继续处理...
$name = $_POST['customer_name'];
$quantity = $_POST['quantity'];
// ... 其余代码和之前一样
?>
```
这里我们:
1. 检查请求方法:必须是POST
2. 检查必填字段是否为空
3. 收集所有错误
4. 如果有错误,显示给用户
5. 如果没问题,继续处理
### 3.5 实战:让表单更友好
老王试用后说:“能不能在提交前显示总价?”
当然!给`order.php`加上JavaScript实时计算:
```php
总价:15元
```
### 3.6 Part 1总结:90分钟成果展示
恭喜!在Part 1中,我们完成了:
✅ **一个完全动态的网站**
- 自动显示日期
- 集中管理价格(改一处,全站更新)
✅ **美观的用户界面**
- 使用MVP.css,零CSS知识需求
- 统一的页头页脚
✅ **完整的订购系统**
- 用户填写表单
- 后端处理数据
- 显示订单确认
- 基础验证和安全性
✅ **总共学习的PHP知识点**
1. `echo` - 输出内容
2. 变量 - `$price = 15;`
3. `include` - 代码复用
4. `$_POST` - 接收表单数据
5. `htmlspecialchars()` - 基础安全
6. `date()` - 日期函数
7. `empty()` - 检查是否为空
最重要的是:**你的网站已经能真正接单了!**
老王现在可以:
1. 顾客访问网站
2. 查看产品和价格
3. 填写订购表单
4. 收到订单确认
---
## Part 1 结语:从“讨厌”到“能干活”
还记得本章开头吗?我说PHP有时候让人讨厌。但看看我们刚刚完成的事情:
**只用90分钟**,我们就把一个静态的Word文档需求,变成了一个能实际接单的动态网站。
是的,PHP的语法可能有点怪。是的,有些设计让人想吐槽。但关键是:**它能工作**。而且工作得相当不错。
在Part 2中,我们会让网站变得更“聪明”:
- 根据库存显示不同信息(如果/否则)
- 自动生成价格表(循环)
- 记住用户的购物车(会话)
但在此之前,先享受一下成就感。你刚刚用PHP解决了一个真实世界的商业需求。
> **小任务**:
> 1. 在网站上添加一个“联系我们”页面(`contact.php`)
> 2. 让价格根据星期几变化(周一至周五15元,周末18元)
> 3. 添加一个“促销产品”板块,价格比正常低20%
准备好了吗?Part 2见!
## 第3章:与用户对话(表单基础)
### 3.1 制作一个简单的订购表单(HTML)。
### 3.2 使用$_GET和$_POST获取用户输入。
### 3.3 显示用户提交的信息(不做验证,不安全,但快速)。
实战:用户可以提交订单,页面显示“您订购了X个百吉饼”。
# Part 2:让网站“有逻辑”(4-7章) - PHP核心语法
目标:掌握条件、循环、函数等核心概念,实现业务逻辑。
## 第4章:决策时刻(if/else, switch)
### 4.1 根据库存显示不同信息(if/else)。
### 4.2 根据星期几显示不同的促销活动(switch)。
实战:让网站根据条件显示不同的内容。
## 第5章:重复的艺术(循环)
### 5.1 使用for循环生成价格表。
### 5.2 使用foreach循环展示产品列表。
实战:动态生成产品目录和价格表。
## 第6章:代码组织(函数与文件包含)
### 6.1 创建函数来计算总价。
### 6.2 将通用代码(如导航栏、页脚)提取到单独文件。
实战:重构网站,使其模块化。
## 第7章:记住用户(Session与Cookie)
### 7.1 使用Session实现简易购物车。
### 7.2 使用Cookie记住用户偏好(如名字)。
实战:用户可以添加商品到购物车,并在不同页面记住购物车内容。
# Part 3:天哪,是MySQL!(8-10章) - 数据库快速上手(不安全版)
目标:快速体验数据库的威力,但故意使用不安全的方式,为Part 4的“安全课堂”铺垫。
教学戏剧:PHP娘兴奋地使用数据库,但不知道危险所在。
## 第8章:为什么需要数据库?
### 8.1 电子表格的局限性:数据量大时的问题。
### 8.2 数据库基本概念:表、行、列。
### 8.3 连接数据库:mysqli_connect。
## 第9章:存储与检索(CRUD)
### 9.1 创建表:存储百吉饼订单。
### 9.2 插入数据:将表单数据直接拼接SQL存入(不安全!)。
### 9.3 查询数据:显示所有订单。
实战:订单数据存入数据库,并能查看。
## 第10章:整合应用
### 10.1 将之前的Session购物车与数据库结合。
### 10.2 用户注册与登录(密码明文存储,不安全!)。
里程碑:完成第一个“完整”的Web应用(但有严重安全隐患)。
# Part 4:安全升级篇(11-13章) - MySQL娘的审判
教学戏剧高潮:MySQL娘登场,指出所有安全问题,并进行修正。
核心:先犯错,再纠正,强化记忆。
## 第11章:MySQL娘的愤怒(SQL注入)
### 11.1 演示SQL注入攻击:如何通过表单输入删除整个表。
### 11.2 讲解预处理语句:mysqli_prepare。
### 11.3 修正所有之前的插入、查询代码。
## 第12章:其他安全威胁(XSS、密码存储)
### 12.1 XSS攻击与防护:htmlspecialchars。
### 12.2 密码安全:哈希与验证(password_hash和password_verify)。
### 12.3 文件上传安全。
## 第13章:重构安全应用
### 13.1 重写用户注册登录系统(安全版)。
### 13.2 重写订单处理系统(安全版)。
### 13.3 安全配置检查清单。
# Part 5:走向真实世界(14-19章) - 部署与优化
## 第14章:错误处理与调试
### 14.1 友好的错误页面。
### 14.2 日志记录。
### 14.3 调试技巧(var_dump, print_r等)。
## 第15章:性能优化
### 15.1 数据库查询优化(索引简介)。
### 15.2 缓存基础。
### 15.3 代码优化技巧。
## 第16章:项目架构优化
### 16.1 配置文件管理。
### 16.2 目录结构最佳实践。
### 16.3 简单的MVC思想。
## 第17章:使用Composer(现代PHP生态)
### 17.1 包管理基础。
### 17.2 引入第一个外部包(例如:发送邮件的库)。
### 17.3 现代化PHP开发简介。
## 第18章:部署上线
### 18.1 选择托管服务。
### 18.2 文件上传与数据库迁移。
### 18.3 域名与HTTPS。
## 第19章:下一步学习路径
### 19.1 框架介绍(Laravel等)。
### 19.2 API开发基础。
### 19.3 推荐学习资源。