本文目录导读:

我来封装一个功能全面的PHP数组工具类,包含常用且实用的数组操作方法。
完整版数组工具类
<?php
/**
* 数组工具类
*
* 提供常用数组操作的静态方法封装
*/
class ArrayUtil
{
/**
* 获取数组指定key的值,支持默认值和点语法
*
* @param array $array 数组
* @param string $key 键名,支持点语法如 'a.b.c'
* @param mixed $default 默认值
* @return mixed
*/
public static function get(array $array, $key, $default = null)
{
if (is_null($key)) {
return $array;
}
if (isset($array[$key])) {
return $array[$key];
}
// 点语法支持
if (strpos($key, '.') !== false) {
$keys = explode('.', $key);
foreach ($keys as $segment) {
if (!is_array($array) || !isset($array[$segment])) {
return $default;
}
$array = $array[$segment];
}
return $array;
}
return $default;
}
/**
* 设置数组指定key的值,支持点语法
*
* @param array $array 数组(引用传递)
* @param string $key 键名
* @param mixed $value 值
* @return void
*/
public static function set(array &$array, $key, $value)
{
if (is_null($key)) {
$array = $value;
return;
}
$keys = explode('.', $key);
while (count($keys) > 1) {
$key = array_shift($keys);
if (!isset($array[$key]) || !is_array($array[$key])) {
$array[$key] = [];
}
$array = &$array[$key];
}
$array[array_shift($keys)] = $value;
}
/**
* 检查数组中是否存在某个key
*
* @param array $array 数组
* @param string $key 键名
* @return bool
*/
public static function has(array $array, $key)
{
if (isset($array[$key])) {
return true;
}
if (strpos($key, '.') !== false) {
$keys = explode('.', $key);
foreach ($keys as $segment) {
if (!is_array($array) || !isset($array[$segment])) {
return false;
}
$array = $array[$segment];
}
return true;
}
return false;
}
/**
* 删除数组中的某个key
*
* @param array $array 数组(引用传递)
* @param string $key 键名
* @return void
*/
public static function remove(array &$array, $key)
{
if (isset($array[$key])) {
unset($array[$key]);
return;
}
if (strpos($key, '.') !== false) {
$keys = explode('.', $key);
$last = array_pop($keys);
$target = &$array;
foreach ($keys as $segment) {
if (!isset($target[$segment]) || !is_array($target[$segment])) {
return;
}
$target = &$target[$segment];
}
unset($target[$last]);
}
}
/**
* 数组去重(支持多维数组)
*
* @param array $array 数组
* @return array
*/
public static function unique(array $array)
{
$result = [];
foreach ($array as $key => $value) {
if (is_array($value)) {
$value = self::unique($value);
}
$result[$key] = $value;
}
// 使用序列化进行去重
$serialized = array_map('serialize', $result);
$unique = array_unique($serialized);
return array_intersect_key($result, $unique);
}
/**
* 扁平化多维数组
*
* @param array $array 多维数组
* @param string $prefix 前缀
* @return array
*/
public static function flatten(array $array, $prefix = '')
{
$result = [];
foreach ($array as $key => $value) {
if (is_array($value) && !empty($value)) {
$result = array_merge($result, self::flatten($value, $prefix . $key . '.'));
} else {
$result[$prefix . $key] = $value;
}
}
return $result;
}
/**
* 将扁平数组转换为多维数组
*
* @param array $array 扁平数组
* @return array
*/
public static function unflatten(array $array)
{
$result = [];
foreach ($array as $key => $value) {
self::set($result, $key, $value);
}
return $result;
}
/**
* 数组排序(支持按多个字段排序)
*
* @param array $array 数组
* @param string|array $field 排序字段或规则数组
* @param string $order 排序方式 ASC/DESC
* @param int $sortType 排序类型
* @return array
*/
public static function orderBy(array $array, $field, $order = 'ASC', $sortType = SORT_REGULAR)
{
if (empty($array)) {
return $array;
}
// 支持多字段排序
if (is_array($field)) {
$args = [];
foreach ($field as $f => $o) {
$args[] = array_column($array, $f);
$args[] = ($o === 'DESC') ? SORT_DESC : SORT_ASC;
$args[] = $sortType;
}
$args[] = &$array;
call_user_func_array('array_multisort', $args);
return $array;
}
$column = array_column($array, $field);
array_multisort($column, ($order === 'DESC' ? SORT_DESC : SORT_ASC), $sortType, $array);
return $array;
}
/**
* 分组数组
*
* @param array $array 数组
* @param string|callable $key 分组键或回调函数
* @return array
*/
public static function groupBy(array $array, $key)
{
$result = [];
foreach ($array as $item) {
if (is_callable($key)) {
$groupKey = $key($item);
} else {
$groupKey = $item[$key] ?? '';
}
$result[$groupKey][] = $item;
}
return $result;
}
/**
* 提取指定字段构成新数组
*
* @param array $array 原数组
* @param string|array $columns 字段名或多个字段
* @param bool $reindex 是否重新索引
* @return array
*/
public static function pluck(array $array, $columns, $reindex = true)
{
$result = [];
if (is_string($columns)) {
$columns = [$columns];
}
foreach ($array as $item) {
if (count($columns) === 1) {
$result[] = $item[$columns[0]] ?? null;
} else {
$row = [];
foreach ($columns as $col) {
$row[$col] = $item[$col] ?? null;
}
$result[] = $row;
}
}
if (!$reindex) {
$result = array_combine(array_keys($array), array_values($result));
}
return $result;
}
/**
* 根据条件筛选数组
*
* @param array $array 数组
* @param array $conditions 条件数组 ['field' => value] 或 ['field' => ['gt' => 5]]
* @return array
*/
public static function where(array $array, array $conditions)
{
return array_values(array_filter($array, function ($item) use ($conditions) {
foreach ($conditions as $key => $value) {
if (is_array($value)) {
$operator = array_key_first($value);
$compareValue = $value[$operator];
switch ($operator) {
case 'gt':
if (!($item[$key] ?? null) > $compareValue) return false;
break;
case 'lt':
if (!($item[$key] ?? null) < $compareValue) return false;
break;
case 'gte':
if (!($item[$key] ?? null) >= $compareValue) return false;
break;
case 'lte':
if (!($item[$key] ?? null) <= $compareValue) return false;
break;
case 'eq':
if (($item[$key] ?? null) != $compareValue) return false;
break;
case 'neq':
if (($item[$key] ?? null) == $compareValue) return false;
break;
case 'in':
if (!in_array($item[$key] ?? null, $compareValue)) return false;
break;
case 'not_in':
if (in_array($item[$key] ?? null, $compareValue)) return false;
break;
case 'contains':
if (strpos($item[$key] ?? '', $compareValue) === false) return false;
break;
default:
if (($item[$key] ?? null) != $value) return false;
}
} else {
if (($item[$key] ?? null) != $value) return false;
}
}
return true;
}));
}
/**
* 分页数组
*
* @param array $array 数组
* @param int $page 页码
* @param int $size 每页数量
* @return array ['data' => [], 'total' => int, 'page' => int, 'size' => int]
*/
public static function paginate(array $array, $page = 1, $size = 10)
{
$total = count($array);
$totalPages = ceil($total / $size);
$page = max(1, min($page, $totalPages));
$offset = ($page - 1) * $size;
$data = array_slice($array, $offset, $size);
return [
'data' => $data,
'total' => $total,
'page' => $page,
'size' => $size,
'total_pages' => $totalPages
];
}
/**
* 多维数组转单列
*
* @param array $array 数组
* @return array
*/
public static function toFlat($array)
{
$result = [];
array_walk_recursive($array, function ($value, $key) use (&$result) {
$result[] = $value;
});
return $result;
}
/**
* 二维数组根据某个字段去重
*
* @param array $array 二维数组
* @param string $field 去重字段
* @return array
*/
public static function distinct(array $array, $field)
{
$result = [];
$seen = [];
foreach ($array as $item) {
$value = $item[$field] ?? '';
if (!isset($seen[$value])) {
$seen[$value] = true;
$result[] = $item;
}
}
return $result;
}
/**
* 数组转XML
*
* @param array $array 数组
* @param string $root 根节点名称
* @param string $encoding 编码
* @return string
*/
public static function toXml(array $array, $root = 'root', $encoding = 'UTF-8')
{
$xml = '<?xml version="1.0" encoding="' . $encoding . '"?>';
$xml .= '<' . $root . '>';
$xml .= self::arrayToXml($array);
$xml .= '</' . $root . '>';
return $xml;
}
/**
* 数组转XML辅助方法
*
* @param array $array
* @return string
*/
private static function arrayToXml(array $array)
{
$xml = '';
foreach ($array as $key => $value) {
if (is_int($key)) {
$key = 'item';
}
if ($key === '@attributes') {
foreach ($value as $attrKey => $attrValue) {
$xml = str_replace('<' . $attrKey . '>', '<' . $attrKey . ' ' . $attrValue . '>', $xml);
}
continue;
}
if (is_array($value)) {
$childXml = self::arrayToXml($value);
$xml .= '<' . $key . '>' . $childXml . '</' . $key . '>';
} else {
$xml .= '<' . $key . '>' . htmlspecialchars($value) . '</' . $key . '>';
}
}
return $xml;
}
/**
* 按值搜索并返回key
*
* @param array $array 数组
* @param mixed $value 要搜索的值
* @param bool $strict 严格比较
* @return mixed 找到的key或false
*/
public static function searchValue(array $array, $value, $strict = false)
{
return array_search($value, $array, $strict);
}
/**
* 获取数组最后一个元素
*
* @param array $array 数组
* @return mixed
*/
public static function last(array $array)
{
return end($array);
}
/**
* 获取数组第一个元素
*
* @param array $array 数组
* @return mixed
*/
public static function first(array $array)
{
return reset($array);
}
/**
* 随机打乱关联数组(保留key)
*
* @param array $array 数组
* @return array
*/
public static function shuffleAssoc(array $array)
{
$keys = array_keys($array);
shuffle($keys);
$result = [];
foreach ($keys as $key) {
$result[$key] = $array[$key];
}
return $result;
}
/**
* 数组元素求和(支持多维)
*
* @param array $array 数组
* @return int|float
*/
public static function sum(array $array)
{
$sum = 0;
array_walk_recursive($array, function ($value) use (&$sum) {
$sum += $value;
});
return $sum;
}
/**
* 数组交集(支持多维)
*
* @param array $array1 第一个数组
* @param array $array2 第二个数组
* @return array
*/
public static function intersect(array $array1, array $array2)
{
return array_uintersect($array1, $array2, function($a, $b) {
return strcmp(serialize($a), serialize($b));
});
}
}
使用示例
<?php
// 引入工具类
// require_once 'ArrayUtil.php';
// ============ 基本操作 ============
$user = [
'name' => '张三',
'age' => 25,
'address' => [
'city' => '北京',
'district' => '海淀区',
'detail' => [
'street' => '中关村大街'
]
]
];
// 获取值(支持点语法)
echo ArrayUtil::get($user, 'name'); // 张三
echo ArrayUtil::get($user, 'address.city'); // 北京
echo ArrayUtil::get($user, 'address.detail.street'); // 中关村大街
echo ArrayUtil::get($user, 'email', '默认邮箱'); // 默认邮箱
// 设置值(支持点语法)
$newUser = [];
ArrayUtil::set($newUser, 'address.city', '上海');
ArrayUtil::set($newUser, 'address.code', '200000');
// 检查是否存在
var_dump(ArrayUtil::has($user, 'address.city')); // true
var_dump(ArrayUtil::has($user, 'phone')); // false
// ============ 数据处理 ============
$items = [
['id' => 1, 'name' => '商品A', 'price' => 100, 'category' => '电子产品'],
['id' => 2, 'name' => '商品B', 'price' => 200, 'category' => '服装'],
['id' => 3, 'name' => '商品C', 'price' => 150, 'category' => '电子产品'],
['id' => 4, 'name' => '商品D', 'price' => 80, 'category' => '食品'],
['id' => 5, 'name' => '商品E', 'price' => 300, 'category' => '电子产品'],
];
// 排序
$byPrice = ArrayUtil::orderBy($items, 'price', 'DESC');
$byCategoryAndPrice = ArrayUtil::orderBy($items, ['category' => 'ASC', 'price' => 'DESC']);
// 分组
$categoryGroup = ArrayUtil::groupBy($items, 'category');
$priceGroup = ArrayUtil::groupBy($items, function($item) {
return $item['price'] > 150 ? '高价' : '低价';
});
// 提取字段
$names = ArrayUtil::pluck($items, 'name');
$productInfo = ArrayUtil::pluck($items, ['id', 'name', 'price']);
// 条件筛选
$expensiveItems = ArrayUtil::where($items, ['price' => ['gt' => 150]]);
$electronicItems = ArrayUtil::where($items, ['category' => '电子产品']);
$combinedFilter = ArrayUtil::where($items, [
'category' => '电子产品',
'price' => ['lte' => 200]
]);
// 分页
$page1 = ArrayUtil::paginate($items, 1, 2);
$page2 = ArrayUtil::paginate($items, 2, 2);
// 去重
$mainItems = [
['id' => 1, 'name' => '商品A'],
['id' => 2, 'name' => '商品A'],
['id' => 3, 'name' => '商品B'],
];
$uniqueItems = ArrayUtil::distinct($mainItems, 'name');
// ============ 高级操作 ============
// 扁平化
$nestedArray = [
'a' => 1,
'b' => ['c' => 2, 'd' => ['e' => 3]],
'f' => 4
];
$flattened = ArrayUtil::flatten($nestedArray);
print_r($flattened);
// 输出: ['a' => 1, 'b.c' => 2, 'b.d.e' => 3, 'f' => 4]
// 反转扁平化
$unflattened = ArrayUtil::unflatten($flattened);
print_r($unflattened);
// 数组转XML
$xmlData = [
'user' => ['name' => '张三', 'age' => 25],
'items' => [['id' => 1], ['id' => 2]]
];
$xml = ArrayUtil::toXml($xmlData, 'response');
echo $xml;
// 其他工具方法
$numbers = [5, 3, 8, 1, 9];
echo ArrayUtil::sum($numbers); // 26
echo ArrayUtil::first($numbers); // 5
echo ArrayUtil::last($numbers); // 9
echo ArrayUtil::searchValue($numbers, 8); // 2
$shuffled = ArrayUtil::shuffleAssoc($numbers);
print_r($shuffled);
扩展版本(更完整)
<?php
/**
* 扩展的数组工具类
* 增加更多实用功能
*/
class ExtendedArrayUtil extends ArrayUtil
{
/**
* 递归合并数组(更深层次的合并)
*
* @param array $array1 第一个数组
* @param array $array2 第二个数组
* @return array
*/
public static function deepMerge(array $array1, array $array2)
{
foreach ($array2 as $key => $value) {
if (isset($array1[$key]) && is_array($array1[$key]) && is_array($value)) {
$array1[$key] = self::deepMerge($array1[$key], $value);
} else {
$array1[$key] = $value;
}
}
return $array1;
}
/**
* 数组转对象
*
* @param array $array 数组
* @return object
*/
public static function toObject(array $array)
{
return json_decode(json_encode($array));
}
/**
* 对象转数组
*
* @param object $object 对象
* @return array
*/
public static function fromObject($object)
{
return json_decode(json_encode($object), true);
}
/**
* 移除数组中的空值(null, '', false, [])
*
* @param array $array 数组
* @return array
*/
public static function removeEmpty(array $array)
{
return array_filter($array, function($value) {
return !is_null($value) && $value !== '' && $value !== false && $value !== [];
});
}
/**
* 将数组转为查询字符串
*
* @param array $array 数组
* @return string
*/
public static function toQueryString(array $array)
{
$flattened = self::flatten($array);
$pairs = [];
foreach ($flattened as $key => $value) {
$pairs[] = urlencode($key) . '=' . urlencode($value);
}
return implode('&', $pairs);
}
/**
* 从查询字符串解析为数组
*
* @param string $queryString 查询字符串
* @return array
*/
public static function fromQueryString($queryString)
{
parse_str($queryString, $result);
return $result;
}
/**
* 在两个数组中查找差异(支持多维)
*
* @param array $array1 第一个数组
* @param array $array2 第二个数组
* @return array
*/
public static function diff(array $array1, array $array2)
{
$result = [];
// 查找在第一个数组但不在第二个数组中的元素
foreach ($array1 as $key => $value) {
if (!isset($array2[$key])) {
$result['only_in_first'][$key] = $value;
} elseif (is_array($value) && is_array($array2[$key])) {
$diff = self::diff($value, $array2[$key]);
if (!empty($diff)) {
$result['different'][$key] = $diff;
}
} elseif ($value != $array2[$key]) {
$result['different'][$key] = [
'first' => $value,
'second' => $array2[$key]
];
}
}
// 查找在第二个数组但不在第一个数组中的元素
foreach ($array2 as $key => $value) {
if (!isset($array1[$key])) {
$result['only_in_second'][$key] = $value;
}
}
return $result;
}
/**
* 生成指定范围的数字数组
*
* @param int $start 开始值
* @param int $end 结束值
* @param int $step 步长
* @return array
*/
public static function range($start, $end, $step = 1)
{
return range($start, $end, $step);
}
/**
* 数组转CSV字符串
*
* @param array $array 二维数组
* @param string $delimiter 分隔符
* @return string
*/
public static function toCsv(array $array, $delimiter = ',')
{
$output = '';
$firstRow = true;
foreach ($array as $row) {
if (!$firstRow) {
$output .= "\n";
}
$output .= implode($delimiter, array_map(function($value) {
return '"' . str_replace('"', '""', $value) . '"';
}, $row));
$firstRow = false;
}
return $output;
}
/**
* 数组转JSON字符串(带格式化和错误处理)
*
* @param array $array 数组
* @param bool $prettyPrint 是否格式化
* @return string|false
*/
public static function toJson(array $array, $prettyPrint = false)
{
$flags = JSON_UNESCAPED_UNICODE;
if ($prettyPrint) {
$flags |= JSON_PRETTY_PRINT;
}
$json = json_encode($array, $flags);
// 处理编码错误
if ($json === false && json_last_error() === JSON_ERROR_UTF8) {
$array = self::recursiveUtf8Encode($array);
$json = json_encode($array, $flags);
}
return $json;
}
/**
* 递归处理UTF-8编码
*
* @param array $array 数组
* @return array
*/
private static function recursiveUtf8Encode(array $array)
{
foreach ($array as $key => $value) {
if (is_array($value)) {
$array[$key] = self::recursiveUtf8Encode($value);
} elseif (is_string($value)) {
$array[$key] = utf8_encode($value);
}
}
return $array;
}
/**
* 数组替换占位符
*
* @param array $array 数组
* @param string $pattern 占位符模式,如 {name}
* @return array
*/
public static function replacePlaceholders(array $array, $placeholderPattern = '/{(.*?)}/')
{
$result = [];
array_walk_recursive($array, function($value, $key) use (&$result) {
if (is_string($value)) {
$value = preg_replace_callback($placeholderPattern, function($matches) use (&$result) {
return $result[$matches[1]] ?? $matches[0];
}, $value);
}
$result[$key] = $value;
});
return $result;
}
/**
* 数组统计(最大值、最小值、平均值、中位数)
*
* @param array $array 一维数组
* @return array
*/
public static function statistics(array $array)
{
if (empty($array)) {
return [];
}
sort($array);
$count = count($array);
$middle = floor($count / 2);
return [
'max' => max($array),
'min' => min($array),
'avg' => array_sum($array) / $count,
'median' => ($count % 2) ? $array[$middle] : (($array[$middle - 1] + $array[$middle]) / 2),
'count' => $count,
'sum' => array_sum($array),
];
}
/**
* 建立树形结构
*
* @param array $items 数据项列表
* @param int $parentId 父级ID
* @param string $idField ID字段名
* @param string $parentField 父级ID字段名
* @param string $childrenField 子级字段名
* @return array
*/
public static function buildTree(
array $items,
$parentId = 0,
$idField = 'id',
$parentField = 'parent_id',
$childrenField = 'children'
) {
$tree = [];
$itemsByParent = [];
foreach ($items as $item) {
$itemsByParent[$item[$parentField]][] = $item;
}
$build = function ($parentId) use (&$build, &$itemsByParent, $idField, $childrenField) {
$branch = [];
if (isset($itemsByParent[$parentId])) {
foreach ($itemsByParent[$parentId] as $item) {
$item[$childrenField] = $build($item[$idField]);
$branch[] = $item;
}
}
return $branch;
};
return $build($parentId);
}
}
这个工具类包含了:
- 基本操作:获取、设置、检查、删除(支持点语法)
- 数据处理:排序、分组、筛选、分页、去重
- 高级功能:扁平化、树形构建、XML转换、CSV转换
- 实用工具:统计、差异比较、占位符替换等
使用这个工具类可以大大提高PHP数组操作的效率和代码的可读性。