第1章 1.3 变量、常量与基本数据类型

上章回顾:上一章我们装好了 PHP 环境,打开编辑器就能写代码了。但现在的代码只能「傻傻地」执行固定逻辑——写死的东西换个数据就得改源代码。这就像做菜,如果每次都要重新买锅买灶,太麻烦了。

本章目标:学完这一章,你就能写出「会思考」的代码——根据不同数据自动做不同的事。比如做个「购物车」,随便丢什么商品进去,它都能帮你算总价。


🎯 开场 3 分钟:为什么要学这个?

想象一个场景:你在写一个「商品管理系统」,卖 iPhone 卖 5999 块,卖 MacBook 卖 9999 块。如果写成这样:

<?php
echo "iPhone 价格是 5999";
echo "MacBook 价格是 9999";
?>

问题来了:某天 iPhone 降价到 5499,你得翻遍整个代码把所有「5999」改成「5499」。万一手抖改错了其他数字,哭都来不及。

变量就是程序员的「储物箱」——给数据起个名字,需要的时候喊名字就能拿到值,改也只改一个地方。
\n\nSimple tech illustration expla\n\nAI comic creation scene, creat\n\n
常量就是「铁打的标签」——一旦贴上就不能撕下来改,适合放那些「整个程序都不会变」的东西,比如税率、版本号。

数据类型决定了这个箱子里能放什么——放数字的不能当文字用,放真假判断的只能存「对」或「错」。


🧱 基础 25 分钟:核心概念

1. 变量:数据的「花名册」

是什么:变量就是给数据起的名字,用 $ 符号开头。

生活类比:就像宿舍楼里的「花名册」,每床位有个编号(变量名),住进去的人会换(值可以变),但床位编号不变。

为什么用:避免硬编码,方便修改,一处改动全局生效。

怎么用

<?php
$price = 5999;          // 整数类型
$product_name = "iPhone"; // 字符串类型
$in_stock = true;       // 布尔类型

echo $product_name . " 售价 " . $price . " 元";
?>

输出

iPhone 售价 5999 元

这段代码里 $price 是个「储物箱」,里面放了数字 5999。需要改价格?只改这一行就行。

2. 基本数据类型:数据的「性格」

PHP 是「懒人语言」,变量不用提前声明类型,但它心里有数。

字符串(string):一串字符,用引号包起来。

<?php
$name = "小明";
$address = '北京市朝阳区';
echo "用户 $name 住在 $address"; // 双引号里能解析变量
echo '用户名是 $name';            // 单引号里是纯文本,原样输出
?>

输出

用户 小明 住在北京市朝阳区
用户名是 $name

注意!双引号里写变量名会「变」出值,单引号里写变量名只会「变」出字面量。

整数(int):没有小数点的数字。

<?php
$age = 25;
$price = -99;
$quantity = 0;
echo $age + $price; // 25 + (-99) = -74
?>

输出

-74

浮点数(float):带小数点的数字。

<?php
$height = 1.75;
$weight = 68.5;
$bmi = $weight / ($height * $height);
echo "BMI 值是 " . $bmi;
?>

输出

BMI 值是 22.3673469387755

布尔(bool):只有 true(真)和 false(假)两种值。

<?php
$is_logged_in = true;
$is_admin = false;

if ($is_admin) {
echo "欢迎管理员";
} else {
echo "普通用户无权访问";
}
?>

输出

普通用户无权访问

布尔类型看起来简单,但用处极大——所有「是/否」「对/错」的判断都用它。

3. 常量:不能改的「铁标签」

是什么:一旦定义就不能修改的量,用 define()const 定义。

生活类比:就像宪法——全国统一,谁都不能改。程序里放税率、PI 值、API 地址等「铁定不变」的东西。

为什么用:防止手滑改错值,告诉其他程序员「这个你别动」。

怎么用

<?php
// 方式1:define(名字, 值)
define("TAX_RATE", 0.13);
define("APP_VERSION", "1.0.0");

// 方式2:const(更现代)
const DB_HOST = "localhost";
const DB_NAME = "shop_db";

// 使用
$price = 100;
$tax = $price * TAX_RATE;
echo "含税价格:" . ($price + $tax);
?>

输出

含税价格:113

常量名字推荐用大写字母加下划线,一眼就能认出「这是常量别乱改」。

