PHP 零基础教程

PHP 数据类型

在 PHP 中,脚本处理的每一条数据都有一个特定的数据类型。这些类型对变量所容纳的值进行了分类,并直接影响 PHP 存储和操作这些数据的方式。理解数据类型是编写高效且无错的 PHP 代码的基础,因为它决定了算术计算、字符串拼接和逻辑比较等操作的具体行为。

PHP 是一门动态类型语言,这意味着你不需要显式地声明变量的数据类型;PHP 会在运行时根据你赋给变量的值自动判断其类型。尽管如此,在系统内部,PHP 依然严格区分这些类型。本章将重点介绍 PHP 的四种标量(单值)数据类型:字符串(Strings)、整数(Integers)、浮点数(Floats)和布尔值(Booleans)。

1. 字符串 (Strings)

字符串是一串字符序列,用于表示文本。在 PHP 中,字符串必须被包裹在单引号 (') 或双引号 (") 中。选择单引号还是双引号,会直接影响 PHP 解析字符串内部的特殊字符和变量的方式。

1.1 单引号字符串

单引号字符串会将几乎所有的字符都视为字面量(即所见即所得)。它唯一能识别的特殊字符只有用来转义单引号自身的反斜杠 (\'),以及转义反斜杠自身的反斜杠 (\\)。写在单引号字符串里的变量名不会被解析或替换为它们的值。

<?php
$name = "Alice";
$message1 = '你好,$name!'; // $name 会被当作普通文本输出,不会变成 Alice
$message2 = '今天天气真好,It\'s a beautiful day.'; // 转义单引号
$message3 = 'C:\\Program Files\\App'; // 除非用来转义 ' 或 \,否则反斜杠就是普通的文本符号

echo $message1; // 输出:你好,$name!
echo "\n";
echo $message2; // 输出:今天天气真好,It's a beautiful day.
echo "\n";
echo $message3; // 输出:C:\Program Files\App
?>

单引号字符串对于 PHP 来说通常处理速度更快,因为解释器不需要去扫描其中的变量或复杂的转义序列。当你的文本不需要插入变量时,使用单引号是很好的选择。

1.2 双引号字符串

双引号字符串的功能更强大,因为它能解析更多的转义序列,并且允许变量插值(Variable Interpolation)。当 PHP 在双引号字符串中遇到美元符号 ($) 时,它会尝试将其替换为同名变量的值。

双引号字符串中常见的转义序列包括:

  • \n: 换行符
  • \r: 回车符
  • \t: 水平制表符 (Tab)
  • \\: 反斜杠
  • \$: 美元符号
  • \": 双引号
<?php
$city = "纽约";
$temp = 25;

$message4 = "欢迎来到$city!今天的温度是 $temp 摄氏度。\n"; // 变量插值
$message5 = "这个字符串包含一个 \"双引号\" 和一个换行符。\n"; // 转义双引号和换行符

echo $message4;
echo $message5;

// 使用花括号进行复杂的变量插值(虽是可选的,但为了代码清晰强烈推荐)
$fruit = "苹果";
$count = 3;
$sentence = "我有 {$count} 个{$fruit}。"; // 花括号清晰地界定了变量名
echo $sentence; // 输出:我有 3 个苹果。
echo "\n";

// 直接在双引号内访问数组元素
$user = ['first_name' => '鲍勃'];
echo "用户的名字是 {$user['first_name']}。\n";
?>

双引号字符串非常适合用于构建动态输出,比如包含用户数据的消息或带有特殊字符的格式化文本。

2. 整数 (Integers)

整数是没有小数部分的数字,可以是正数、负数或零。在 PHP 中,整数可以用十进制(基数 10)、十六进制(基数 16,以 0x 开头)、八进制(基数 8,以 0o0 开头)或二进制(基数 2,以 0b 开头)来表示。

整数的大小依赖于运行的平台,在现代系统上通常是 64 位的,这意味着整数的范围大约在 -9E18 到 9E18 之间。如果一个整数运算的结果超出了这个范围,它会自动转换为浮点数(Float)。

<?php
$decimalInt = 12345;      // 十进制数
$negativeInt = -500;      // 负整数
$hexInt = 0xFF;           // 十六进制(十进制中的 255)
$octalInt = 0o123;        // 八进制(十进制中的 83,现代 PHP 推荐 '0o' 前缀,'0' 也可以)
$binaryInt = 0b101010;    // 二进制(十进制中的 42)

echo "十进制:" . $decimalInt . "\n";
echo "负数:" . $negativeInt . "\n";
echo "十六进制:" . $hexInt . "\n";
echo "八进制:" . $octalInt . "\n";
echo "二进制:" . $binaryInt . "\n";

// 整数溢出导致转换为浮点数的例子
$largeNumber = 9223372036854775807; // 64位整数的最大值
$overflow = $largeNumber + 1;
var_dump($overflow); // 输出将显示 float(9.2233720368548E+18)
?>

整数通常用于计数、ID、年龄、数量或任何不需要小数部分的数值。

3. 浮点数 (Floats)

浮点数(也称为“双精度数”或 doubles)代表带有小数点的数字或以指数形式表示的数字。当需要比整数更高的精度时(例如价格、测量值或科学计算),就会使用浮点数。

<?php
$price = 19.99;          // 十进制浮点数
$temperature = -3.5;     // 负浮点数
$largeFloat = 1.234e3;   // 指数表示法 (1.234 * 10^3 = 1234.0)
$smallFloat = 5.67e-2;   // 指数表示法 (5.67 * 10^-2 = 0.0567)

echo "价格:" . $price . "\n";
echo "温度:" . $temperature . "\n";
echo "大浮点数:" . $largeFloat . "\n";
echo "小浮点数:" . $smallFloat . "\n";

// 【重要陷阱】浮点数的精度问题:由于计算机底层存储机制,直接比较浮点数可能会出问题。
$a = 0.1 + 0.7;
$b = 0.8;
echo "0.1 + 0.7 = " . $a . "\n"; // 输出看上去是:0.8
var_dump($a == $b); // 输出:bool(false) - 这是一个非常常见的陷阱。

// 为了进行准确的比较,通常会使用一个极小的容差值(epsilon),或者在处理金钱计算时优先使用整数(如将“元”转化为“分”计算)。
?>

浮点数对于财务应用(需谨慎处理精度问题)、科学建模以及任何极其依赖小数部分的功能都至关重要。

4. 布尔值 (Booleans)

布尔值代表真假值,它只能是两种状态之一:true(真)或 false(假)。这些值是不区分大小写的。布尔值是控制结构(如 if 语句和循环)的基础,程序需要根据条件是否满足来做出决定。

<?php
$isLoggedIn = true;     // 变量设置为布尔值 true
$isAdmin = FALSE;       // 变量设置为布尔值 false(不区分大小写)
$hasPermission = (10 > 5); // 比较运算的结果,即 true
$isGuest = (empty($_POST['username'])); // 函数返回布尔值的示例

echo "是否已登录?" . ($isLoggedIn ? "是" : "否") . "\n"; // 使用三元运算符进行输出
echo "是否为管理员?" . ($isAdmin ? "是" : "否") . "\n";
echo "是否有权限?" . ($hasPermission ? "是" : "否") . "\n";

// 强制转换为布尔值:理解“Falsy(假值)”
// 以下值在转换为布尔值时会被认为是 FALSE:
// - 布尔值 FALSE 本身
// - 整数 0 (零)
// - 浮点数 0.0 (零)
// - 空字符串 "" 和字符串 "0"
// - 包含零个元素的数组 (空数组 [])
// - 特殊类型 NULL
// - 从空标签创建的 SimpleXML 对象

$emptyString = "";
$zeroInt = 0;
$zeroFloat = 0.0;
$emptyArray = [];
$nullVar = null;

if ($emptyString) { echo "空字符串是 TRUE\n"; } else { echo "空字符串是 FALSE\n"; }
if ($zeroInt) { echo "数字 0 是 TRUE\n"; } else { echo "数字 0 是 FALSE\n"; }
if ($zeroFloat) { echo "浮点数 0.0 是 TRUE\n"; } else { echo "浮点数 0.0 是 FALSE\n"; }
if ($emptyArray) { echo "空数组是 TRUE\n"; } else { echo "空数组是 FALSE\n"; }
if ($nullVar) { echo "NULL 是 TRUE\n"; } else { echo "NULL 是 FALSE\n"; }

$nonEmptyString = "你好";
if ($nonEmptyString) { echo "非空字符串是 TRUE\n"; } else { echo "非空字符串是 FALSE\n"; }
?>

布尔值对于条件逻辑、状态标记以及指示操作是成功还是失败至关重要。例如,一个函数如果执行成功可能会返回 true,否则返回 false

5. 综合实战案例

下面这些案例结合了我们讨论过的数据类型,展示了常见的实际应用场景。

5.1 电子商务订单详情

假设你正在构建一个简单的电子商务系统。你需要存储产品名称、数量、价格以及商品是否有库存。

<?php
// 产品信息
$productName = "无线鼠标";       // 字符串 (String)
$quantity = 2;                  // 整数 (Integer)
$unitPrice = 29.99;             // 浮点数 (Float)
$isInStock = true;              // 布尔值 (Boolean)

// 计算小计
$subtotal = $quantity * $unitPrice; // 结果是一个浮点数

echo "产品名称:" . $productName . "\n";
echo "数量:" . $quantity . "\n";
echo "单价:$" . $unitPrice . "\n";
echo "是否有库存:" . ($isInStock ? "是" : "否") . "\n";
echo "小计金额:$" . $subtotal . "\n";

// 使用双引号进行字符串拼接的例子
$orderSummary = "你订购了 {$quantity} 个 {$productName},单价为 $" . $unitPrice . "。总计:$" . $subtotal . "。";
echo $orderSummary . "\n";
?>

这个案例展示了不同的数据类型如何自然地结合在一起表达现实世界的信息。productName 是文本,quantity 是整数,unitPrice 包含小数,而 isInStock 是一个“是/否”条件。

5.2 用户认证状态

当用户登录网站时,你需要跟踪他们的认证状态。

<?php
$username = "john.doe"; // 字符串
$isAuthenticated = false; // 布尔值 - 初始状态为未认证

// 模拟认证尝试
$passwordAttempt = "password123";
$storedPasswordHash = "hashed_password_from_database"; // 实际上,应该比对哈希值

// 为了简单起见,我们基于一个简单的条件来设置 isAuthenticated
if ($username == "john.doe" && $passwordAttempt == "password123") {
    $isAuthenticated = true; // 用户认证成功
}

// 显示认证结果
if ($isAuthenticated) {
    echo "欢迎," . $username . "!你已成功登录。\n";
} else {
    echo $username . " 的认证失败。请重试。\n";
}

// 另一个关于管理员标记的布尔值例子
$userLevel = "admin";
$isAdministrator = ($userLevel === "admin"); // 检查用户是否为管理员
echo "是否为管理员?" . ($isAdministrator ? "是" : "否") . "\n";
?>