PHP 数组工具类封装

wen PHP项目 4

本文目录导读:

PHP 数组工具类封装

  1. 完整版数组工具类
  2. 使用示例
  3. 扩展版本(更完整)

我来封装一个功能全面的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);
    }
}

这个工具类包含了:

  1. 基本操作:获取、设置、检查、删除(支持点语法)
  2. 数据处理:排序、分组、筛选、分页、去重
  3. 高级功能:扁平化、树形构建、XML转换、CSV转换
  4. 实用工具:统计、差异比较、占位符替换等

使用这个工具类可以大大提高PHP数组操作的效率和代码的可读性。

抱歉,评论功能暂时关闭!