array_column($rows, $column) 从一组行的每一行中取出 $column 的值。它把一张记录表变成只含一个字段的一维数组,这正是在使用 implode、in_array、array_sum 或 array_search 之前需要做的。
<?php
$users = [
["id" => 3, "name" => "Ada", "email" => "ada@example.com"],
["id" => 7, "name" => "Bob", "email" => "bob@example.com"],
["id" => 9, "name" => "Cy", "email" => "cy@example.com"],
];
$emails = array_column($users, "email");
print_r($emails);
echo implode(", ", array_column($users, "name")), "\n";Master PHP the hands-on way
Interactive lessons, real projects, and instant feedback.
START NOW
这些行可以来自任何地方:解码后的 JSON 响应、CSV 文件,或者返回关联数组组成的数组的数据库查询。
用索引键生成键值对
第三个参数指定一个字段,它的值会成为每个结果的键。array_column($users, 'name', 'id') 是生成“id 对应名字”查找表的常用写法,例如用来生成 <select> 下拉列表。
<?php
$users = [
["id" => 3, "name" => "Ada", "role" => "admin"],
["id" => 7, "name" => "Bob", "role" => "editor"],
["id" => 9, "name" => "Cy", "role" => "viewer"],
];
$names = array_column($users, "name", "id");
print_r($names);
echo $names[7], "\n";
如果两行的索引值相同,后面的行会覆盖前面的行。
用 null 按 id 索引整行
把列参数设为 null,就会保留每一整行,并用索引字段重新设置键。之后按 id 查找某一行就是直接访问键,不需要循环。
<?php
$products = [
["sku" => "A12", "name" => "Lamp", "price" => 29],
["sku" => "B07", "name" => "Desk", "price" => 199],
["sku" => "C33", "name" => "Chair", "price" => 89],
];
$bySku = array_column($products, null, "sku");
$sku = "B07";
if (isset($bySku[$sku])) {
echo "{$bySku[$sku]['name']} costs {$bySku[$sku]['price']}\n";
}
print_r(array_keys($bySku));
索引只需建立一次,之后的每次查找都是瞬间完成的,当你在循环中查找很多 id 时,这一点很重要。
用 array_column 和 array_search 查找一行
要找出哪一行包含某个值,就在这一列中搜索,然后使用返回的位置。用 !== false 检查结果,因为匹配到第一行时返回的是 0。
<?php
$users = [
["name" => "Ada", "email" => "ada@example.com"],
["name" => "Bob", "email" => "bob@example.com"],
["name" => "Cy", "email" => "cy@example.com"],
];
$wanted = "bob@example.com";
$index = array_search($wanted, array_column($users, "email"));
if ($index !== false) {
echo "Found: {$users[$index]['name']} at position $index\n";
} else {
echo "No user with $wanted\n";
}
// Just checking existence
var_dump(in_array("zoe@example.com", array_column($users, "email"), true));
这依赖于 $users 的键是 0, 1, 2,因为 array_column 返回的是一个列表。如果数组被过滤过、键不连续,先调用 array_values($users)。array_search 一页详细讲解了 false 和 0 的陷阱。
对一列求和、计数或求平均值
array_column 和数学辅助函数配合得很好:先取出字段,再把它们加起来。
<?php
$cart = [
["item" => "Book", "qty" => 2, "price" => 12.5],
["item" => "Pen", "qty" => 10, "price" => 1.2],
["item" => "Bag", "qty" => 1, "price" => 30.0],
];
$qtys = array_column($cart, "qty");
echo "Items: " . array_sum($qtys) . "\n";
$prices = array_column($cart, "price");
echo "Most expensive: " . max($prices) . "\n";
echo "Average price: " . round(array_sum($prices) / count($prices), 2) . "\n";
$total = array_sum(array_map(fn($row) => $row["qty"] * $row["price"], $cart));
echo "Total: $total\n";
如果值要由多个字段计算得出,比如数量乘以价格,就该用 array_map,如最后一行所示。
在对象上使用 array_column
对于一组对象,array_column 读取的是 public 属性。private 和 protected 属性对它不可见。
<?php
class User
{
public function __construct(
public int $id,
public string $name,
private string $password,
) {}
}
$users = [
new User(1, "Ada", "x"),
new User(2, "Bob", "y"),
];
print_r(array_column($users, "name", "id"));
var_dump(array_column($users, "password"));
第二次调用返回了一个空数组:password 是 private 属性,所以每个对象都被跳过了。
缺少字段的行会被跳过
对于缺少该字段的行,array_column 不会补上占位值。结果可能比输入短,所以它的位置和原来的行就对不上了。
<?php
$people = [
["name" => "Ada", "phone" => "555-0101"],
["name" => "Bob"],
["name" => "Cy", "phone" => "555-0199"],
];
print_r(array_column($people, "phone"));
// Keep the link to each person with an index key
print_r(array_column($people, "phone", "name"));
第一个结果有两个电话号码,却看不出 Bob 没有号码。用名字作为索引键,就能看出每个号码属于谁;只要某些行可能缺少这个字段,这种写法就更安全。