PHP $_GET 变量

Reading query string parameters, plus missing keys, type casting and array parameters.

Beginner
Key PointsValues in `$_GET` are always strings (or arrays of strings) — cast them yourself.

Reading values

Requesting http://localhost/welcome.php?name=Tom&age=18 populates $_GET automatically.

PHP
<?php
// URL: welcome.php?name=Tom&age=18
echo $_GET["name"], "\n";
echo $_GET["age"], "\n";
var_dump($_GET["age"]);
Output
Tom
18
string(2) "18

Note string(2) "18" — not an int. Arithmetic coerces, but comparisons can surprise you.

PHP
<?php
$age = (int)($_GET["age"] ?? 0);
echo $age + 1, "\n";

var_dump("18" == 18);      // true,松散比较
var_dump("18" === 18);     // false,类型不同
Output
19
bool(true)
bool(false)

Missing parameters

Users delete query strings or hand-type wrong URLs. **Every $_GET access needs a fallback.**

PHP
<?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);
Output
匿名
没有 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
<?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";
Output
php | web | db
3
Guard against type juggling. An attacker can send ?tag=abc so you get a string, breaking foreach. Always is_array() first.

Pagination example

PHP
<?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);
Output
第 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.

Friends & Partners