4. 可变变量:箱子上再贴箱

是什么:用另一个变量的值作为变量名。

<?php
$apple = "苹果";
$fruit = "apple";  // 这个变量存的是 "apple"(字符串)

echo $$fruit;  // 相当于 echo $apple;
// $$fruit 意思是:用 $fruit 的值("apple")去找对应的变量
?>

输出

苹果

这个语法很「绕」,但可以理解成「套娃」——变量名本身也是变量。新手阶段了解即可,实战中用得不多。

5. 引用:同一个房间的两个门牌号

是什么:给同一个变量起个别名,用 & 符号。

生活类比:就像一个房间有两个门牌号「101」和「甲一号」,进哪个门都是同一个房间。

<?php
$a = 100;
$b = &$a;   // $b 是 $a 的引用,指向同一个数据

$a = 200;   // 改 $a
echo "a=$a, b=$b"; // $b 也跟着变
?>

输出

a=200, b=200

注意!这个操作要小心——改了 $a,$b 也变了;改了 $b,$a 也变了。如果你不想要这种「双胞胎」效果,别用引用。


🔥 实战 35 分钟:3 个递进小项目

项目 1(5 分钟):个人信息的「自我介绍卡」

场景:做一个输出个人信息的小工具,换个人改改变量就能用。

<?php
// 个人信息变量
$name = "李明";
$age = 28;
$city = "上海";
$job = "前端工程师";
$salary = 15000.5;

// 输出自我介绍
echo "=== 个人介绍 ===\n";
echo "姓名:" . $name . "\n";
echo "年龄:" . $age . "岁\n";
echo "所在城市:" . $city . "\n";
echo "职业:" . $job . "\n";
echo "月薪:" . $salary . "元\n";
echo "================\n";

// 计算年薪
$yearly_salary = $salary * 12;
echo "年薪约:" . $yearly_salary . "元\n";
?>

输出

=== 个人介绍 ===
姓名:李明
年龄:28岁
所在城市:上海
职业:前端工程师
月薪:15000.5元
================
年薪约:180006元

一行改,全家改动——把 $name 换成「王五」,整个自我介绍就变成王五的了。


项目 2(15 分钟):购物车价格计算器

场景:从「购物车」里拿出商品,计算总价和折扣。

<?php
// 定义常量:税率和折扣门槛
const TAX_RATE = 0.13;
const DISCOUNT_THRESHOLD = 500;   // 满500打9折
const DISCOUNT_RATE = 0.9;

// 购物车里的商品(模拟数据)
$cart = [
["name" => "iPhone 15", "price" => 5999, "qty" => 1],
["name" => "AirPods Pro", "price" => 1899, "qty" => 2],
["name" => "手机壳", "price" => 59, "qty" => 3],
];

// 计算小计
$subtotal = 0;
echo "购物车清单:\n";
echo str_repeat("-", 30) . "\n";

foreach ($cart as $item) {
$item_total = $item["price"] * $item["qty"];
$subtotal += $item_total;
echo sprintf(
    "%-15s 单价:%6.2f x %d = %7.2f\n",
    $item["name"], $item["price"], $item["qty"], $item_total
);
}

echo str_repeat("-", 30) . "\n";
echo sprintf("%-15s %14.2f\n", "商品合计:", $subtotal);

// 判断是否打折
if ($subtotal >= DISCOUNT_THRESHOLD) {
$subtotal = $subtotal * DISCOUNT_RATE;
echo "已享折扣!折后价:{$subtotal}\n";
}

// 计算税额
$tax = $subtotal * TAX_RATE;
$total = $subtotal + $tax;

echo sprintf("%-15s %14.2f\n", "税额(13%):", $tax);
echo sprintf("%-15s %14.2f\n", "应付总额:", $total);
?>

输出

购物车清单:
------------------------------
iPhone 15       单价:5999.00 x 1 = 5999.00
AirPods Pro     单价:1899.00 x 2 = 3798.00
手机壳          单价:  59.00 x 3 =  177.00
------------------------------
商品合计:          9974.00
已享折扣!折后价:8976.6
税额(13%):         1166.96
应付总额:         10143.56

这个脚本把常量(税率、折扣规则)和变量(商品数据)结合起来,模拟了真实的购物车逻辑。


