
PHP资料推荐:学习基础语法可以从这些内容开始
PHP 入门资料并不少,真正容易让初学者卡住的,往往不是找不到教程,而是不知道先学什么、示例该用哪个 PHP 版本,以及学完语法后如何判断代码是否安全。本文按“选资料—搭环境—学语法—写小程序—理解边界”的顺序整理学习路径,并提供可以直接运行的示例。
PHP 常用于服务器端 Web 开发:接收 HTTP 请求、处理表单、读取数据库,再生成 HTML 或 JSON。它也可以用于命令行脚本、定时任务等场景。本文聚焦基础语法,不把 PHP 描述成适用于所有任务的工具,也不把“能运行”与“适合上线”混为一谈。
一、先选对资料:以官方手册为主,教程为辅
1. PHP 官方手册:遇到具体问题时优先查阅
PHP 官方手册的中文版本可从 php.net/manual/zh 访问。手册提供语法说明、函数参考、示例和版本信息,适合查清一个函数的参数、返回值、错误行为及可用版本。学基础时,可以依次阅读“入门”“语言参考”“安全”以及常用函数相关章节;不必一开始从头背完整本手册。
查资料时,注意函数页面上的版本信息和注释。网络文章可能针对旧版 PHP,手册中的函数说明则会标明参数、返回值及版本变化。遇到不确定的行为,不要只凭搜索结果摘要或用户评论下结论,尽量用当前环境验证。
2. PHP The Right Way:补充工程习惯,不是语法教材
PHP The Right Way 侧重现代 PHP 的实践方式,例如自动加载、依赖管理、错误处理和安全意识。它适合在学过基础语法后阅读,用来了解一个 PHP 项目通常如何组织。它并非逐行讲解基础语法的入门课程,其中部分内容涉及 Composer、框架和工程结构,刚开始时可以先记下目录,等写过几个小程序再回看。
3. 入门教程和视频:适合跟练,关键结论仍要核对
中文教程、视频课程和互动练习适合建立初步概念,也便于跟着敲代码。但选择时要检查教程使用的 PHP 版本、更新日期和代码写法。若教程用已经淘汰的写法,或者把数据库密码直接写在公开示例中,不要照搬到正式项目。
初学阶段尤其要警惕两类内容:一类把短小代码片段描述成“完整安全方案”;另一类只展示成功结果,不说明输入验证、错误处理和部署条件。更可靠的学习方式是用教程理解概念,再回到官方手册核对细节,最后自己修改示例并观察行为。
二、搭建环境:先让一段脚本跑起来
学习 PHP 基础并不一定要先安装整套 Web 服务器。安装 PHP CLI(命令行解释器)后,可以直接运行 php 文件名.php。初学者也可以使用集成开发环境或容器,但要弄清楚命令行 PHP 与 Web 服务器所使用的 PHP 是否为同一版本、是否加载了相同扩展。
在终端运行以下命令查看版本:
php -v
再创建 hello.php:
<?php
declare(strict_types=1);
$name = 'PHP';
echo "Hello, {$name}!\n";
在该文件所在目录执行:
php hello.php
declare(strict_types=1) 用于开启当前文件的严格标量类型检查,适合帮助理解类型约束,但它并不会自动验证所有输入,也不会让 PHP 变成静态类型语言。严格类型的作用范围和行为有明确规则;初学时可以保留这行,遇到类型错误时查看错误信息并理解原因。
若出现“php 不是内部或外部命令”等提示,通常是 PHP 没有安装,或可执行文件没有加入系统 PATH。若提示缺少扩展,则需要按本机环境安装或启用相应扩展。不要把一个教程中的安装命令不加判断地用于所有操作系统。
三、基础语法:变量、类型、运算和输出
变量与常见类型
PHP 变量以美元符号 $ 开头,变量名区分大小写。常见类型包括整数、浮点数、字符串、布尔值、数组、对象和 null。变量通常不需要提前声明类型,但“可以不声明”不代表值没有类型。
<?php
declare(strict_types=1);
$count = 3;
$price = 12.5;
$title = '入门';
$isReady = true;
$nothing = null;
echo $title . ':';
echo $count * $price;
echo PHP_EOL;
var_dump($isReady, $nothing);
PHP 中字符串拼接常用点号 .,不是 JavaScript 中的加号。双引号字符串可以解析变量,单引号字符串通常只处理少数转义形式。输出调试信息时,var_dump() 会显示类型和值;它适合本地调试,不应把包含敏感数据的调试结果直接输出给网站访客。
比较与类型转换
比较时要区分宽松比较 == 和严格比较 ===。宽松比较可能先进行类型转换,容易造成意外;在业务判断中,优先使用严格比较,除非你确实需要宽松转换并清楚其规则。
<?php
$value = '0';
var_dump($value == 0); // 宽松比较
var_dump($value === 0); // 类型和值都要相同
if ($value === '0') {
echo "这是字符串 0\n";
}
注意,isset($x) 在变量不存在或值为 null 时返回 false;empty($x) 会把 0、'0'、空字符串、空数组等也视为“空”。如果业务上必须区分这些值,就不要仅凭 empty() 判断。
条件、循环和函数
条件语句和循环是多数程序的基础。函数应尽量只承担清楚、有限的职责,并明确参数与返回值。
<?php
declare(strict_types=1);
function formatPrice(float $price): string
{
return number_format($price, 2, '.', '');
}
$prices = [8.5, 10, 0];
foreach ($prices as $price) {
if ($price < 0) {
continue;
}
echo formatPrice((float) $price) . PHP_EOL;
}
这里的参数类型和返回类型可以帮助调用者发现错误,但并不等于业务校验。例如,类型声明为 float 并不能证明金额合理,也不能替代对负数、币种、精度和舍入规则的设计。涉及金额时,应根据业务选择合适的表示方式,避免把浮点数精度误差当作财务计算规则。
四、数组与字符串:常用但容易误解的基础
PHP 的数组既能作为有序列表,也能作为键值映射。列表通常使用连续的数字键;关联数组使用字符串键。访问不存在的键可能触发警告或产生空值行为,处理外部输入时应先检查键是否存在。
<?php
$user = [
'name' => 'Lin',
'age' => 20,
];
echo $user['name'] . PHP_EOL;
if (array_key_exists('email', $user)) {
echo $user['email'];
} else {
echo "没有 email 字段\n";
}
array_key_exists() 检查键是否存在,即使对应值是 null 也会返回真;isset() 则会把值为 null 的键视为未设置。两者不能在所有情形下互换。
字符串长度和截取也有边界。strlen() 计算的是字节数,不一定等于中文字符数;处理 UTF-8 文本时,通常需要 mb_strlen() 等多字节字符串函数,并确认服务器安装了 mbstring 扩展。
<?php
$text = '你好 PHP';
echo strlen($text) . PHP_EOL;
if (function_exists('mb_strlen')) {
echo mb_strlen($text, 'UTF-8') . PHP_EOL;
} else {
echo "当前环境未安装 mbstring\n";
}
不要假设一个字符串只包含 ASCII,也不要把字节长度直接当作用户可见字符数量。文件名、数据库字段长度、截取位置和表单输入长度都可能受到字符编码影响。
五、学习 Web 基础:表单输入、输出和请求方法
PHP Web 程序常通过超全局变量读取请求数据,例如 $_GET、$_POST 和 $_SERVER。这些变量中的值都应当视为外部输入:用户可以修改请求内容,不能因为字段来自表单就信任它。
下面是一个最小的表单示例。将其保存为 form.php,在本地开发服务器中访问,而不是直接用浏览器打开文件:
<?php
declare(strict_types=1);
$name = '';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$rawName = $_POST['name'] ?? '';
if (!is_string($rawName)) {
$error = '姓名格式无效';
} else {
$name = trim($rawName);
if ($name === '') {
$error = '请填写姓名';
} elseif (mb_strlen($name, 'UTF-8') > 40) {
$error = '姓名不能超过 40 个字符';
}
}
}
function escapeHtml(string $value): string
{
return htmlspecialchars(
$value,
ENT_QUOTES | ENT_SUBSTITUTE,
'UTF-8'
);
}
?>
<!doctype html>
<html lang="zh-CN">
<meta charset="UTF-8">
<title>简单表单</title>
<form method="post">
<label>姓名
<input name="name" value="<?= escapeHtml($name) ?>">
</label>
<button type="submit">提交</button>
</form>
<?php if ($error !== ''): ?>
<p><?= escapeHtml($error) ?></p>
<?php elseif ($name !== ''): ?>
<p>你好,<?= escapeHtml($name) ?>!</p>
<?php endif; ?>
</html>
示例用 htmlspecialchars() 对准备放进 HTML 文本或属性值的内容进行转义,以减少 HTML 注入和跨站脚本(XSS)风险。转义应与输出上下文匹配:HTML、JavaScript、URL、CSS 有不同规则;不能把一种转义函数当成所有上下文的通用安全方案。示例中的字符数检查还依赖 mbstring,若环境没有该扩展,应安装它或改用符合需求的实现。
输入校验与输出转义解决的问题不同。校验用于确认数据是否符合业务规则,例如长度、格式和允许范围;转义用于在特定输出位置安全地表示数据。不能因为已经校验过输入,就省略输出转义。
六、数据库入门:PDO、参数化查询与安全边界
学习数据库时,可以先理解连接、查询、结果集和事务,再练习 PDO。SQL 语句不要通过字符串拼接用户输入来构造;参数化查询能让数据库驱动把参数作为数据处理,是防止 SQL 注入的重要措施。
<?php
declare(strict_types=1);
$dsn = 'sqlite:' . __DIR__ . '/demo.sqlite';
$pdo = new PDO($dsn, options: [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
$pdo->exec(
'CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL
)'
);
$title = '第一条记录';
$insert = $pdo->prepare(
'INSERT INTO notes (title) VALUES (:title)'
);
$insert->execute(['title' => $title]);
$query = $pdo->prepare(
'SELECT id, title FROM notes WHERE title = :title'
);
$query->execute(['title' => $title]);
foreach ($query->fetchAll() as $row) {
echo $row['id'] . ': ' . $row['title'] . PHP_EOL;
}
此示例使用 SQLite,前提是当前 PHP 环境提供 PDO SQLite 驱动;其他数据库需要相应驱动和连接配置。第一次运行会在脚本目录创建 demo.sqlite。生产环境不应盲目把数据库文件放在可被 Web 直接访问的位置,也不应把真实密码提交到公开代码仓库。
参数化查询保护的是 SQL 中的数据值,不是所有 SQL 结构。表名、列名和排序方向通常不能像普通值一样通过占位符绑定;若这些内容需要动态选择,应使用固定白名单映射,而非直接拼接请求参数。参数化查询也不能替代权限控制、错误处理和数据校验。
七、错误信息、日志与运行方式
开发时应查看 PHP 错误信息,确认脚本实际运行的 PHP 版本,并检查扩展是否启用。生产环境则应避免把详细错误栈、文件路径、SQL 内容和环境变量直接显示给访客;通常应记录到受控日志,并向用户返回适当的错误提示。错误显示与错误记录的设置要根据部署环境配置,不要照抄开发环境配置上线。
从 PHP 5.4 起,内置开发服务器可以用于本机快速调试:
php -S 127.0.0.1:8000
然后在浏览器访问 http://127.0.0.1:8000/。这是便于开发和演示的服务器,不应作为公网生产环境的部署方案。生产环境应使用适合的 Web 服务器和 PHP 运行方式,并配置访问控制、HTTPS、日志和更新策略。
八、常见错误与排查方法
- 变量漏写美元符号。 PHP 变量需要以
$开头;检查拼写和大小写是否一致。 - 把点号和加号混为一谈。 字符串拼接用
.,数值加法用+。类型不明时先检查输入并明确转换。 - 使用宽松比较导致分支错误。 能用
===时优先使用严格比较,并确认输入类型。 - 直接访问不存在的数组键。 对外部数据先用
??提供默认值,或用array_key_exists()检查存在性。 - 把 GET、POST 当成可信数据。 请求字段可以缺失、重复、类型异常或被伪造;读取后仍需按业务规则验证。
- 把原始输入直接拼入 HTML 或 SQL。 输出时按上下文转义;数据库查询使用参数化语句。
- 误以为类型声明等于完整校验。 类型约束不负责验证所有业务条件,也不保证数据来源可信。
- 照抄旧教程中的函数或配置。 对照官方手册确认当前版本是否支持、是否过时,以及所需扩展是否已安装。
- 代码能运行就认为可以上线。 还需要考虑错误处理、权限、日志、依赖更新、数据备份和部署配置。
九、建议的学习顺序:每一阶段都写一个小作品
- 运行环境与语法:安装 PHP CLI,练习变量、字符串、条件、循环和函数,写一个命令行单位换算或简单计算器。
- 数组与数据处理:练习列表、关联数组、遍历和常用数组函数,写一个统计文本词频的小程序。
- Web 请求与 HTML:理解 GET、POST、表单和响应,写一个带校验和安全输出的留言表单。
- 文件与异常:阅读文件函数和异常处理文档,练习检查失败情况。处理上传文件时,要进一步学习文件类型判断、大小限制、随机文件名和存储位置等规则。
- 数据库与 PDO:使用参数化查询完成增删改查,再学习事务和权限配置。数据库迁移、连接池等内容可在需要时深入。
- 工程化:学习 Composer、命名空间、自动加载、测试和代码风格。此时再读 PHP The Right Way 和框架文档会更容易建立整体理解。
每完成一个阶段,都可以给示例增加一个实际需求:处理空输入、限制长度、面对错误依然给出合理结果,或者增加自动化测试。比起复制很多教程项目,能说明代码为何这样写、边界在哪里,才算真正掌握了基础。
总结
学习 PHP 基础,可以用官方手册确认语法和函数行为,用质量可靠的课程建立概念,再用小程序反复练习。先掌握变量、类型、控制结构、函数和数组,再进入表单、数据库与工程化;同时从一开始就区分输入校验、输出转义和 SQL 参数化各自的作用。
遇到教程与实际环境不一致时,先核对 PHP 版本、扩展和运行方式,再查官方手册并构造最小示例验证。这样的学习方法既能减少过时写法带来的困扰,也能让基础语法与真实开发中的安全边界连接起来。







