摘要:在上一篇文章中,我们搭建了开发环境并运行了第一个 PHP 程序,初步感受了它的魅力。从本篇开始,我们将正式踏入 PHP 语法的大门。你是否曾被编程中的"变量""常量""数据类型"这些术语搞得一头雾水?别担心,本文将用最生活化的比喻,带你系统地掌握 PHP 的基础语法规则、八种数据类型及其转换方式、运算符的使用,以及字符串处理的常用技巧。学完本篇,你将能独立编写具有数据处理和逻辑判断能力的小脚本,为后续的流程控制和函数学习打下坚实基础。让我们开始这场充满代码与趣味的探索吧。
一、引言:编程语言的"词汇"与"语法"
就像学英语要先学单词和语法一样,学任何编程语言,首先要掌握它的"词汇"(数据类型、变量、常量)和"语法"(如何组织这些词汇,如表达式、运算符)。PHP 的语法非常宽容,对初学者友好,但这并不意味着可以随意书写。养成良好的编码习惯,从理解底层概念开始。
本篇的内容架构是:变量与常量 → 八种数据类型详解 → 类型转换与判断 → 运算符 → 字符串函数入门。
二、变量:存储数据的"盒子"
2.1 什么是变量?
想象你有一个贴了标签的空盒子,你可以把任何东西放进去------一个数字、一段文字、一串名单。这个盒子就是变量。在 PHP 中,变量名就是标签,变量值就是盒子里的东西,而且盒子里的东西随时可以更换。
2.2 变量的声明与命名规则
PHP 变量必须以 $ 符号开头,后面紧跟变量名。变量名区分大小写,只能包含字母、数字、下划线,且不能以数字开头。通常我们使用驼峰式或下划线式命名。
php
<?php
// 合法命名
$name = "张三";
$_age = 25;
$myFavoriteColor = "蓝色"; // 驼峰式
$user_first_name = "李"; // 下划线式
// 非法命名(不要这样写)
// $123abc = "error"; // 不能以数字开头
// $my-var = "error"; // 不能包含连字符
?>
2.3 变量的赋值与传值方式
PHP 中有两种赋值方式:传值赋值 (默认)和引用赋值。
传值赋值:将原变量的值复制一份给新变量,两者互不影响。
php
<?php
$a = 10;
$b = $a; // $b 得到 $a 的副本
$b = 20;
echo $a; // 输出 10,$a 不受 $b 的影响
?>
引用赋值 :在变量前加 &,使新变量指向原变量的"内存地址",一改俱改。
php
<?php
$a = 10;
$b = &$a; // $b 是 $a 的别名,指向同一内存地址
$b = 20;
echo $a; // 输出 20,因为 $a 和 $b 本质上是同一个值
?>
2.4 变量的变量
PHP 允许使用一个变量的值作为另一个变量的名称,称为"变量的变量"。
php
<?php
$fruit = "apple";
$$fruit = "红富士"; // 相当于 $apple = "红富士";
echo $apple; // 输出 "红富士"
?>
虽然灵活,但可读性差,实际开发中极少使用。
三、常量:不变的"固定标签"
3.1 什么是常量?
常量与变量相对,一旦定义,其值在整个脚本运行期间不可更改。用于存储不会变的值,如网站域名、数据库连接参数、数学常数等。
3.2 定义常量的两种方式
方式一:define() 函数(传统方式,运行阶段定义)
php
<?php
define("SITE_NAME", "我的博客");
define("MAX_LOGIN_ATTEMPTS", 5);
define("PI", 3.14159);
echo SITE_NAME; // 输出 "我的博客",常量名前不需要 $
echo PI; // 输出 3.14159
?>
方式二:const 关键字(编译阶段定义,性能略好,用于类常量更佳)
php
<?php
const DB_HOST = "localhost";
const DB_USER = "root";
echo DB_HOST; // 输出 "localhost"
?>
3.3 常量的特点与魔术常量
-
常量名通常全大写,用下划线分隔(约定俗成)。
-
常量是全局的,无需关心作用域。
-
define可以定义表达式(PHP 7+),const不能用于条件语句中。
魔术常量:PHP 预定义的一些常量,值会随着所在位置变化。
php
<?php
echo __LINE__; // 当前行号
echo __FILE__; // 当前文件完整路径
echo __DIR__; // 当前文件所在目录
echo __FUNCTION__; // 当前函数名(在函数内)
?>
四、PHP 的八种数据类型深度剖析
数据类型定义了变量可以存储什么种类的数据,以及能对这些数据做什么操作。PHP 是弱类型语言,同一个变量可以先后存储不同类型的值,但理解每种类型至关重要。
4.1 整型(Integer)
用于存储没有小数点的数字,可以是十进制、八进制(0 开头)、十六进制(0x 开头)、二进制(0b 开头,PHP 5.4+)。
php
<?php
$decimal = 42; // 十进制
$octal = 0755; // 八进制(以 0 开头,等于十进制的 493)
$hex = 0xFF; // 十六进制(等于十进制的 255)
$binary = 0b1100; // 二进制(等于十进制的 12)
echo $decimal; // 42
echo PHP_INT_MAX; // 本平台最大整数,通常是 9223372036854775807(64 位系统)
echo PHP_INT_MIN; // 最小整数
?>
溢出处理:如果给定的数超出整型范围,PHP 会将其自动解释为浮点型。
4.2 浮点型(Float / Double)
用于存储带小数点的数字或极大/极小的数(科学计数法)。
php
<?php
$price = 19.99;
$distance = 3.4e3; // 3.4 × 10³ = 3400
$tiny = 7E-10; // 7 × 10⁻¹⁰
var_dump($price); // float(19.99)
?>
精度问题警示:浮点数在计算机内部是二进制近似存储,运算可能产生微小的误差。
php
<?php
$a = 0.1;
$b = 0.2;
$c = $a + $b;
var_dump($c == 0.3); // 输出 bool(false)!
// 实际 $c 可能是 0.30000000000000004
// 比较浮点数应使用一个误差范围,如 abs($c - 0.3) < 0.00001
?>
4.3 布尔型(Boolean)
只有两个值:true 和 false,不区分大小写(TRUE/False 皆可,但推荐小写)。常用于条件判断。
php
<?php
$is_logged_in = true;
$has_permission = false;
if ($is_logged_in) {
echo "欢迎回来!";
}
?>
哪些值被视为 false(强制转换时)?
-
布尔值
false本身 -
整型
0 -
浮点型
0.0 -
空字符串
""和字符串"0" -
空数组
[]或array() -
NULL -
从零值变量创建的
SimpleXML对象
其余一切值都被视为 true。这叫做"松散比较"。
4.4 字符串(String)
字符串是字符的序列。PHP 中有四种定义方式。
① 单引号字符串 单引号内的字符几乎都被当作字面值,只有两个转义字符有效:\\(单引号)和 \\'(反斜杠本身)。变量不会被解析。
php
<?php
$name = "小明";
echo '你好,$name'; // 输出:你好,$name(变量未被解析)
echo 'I\'m happy'; // 输出:I'm happy
?>
② 双引号字符串 双引号会解析其中的变量和转义字符(\n, \r, \t, \\, \$ 等)。
php
<?php
$count = 5;
echo "你有 $count 条新消息。"; // 输出:你有 5 条新消息。
echo "第一行\n第二行"; // 在命令行会换行,HTML 中需要用 <br> 或查看源代码
?>
如果变量名后紧跟字母数字,可用花括号明确变量边界:
php
<?php
$fruit = "apple";
echo "I like {$fruit}s."; // 输出:I like apples.
?>
③ Heredoc 语法(<<<) 适合定义包含大量文本、保留换行的字符串。语法类似双引号,会解析变量。
php
<?php
$title = "公告";
$str = <<<EOT
<h2>$title</h2>
<p>这是多行文本内容,
支持变量解析和双引号无需转义。</p>
EOT;
echo $str;
?>
标识符 EOT(可以任意命名)所在行必须仅包含自身,不可有空格或其他字符。
④ Nowdoc 语法(<<<'EOT') 类似单引号,不解析变量。
php
<?php
$str = <<<'EOT'
这里不会解析 $变量,相当于加强版单引号。
EOT;
?>
4.5 数组(Array)
数组可以存储多个值,是 PHP 中最强大、最常用的数据结构之一(下一篇会专门深入数组)。这里先认识创建和访问。
索引数组(键为数字):
php
<?php
$colors = array("红", "绿", "蓝");
// PHP 5.4+ 简写
$colors = ["红", "绿", "蓝"];
echo $colors[0]; // 输出 "红"
$colors[] = "黄"; // 自动追加到末尾,索引 3
?>
关联数组(键为字符串):
php
<?php
$user = [
"name" => "李四",
"age" => 30,
"city" => "上海"
];
echo $user["name"]; // 输出 "李四"
?>
4.6 对象(Object)
对象是面向对象编程的核心,通过 new 关键字实例化一个类得到。
php
<?php
class Person {
public $name;
public function sayHello() {
echo "你好,我叫 $this->name";
}
}
$p = new Person();
$p->name = "王五";
$p->sayHello(); // 输出:你好,我叫王五
?>
4.7 NULL 类型
NULL 表示变量没有值。以下情况变量会被视为 NULL:
-
被显式赋值为
NULL。 -
尚未被赋值。
-
使用
unset()销毁后的变量。
php
<?php
$var = NULL;
var_dump($var); // NULL
$var2; // 未赋值,值为 NULL(但会触发 Notice 警告)
unset($var);
var_dump($var); // NULL(且变量 $var 已不存在)
?>
4.8 资源(Resource)
资源是一种特殊的变量,保存到外部资源(如文件、数据库连接、图像画布)的引用。PHP 负责管理这些资源,用完通常需手动释放或等脚本结束自动回收。
php
<?php
$file = fopen("test.txt", "r"); // 打开文件,返回资源
var_dump($file); // resource(...)
fclose($file); // 关闭文件,释放资源
?>
资源在调试时看不到具体数据,只能看到类型编号。
五、类型判断、获取与转换
5.1 获取数据类型
var_dump() 用于调试,输出变量类型和值。gettype() 返回类型的字符串名称。
php
<?php
$data = 123;
var_dump($data); // int(123)
echo gettype($data); // "integer"
?>
5.2 类型判断函数
PHP 提供了一系列以 is_ 开头的函数判断类型:
php
<?php
$val = "hello";
is_string($val); // true
is_int($val); // false
is_float($val); // false
is_bool($val); // false
is_array($val); // false
is_null($val); // false
is_numeric("123"); // true(判断是否为数值或数值字符串)
isset($val); // true(变量存在且不为 NULL)
empty($val); // false(变量为空时返回 true)
?>
isset() 与 empty() 的区别是常见面试题:
-
isset():变量已设置且值不为NULL。 -
empty():值等于空(空字符串、0、"0"、false、NULL、空数组等)返回true,即使变量不存在也不产生警告。
5.3 类型转换
自动类型转换(类型转换):PHP 会根据上下文自动转换类型。
php
<?php
$num = "10" + 5; // 字符串 "10" 转为整数 10,结果 15
$str = "10hello" + 5; // 字符串 "10hello" 转为整数 10,结果 15(产生 Warning)
$concat = "10" . 5; // 点运算符强制将 5 转为字符串,结果 "105"
?>
强制类型转换:在变量前加括号指定目标类型,不会改变原变量。
php
<?php
$x = 3.14;
$y = (int)$x; // $y = 3,$x 仍是 3.14
$z = (string)$x; // $z = "3.14"
?>
常用强制转换关键字:(int), (float), (string), (bool), (array), (object)。
函数转换 :intval(), floatval(), strval()。
php
<?php
$a = "42px";
echo intval($a); // 42
?>
六、运算符:让数据"动"起来
运算符是处理数据的工具。PHP 的运算符与大部分语言类似。
6.1 算术运算符
| 运算符 | 名称 | 示例 |
|---|---|---|
| + | 加 | $a + $b |
| - | 减 | $a - $b |
| * | 乘 | $a * $b |
| / | 除 | $a / $b |
| % | 取模 | $a % $b |
| ** | 乘方 | $a ** $b(PHP 5.6+) |
php
<?php
echo 10 % 3; // 输出 1
echo 2 ** 3; // 输出 8
?>
6.2 赋值运算符
= 是基本赋值,可与算术运算符组合:
php
<?php
$a = 10;
$a += 5; // 相当于 $a = $a + 5;
$a .= "元"; // 相当于 $a = $a . "元";(连接字符串)
?>
6.3 比较运算符
比较表达式返回布尔值。
| 运算符 | 名称 | 示例 |
|---|---|---|
| == | 等于 | $a == $b |
| === | 全等 | $a === $b |
| != | 不等 | $a != $b |
| !== | 不全等 | $a !== $b |
| < | 小于 | $a < $b |
| > | 大于 | $a > $b |
| <= | 小于等于 | $a <= $b |
| >= | 大于等于 | $a >= $b |
| <=> | 太空船 | $a <=> $b |
== vs === 是核心区别:
-
==会进行类型转换后再比较。 -
===要求类型和值都相等。
php
<?php
var_dump(0 == "0"); // true,因为字符串 "0" 转为整数 0
var_dump(0 === "0"); // false,类型不同(整数 vs 字符串)
var_dump(0 == false); // true,false 转为整数 0
var_dump(0 === false); // false
// 太空船运算符:$a <=> $b 当 $a 小于/等于/大于 $b 时,分别返回 -1/0/1
echo 5 <=> 10; // -1
echo 10 <=> 10; // 0
echo 15 <=> 10; // 1
?>
6.4 逻辑运算符
用于组合多个条件。
| 运算符 | 名称 | 示例 |
|---|---|---|
| && / and | 与 | $a && $b |
| || / or | 或 | $a || $b |
| ! | 非 | !$a |
| xor | 异或 | $a xor $b |
&& 比 and 优先级高,|| 比 or 高,这是常见的坑。推荐统一使用 && 和 ||。
php
<?php
$logged = true;
$admin = false;
if ($logged && $admin) {
echo "进入管理面板";
} else {
echo "权限不足";
}
// 短路特性:如果左侧已能决定结果,右侧不再执行
$result = false && someFunction(); // someFunction() 不会被执行
?>
6.5 字符串运算符
. 用于连接字符串,.= 用于连接并赋值。
php
<?php
$hello = "你好";
$world = "世界";
echo $hello . ", " . $world . "!"; // 输出:你好, 世界!
$msg = "Hello";
$msg .= " PHP"; // $msg = "Hello PHP"
?>
6.6 递增/递减运算符
++(递增 1),--(递减 1),有前置后置之分,影响表达式的返回值。
php
<?php
$a = 5;
echo $a++; // 输出 5,然后 $a 变为 6(后置递增:先返回旧值,再自增)
echo ++$a; // $a 先变为 7,然后输出 7(前置递增:先自增,再返回新值)
?>
6.7 三元运算符与空合并运算符
三元运算符 :条件 ? 值1 : 值2
php
<?php
$age = 20;
$status = ($age >= 18) ? "成年人" : "未成年人";
echo $status; // 输出:成年人
?>
空合并运算符 (PHP 7+):??,用于简化 isset() 的三元判断。
php
<?php
$name = $_GET['user'] ?? "游客"; // 若 $_GET['user'] 存在且不为 NULL,用其值;否则用 "游客"
?>
空合并赋值运算符 (PHP 7.4+):??=
php
<?php
$count = null;
$count ??= 10; // 等价于 $count = $count ?? 10;
echo $count; // 10
?>
七、字符串函数入门:玩转文字
字符串处理是 Web 开发的高频操作。PHP 内置了上百个字符串函数,这里列举最常用的一部分。
7.1 获取字符串长度:strlen()
php
<?php
echo strlen("hello"); // 5
echo strlen("你好"); // 6(UTF-8 编码下,一个汉字占 3 个字节)
echo mb_strlen("你好"); // 2(mb_* 系列函数支持多字节字符,更准确)
?>
7.2 查找与替换
php
<?php
$text = "Hello World, Hello PHP";
// strpos():查找字符串首次出现的位置(区分大小写,未找到返回 false)
$pos = strpos($text, "World");
var_dump($pos); // int(6)(从 0 开始计数)
// str_replace():替换字符串
$new = str_replace("Hello", "你好", $text);
echo $new; // 你好 World, 你好 PHP
// str_ireplace():不区分大小写的替换
?>
注意 :strpos 可能返回 0(第一个字符),而 0 在松散比较中等同于 false,因此判断时必须用 === false:
php
<?php
if (strpos($text, "Hello") !== false) {
echo "找到了";
}
?>
7.3 截取与分割
php
<?php
$str = "abcdefg";
// substr():截取子串(参数:字符串, 起始位置, 长度)
echo substr($str, 0, 3); // "abc"
echo substr($str, -3); // "efg"(负数从末尾开始)
echo substr($str, 3); // "defg"(省略长度,取到末尾)
// explode():按分隔符分割字符串为数组
$list = "苹果,香蕉,橘子";
$arr = explode(",", $list);
var_dump($arr); // ["苹果", "香蕉", "橘子"]
// implode() / join():将数组合并为字符串
echo implode(" | ", $arr); // "苹果 | 香蕉 | 橘子"
?>
7.4 大小写转换与格式化
php
<?php
echo strtolower("HELLO"); // "hello"
echo strtoupper("hello"); // "HELLO"
echo ucfirst("hello"); // "Hello"(首字母大写)
echo ucwords("hello world");// "Hello World"(每个单词首字母大写)
// trim():去除首尾空白字符(换行、空格、制表符)
$input = " 有空格的用户名 ";
echo trim($input); // "有空格的用户名"
// str_pad():填充字符串到指定长度
echo str_pad("42", 5, "0", STR_PAD_LEFT); // "00042"
?>
7.5 HTML 相关函数
php
<?php
// htmlspecialchars():将特殊字符转为 HTML 实体,防止 XSS
$user_input = '<script>alert("XSS")</script>';
echo htmlspecialchars($user_input);
// 浏览器将显示为文本而非执行脚本
// strip_tags():去除所有 HTML 和 PHP 标签
echo strip_tags("<p>这是<b>粗体</b></p>"); // "这是粗体"
?>
7.6 字符串与数组互转的趣味应用
php
<?php
// str_split():将字符串按字符分割成数组
$chars = str_split("hello");
print_r($chars); // ['h', 'e', 'l', 'l', 'o']
// str_word_count():返回单词数量或单词数组
echo str_word_count("Hello PHP world"); // 3
?>
八、综合示例:一个简单的用户信息卡片
我们将本篇的知识整合起来,编写一个动态生成用户信息卡片的小脚本。
php
<?php
// 模拟用户数据
$username = " 张三 ";
$age = 28;
$city = "北京";
$hobbies = ["编程", "摄影", "旅行"];
$bio = "热爱技术,喜欢用代码创造价值。";
// 数据清洗
$username = trim($username);
$safe_bio = htmlspecialchars($bio);
$user_status = ($age >= 18) ? "成年人" : "未成年人";
$hobby_text = implode("、", $hobbies);
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title><?php echo $username; ?> 的个人卡片</title>
<style>
.card { border: 1px solid #ccc; padding: 20px; width: 300px; }
.avatar {
width: 100px;
height: 100px;
border-radius: 50%;
background: #4299e1;
color: white;
font-size: 40px;
display: flex;
align-items: center;
justify-content: center;
}
.tag { background: #eee; padding: 2px 8px; margin: 2px; display: inline-block; }
</style>
</head>
<body>
<div class="card">
<!-- CSS绘制圆形头像,显示姓名第一个字,无网络请求 -->
<div class="avatar">
<?php echo mb_substr($username, 0, 1); ?>
</div>
<h2><?php echo $username; ?> <small>(<?php echo $user_status; ?>)</small></h2>
<p>城市:<?php echo $city; ?></p>
<p>爱好:<?php echo $hobby_text; ?></p>
<p>简介:<?php echo $safe_bio; ?></p>
</div>
</body>
</html>
代码解析:
-
用本地 CSS 文字头像。
-
使用变量存储用户信息。
-
trim()清理用户名前后空格。 -
htmlspecialchars()防止简介中可能存在的恶意代码。 -
三元运算符判断用户是否成年。
-
implode()将爱好数组拼接成字符串。 -
在 HTML 中穿插 PHP 输出动态数据。
将上述代码保存为 card.php 并运行,即可看到一张用户信息卡片。

试着修改 $username 的值为 " 李四 <script>alert('!')</script>",观察 trim 和 htmlspecialchars 的作用。


九、总结
-
变量 :以
$开头,是存储数据的容器;传值赋值与引用赋值的区别要牢记。 -
常量 :使用
define()或const定义,值不可变,常用于配置项。 -
八种数据类型:整型、浮点型、布尔型、字符串、数组、对象、NULL、资源。每种类型都有其适用场景和特性,浮点数精度问题、布尔值"假"的列表是常见考点。
-
类型判断与转换 :
var_dump()是调试利器;is_*系列函数用于判断;自动转换与强制转换需要留意规则,避免 bug。 -
运算符 :算术、比较(
==vs===)、逻辑(短路特性)、字符串连接、递增递减、三元与空合并运算符,都是代码逻辑的基础。 -
字符串函数 :
strlen、strpos、substr、explode、implode、htmlspecialchars等是处理文本的瑞士军刀。
十、练习题(动手试试!)
-
定义两个变量
$a = 10; $b = "10";,分别用==和===比较它们,用var_dump()输出结果,解释为什么。 -
写一个脚本,接收一个名字参数
$_GET['name'],用空合并运算符设置默认值为"访客",然后输出"欢迎你,名字!"。注意使用htmlspecialchars防止 XSS。 -
给定字符串
"apple, banana, orange",用explode分割成数组,再用foreach循环打印每个水果(下一章才学循环,可提前搜索尝试或保留到下一篇)。 -
计算圆的面积(常量
PI= 3.14,半径$r = 5),输出"半径为 5 的圆的面积是 78.5"。
如果这篇文章帮你解决了实操上的困惑,别忘记点击点赞、分享 ,也可以留言告诉我你遇到的其它问题,我会尽快回复。动手练习是掌握编程最快的方法,请务必亲手敲一遍本文的所有示例代码,并截图保存你的成果。你的关注是我坚持原创和细节共享的力量来源,谢谢大家。