项目 3(15 分钟):学生成绩统计小工具

场景:读取学生成绩单,计算平均分、最高分,判断是否全及格。

<?php
// 模拟的学生成绩数据(实际可以从CSV/JSON读入)
$students = [
["name" => "张三", "chinese" => 85, "math" => 92, "english" => 78],
["name" => "李四", "chinese" => 73, "math" => 88, "english" => 91],
["name" => "王五", "chinese" => 95, "math" => 67, "english" => 82],
["name" => "赵六", "chinese" => 60, "math" => 75, "english" => 58],
];

const PASS_SCORE = 60;  // 及格线

echo "=== 学生成绩统计 ===\n\n";

// 遍历统计每个人
$total_avg = 0;
$class_total = 0;
$all_passed = true;
$top_student = "";
$top_avg = 0;

foreach ($students as $student) {
// 计算该学生平均分
$avg = ($student["chinese"] + $student["math"] + $student["english"]) / 3;
$class_total += $avg;

// 判断是否有不及格
$has_fail = $student["chinese"] < PASS_SCORE
          || $student["math"] < PASS_SCORE
          || $student["english"] < PASS_SCORE;

if ($has_fail) {
    $all_passed = false;
}

// 找最高平均分学生
if ($avg > $top_avg) {
    $top_avg = $avg;
    $top_student = $student["name"];
}

// 输出该学生成绩
echo sprintf(
    "%s:语文=%d 数学=%d 英语=%d 平均=%.1f %s\n",
    $student["name"],
    $student["chinese"],
    $student["math"],
    $student["english"],
    $avg,
    $has_fail ? "❌有挂科" : "✓全部及格"
);
}

// 班级平均分
$class_avg = $class_total / count($students);

echo "\n--- 班级统计 ---\n";
echo "班级平均分:" . sprintf("%.1f", $class_avg) . "\n";
echo "最高平均分:" . $top_student . "(" . sprintf("%.1f", $top_avg) . "分)\n";
echo "全科及格:" . ($all_passed ? "是 ✓" : "否 ❌") . "\n";
?>

输出

=== 学生成绩统计 ===

张三:语文=85 数学=92 英语=78 平均=85.0 ✓全部及格
李四:语文=73 数学=88 英语=91 平均=84.0 ✓全部及格
王五:语文=95 数学=67 英语=82 平均=81.3 ✓全部及格
赵六:语文=60 数学=75 英语=58 平均=64.3 ❌有挂科

--- 班级统计 ---
班级平均分:78.6
最高平均分:张三(85.0分)
全科及格:否 ❌

这个项目把数组、循环、条件判断、变量、常量全部串起来了——这就是「会思考的代码」。


💪 进阶 20 分钟:常见坑 + 性能小贴士

坑 1:双引号和单引号的区别

<?php
// ❌ 错误:单引号不解析变量
$name = "小明";
echo '你好 $name';   // 输出:你好 $name(变量名原样输出)

// ✅ 正确:根据需求选引号
echo "你好 $name";   // 输出:你好 小明
echo '你好 ' . $name; // 输出:你好 小明(单引号拼接也行)
?>

坑 2:变量名大小写敏感

<?php
$Name = "张三";
$name = "李四";
echo $Name;  // 输出:张三
echo $name;  // 输出:李四(注意!这是两个不同的变量)
?>

PHP 变量 $name$Name 是两个人,不能混为一谈。

坑 3:整数除法会丢失小数

<?php
$a = 10;
$b = 3;
$result = $a / $b;

echo $result;        // 输出:3.3333333333333(浮点数)
echo gettype($result); // 输出:double(PHP7+自动转浮点)

// 如果你确实想要整数(向下取整)
echo floor($result);  // 输出:3
echo intval($result); // 输出:3
?>

坑 4:用 & 引用要小心

<?php
// ❌ 危险:循环里用引用,小心最后留下「尾巴」
$arr = [1, 2, 3];
foreach ($arr as &$value) {
$value = $value * 2;
}
print_r($arr); // [2, 4, 6]

// 这里如果继续用 $value,它还指向 $arr[2]!
$value = 100;
print_r($arr); // [2, 4, 100] (踩坑!)

// ✅ 安全:循环结束unset掉引用
unset($value);
?>

