PHP $_GET 变量
Reading query string parameters, plus missing keys, type casting and array parameters.
Reading values
Requesting http://localhost/welcome.php?name=Tom&age=18 populates $_GET automatically.
<?php
// URL: welcome.php?name=Tom&age=18
echo $_GET["name"], "\n";
echo $_GET["age"], "\n";
var_dump($_GET["age"]);Tom
18
string(2) "18Note string(2) "18" — not an int. Arithmetic coerces, but comparisons can surprise you.
<?php
$age = (int)($_GET["age"] ?? 0);
echo $age + 1, "\n";
var_dump("18" == 18); // true,松散比较
var_dump("18" === 18); // false,类型不同19
bool(true)
bool(false)Missing parameters
Users delete query strings or hand-type wrong URLs. **Every $_GET access needs a fallback.**
<?php
// 不安全的写法:直接访问会产生 warning
// echo $_GET["name"];
// 写法一:空合并
echo $_GET["name"] ?? "匿名", "\n";
// 写法二:isset 判断
if (isset($_GET["name"])) {
echo "有 name 参数\n";
} else {
echo "没有 name 参数\n";
}
// 写法三:一次性取多个并给默认值
$params = array_merge(
["page" => 1, "size" => 10, "kw" => ""],
array_intersect_key($_GET, ["page" => 1, "size" => 1, "kw" => 1])
);
print_r($params);匿名
没有 name 参数
Array
(
[page] => 1
[size] => 10
[kw] =>
)The third pattern suits pagination and filter endpoints — defaults and allowlist in one place, extra params dropped.
Array parameters
?tag[]=php&tag[]=web makes $_GET["tag"] an array. ?tag[0]=php works too.
<?php
// URL: list.php?tag[]=php&tag[]=web&tag[]=db
$tags = $_GET["tag"] ?? [];
if (!is_array($tags)) {
$tags = [$tags]; // 容错:用户可能只传一个
}
$tags = array_values(array_filter(array_map("trim", $tags), fn($t) => $t !== ""));
echo implode(" | ", $tags), "\n";
echo count($tags), "\n";php | web | db
3?tag=abc so you get a string, breaking foreach. Always is_array() first.Pagination example
<?php
// URL: list.php?page=3
$page = max(1, (int)($_GET["page"] ?? 1));
$size = 10;
$total = 95;
$pages = (int)ceil($total / $size);
$page = min($page, $pages);
$offset = ($page - 1) * $size;
printf("第 %d/%d 页,偏移 %d,每页 %d 条\n", $page, $pages, $offset, $size);第 3/10 页,偏移 20,每页 10 条max(1, ...) guards against zero and negatives; min($page, $pages) clamps overflow. Both are mandatory or the SQL OFFSET breaks.
$offset must be an integer before it hits SQL. Casting is the reliable fix — LIMIT/OFFSET cannot use placeholders in most drivers.取值
访问 http://localhost/welcome.php?name=Tom&age=18 时,PHP 自动把查询串解析进 $_GET。
<?php
// URL: welcome.php?name=Tom&age=18
echo $_GET["name"], "\n";
echo $_GET["age"], "\n";
var_dump($_GET["age"]);Tom
18
string(2) "18注意 var_dump 打出的是 string(2) "18"——不是整数。直接做数学运算 PHP 会隐式转换,但比较时容易出问题。
<?php
$age = (int)($_GET["age"] ?? 0);
echo $age + 1, "\n";
var_dump("18" == 18); // true,松散比较
var_dump("18" === 18); // false,类型不同19
bool(true)
bool(false)参数缺失
用户可能删掉查询串,也可能手打一个错的 URL。**每个 $_GET 都要有兜底**。
<?php
// 不安全的写法:直接访问会产生 warning
// echo $_GET["name"];
// 写法一:空合并
echo $_GET["name"] ?? "匿名", "\n";
// 写法二:isset 判断
if (isset($_GET["name"])) {
echo "有 name 参数\n";
} else {
echo "没有 name 参数\n";
}
// 写法三:一次性取多个并给默认值
$params = array_merge(
["page" => 1, "size" => 10, "kw" => ""],
array_intersect_key($_GET, ["page" => 1, "size" => 1, "kw" => 1])
);
print_r($params);匿名
没有 name 参数
Array
(
[page] => 1
[size] => 10
[kw] =>
)第三种写法在做分页、筛选接口时很省事:默认值和白名单一次说清,多余参数自动忽略。
数组参数
查询串里写 ?tag[]=php&tag[]=web,$_GET["tag"] 就是数组。也可以写 ?tag[0]=php。
<?php
// URL: list.php?tag[]=php&tag[]=web&tag[]=db
$tags = $_GET["tag"] ?? [];
if (!is_array($tags)) {
$tags = [$tags]; // 容错:用户可能只传一个
}
$tags = array_values(array_filter(array_map("trim", $tags), fn($t) => $t !== ""));
echo implode(" | ", $tags), "\n";
echo count($tags), "\n";php | web | db
3?tag=abc 让你拿到字符串而不是数组,代码里 foreach 就报错。先 is_array() 判断是必需的。分页实例
<?php
// URL: list.php?page=3
$page = max(1, (int)($_GET["page"] ?? 1));
$size = 10;
$total = 95;
$pages = (int)ceil($total / $size);
$page = min($page, $pages);
$offset = ($page - 1) * $size;
printf("第 %d/%d 页,偏移 %d,每页 %d 条\n", $page, $pages, $offset, $size);第 3/10 页,偏移 20,每页 10 条max(1, ...) 防负数和 0,min($page, $pages) 防超出总页数。这两个夹取是分页必备,否则 OFFSET 算出负数会让 SQL 报错。
$offset 拼进 SQL 前必须是整数。(int) 强转就是最简单可靠的做法——LIMIT 和 OFFSET 不能用预处理占位符(除非用 PDO 的模拟模式)。