坑 5:常量名字拼写错误

<?php
// ❌ 易错:常量名写错不会报错,只会返回常量名当字符串
define("DB_HOST", "localhost");
echo DB_Host;  // 输出:DB_Host(写成了 DB_Host,PHP当字符串处理了)

// ✅ 正确:写完检查一下,或者用 const(IDE会提示)
const DB_HOST = "localhost";
// echo DB_Host;  // 如果IDE好,会直接标红
?>

性能小贴士:字符串拼接用双引号还是 .

<?php
// 少量拼接用 . 或双引号都行
$name = "小明";
echo "你好 " . $name;

// 大量拼接用 sprintf 或 heredoc 更高效
$sql = sprintf(
"SELECT * FROM users WHERE name='%s' AND age>%d",
$name, $age
);
?>

调试技巧:var_dump 是你的好朋友

<?php
$data = [
"name" => "iPhone",
"price" => 5999,
"in_stock" => true
];

// 看变量类型和值
var_dump($data);
// 输出:array(3) { ["name"]=> string(6) "iPhone" ... }

// 看单个值
echo $data["price"];

// 格式化输出
print_r($data);
?>

✏️ 练习题 + 作业题

练习题(5 道,10 分钟)

练习 1(1 分钟):换个名字
- 输入:把项目 1 里的 $name 改成你自己的名字
- 预期输出:自我介绍里显示你的名字
- 提示:找到 $name = "李明" 那一行,改掉引号里的字就行

练习 2(2 分钟):判断是否成年
- 输入:在项目 1 基础上加一个判断,如果 age >= 18 输出「已成年」,否则输出「未成年」
- 预期输出:年龄:28岁 下面多一行「已成年」
- 提示:用 if ($age >= 18) { ... }

练习 3(3 分钟):换个商品算折扣
- 输入:把项目 2 的购物车数据改成:耳机 299 x 2、键盘 599 x 1、鼠标 99 x 1
- 预期输出:总价不到 500,不享受折扣
- 提示:改 $cart 数组里的 namepriceqty

练习 4(2 分钟):找出不及格学生
- 输入:在项目 3 里,把「赵六」的成绩改成全部及格(70、75、72)
- 预期输出:「全科及格:是 ✓」
- 提示:改 $students 数组里最后一个元素

练习 5(2 分钟):看懂报错
- 输入:运行下面这段代码,分析为什么报错

<?php
$message = 'Hello World';
echo "$message";
?>
  • 预期输出:应该正常输出 Hello World,不会报错
  • 提示:如果报错了,想想引号有没有匹配

作业题(30 分钟 - 2 小时)

作业:做一个「个人理财小助手」

  • 需求描述:管理你一个月的收支,计算结余
  • 功能点
    1. 用变量存储「收入」和「支出」项目(至少 5 笔收入、5 笔支出)
    2. 用常量定义「月度预算上限」(比如 5000 元)
    3. 计算「总收入」「总支出」「本月结余」
    4. 判断「是否超支」,超支了显示超了多少
    5. 列出「最大一笔支出」是多少钱、干什么的
  • 加分项
    1. 用数组存多笔账目,包含「描述」和「金额」
    2. 输出格式整齐美观(用 sprintf 格式化)
  • 验收标准:能跑起来、输出正确、有注释
  • 提交方式:评论区贴代码或 GitHub 链接

📚 总结 + 资源

本文学了 3 件事
1. 变量是「会变的储物箱」,用 $ 开头,里面能放各种数据
2. 常量是「铁打的标签」,用 define()const 定义,定义完不能改
3. 数据类型决定了数据能做什么——字符串是文字、整数是小数点、布尔是是非

延伸学习
- PHP 官方文档:变量 ——最权威的参考
- 《PHP 核心技术与最佳实践》——进阶必备
- 视频:B 站「PHP 入门教程」系列(选播放量高的)

互动钩子:你在写代码时,最常搞混的是「单引号还是双引号」?还是「变量和常量什么时候用」?评论区聊聊,老粉优先回复!


下章预告:学会了存数据,下一章我们要学习「怎么把这些数据变成我们想要的样子」——字符串的拼接、截取、替换,还有 PHP 特有的 heredoc/nowdoc 语法,让你能优雅地写一大段文字。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。