DataArray 类完整使用说明文档
类概述
DataArray 是一个强大的数组包装类,提供面向对象的数组操作方式,支持链式调用、点分隔符访问、通配符查找等高级功能。
主要特性
链式操作:大部分方法支持链式调用
智能查找:支持点分隔符和通配符查找
只读模式:防止数据被意外修改
多种构造:支持从JSON、对象、查询字符串创建
丰富操作:包含排序、过滤、映射等完整数组操作
强大搜索:支持递归搜索、通配符搜索、回调搜索
安装和实例化
基础实例化
use zxf\Util\Array\DataArray;
// 1. 基础实例化
$data = new DataArray(['name' => 'John', 'age' => 30]);
// 2. 从JSON创建
$jsonData = DataArray::fromJson('{"user": {"name": "John", "age": 30}}');
// 3. 从对象创建
$user = new stdClass();
$user->name = 'John';
$objectData = DataArray::fromObject($user);
// 4. 从查询字符串创建
$queryData = DataArray::fromQueryString('name=John&age=30&skills[]=php&skills[]=js');
// 5. 创建只读实例
$readOnlyData = DataArray::readOnly(['config' => 'value']);
空数组实例化
基础数据访问
基本访问方式
$data = new DataArray([
'user' => [
'name' => 'John',
'profile' => [
'age' => 30,
'email' => 'john@example.com'
]
],
'skills' => ['PHP', 'JavaScript', 'Python']
]);
// 1. 方法访问
echo $data->get('user.name'); // John
echo $data->get('user.profile.email'); // john@example.com
// 2. 数组式访问
echo $data['user.name']; // John
echo $data['user.profile.age']; // 30
// 3. 属性式访问(返回DataArray实例用于链式调用)
echo $data->user->name; // John
数据设置和修改
// 设置值
$data->set('user.location', 'New York');
$data['user.profile.phone'] = '123-456-7890';
// 批量设置
$data->add([
'user.profile.company' => 'Tech Corp',
'user.profile.title' => 'Developer'
]);
// 删除数据
$data->delete('user.profile.phone');
unset($data['user.profile.company']);
// 批量删除
$data->deleteMultiple(['user.location', 'user.profile.title']);
存在性检查
高级数据访问
通配符查找
$data = new DataArray([
'users' => [
'user1' => ['name' => 'John', 'age' => 30],
'user2' => ['name' => 'Jane', 'age' => 25],
'group' => [
'user3' => ['name' => 'Bob', 'age' => 35]
]
],
'products' => [
'product1' => ['name' => 'Phone', 'price' => 999],
'product2' => ['name' => 'Laptop', 'price' => 1999]
]
]);
// 单级通配符 (*) - 下一级的所有匹配
$userNames = $data->get('users.*.name');
// 返回: ['John', 'Jane'] (不包含Bob)
// 多级通配符 (**) - 任意深度的所有匹配
$allNames = $data->get('users.**.name');
// 返回: ['John', 'Jane', 'Bob']
// 混合使用
$allPrices = $data->get('products.*.price');
// 返回: [999, 1999]
// 复杂通配符
$nestedData = $data->get('users.**.age');
// 返回: [30, 25, 35]
默认值处理
多层数据访问
$complexData = new DataArray([
'company' => [
'departments' => [
'engineering' => [
'teams' => [
'frontend' => ['members' => 5, 'tech' => 'React'],
'backend' => ['members' => 8, 'tech' => 'PHP']
]
],
'marketing' => [
'teams' => [
'social' => ['members' => 3, 'platform' => 'Twitter'],
'content' => ['members' => 4, 'platform' => 'Blog']
]
]
]
]
]);
// 深度访问
echo $complexData->get('company.departments.engineering.teams.backend.tech'); // PHP
// 通配符深度搜索
$allMembers = $complexData->get('company.departments.*.teams.*.members');
// 返回: [5, 8, 3, 4]
$allTech = $complexData->get('company.departments.**.tech');
// 返回: ['React', 'PHP']
数组操作
基本数组操作
$data = new DataArray(['a' => 1, 'b' => 2, 'c' => 3, 'd' => 2]);
// 键值操作
$keys = $data->keys(); // ['a', 'b', 'c', 'd']
$values = $data->values(); // [1, 2, 3, 2]
// 栈操作
$data->unshift('first'); // 在开头添加元素
$first = $data->shift(); // 移除并返回第一个元素
$data->push('last'); // 在末尾添加元素
$last = $data->pop(); // 移除并返回最后一个元素
// 首尾元素
$first = $data->first(); // 第一个元素
$last = $data->last(); // 最后一个元素
// 随机元素
$random = $data->random(); // 随机一个元素
$randoms = $data->random(3); // 随机三个元素
数组合并
$data1 = new DataArray(['a' => 1, 'b' => ['c' => 2]]);
$data2 = new DataArray(['b' => ['d' => 3], 'e' => 4]);
// 普通合并(覆盖相同键)
$data1->merge($data2);
// 结果: ['a' => 1, 'b' => ['d' => 3], 'e' => 4]
// 递归合并(合并数组内容)
$data1->mergeRecursive(new DataArray(['b' => ['c' => 5, 'f' => 6]]));
// 结果: ['a' => 1, 'b' => ['d' => 3, 'c' => 5, 'f' => 6], 'e' => 4]
// 合并普通数组
$data1->merge(['g' => 7, 'h' => 8]);
数组转换操作
$data = new DataArray([
['id' => 1, 'name' => 'John', 'department' => 'Engineering'],
['id' => 2, 'name' => 'Jane', 'department' => 'Marketing'],
['id' => 3, 'name' => 'Bob', 'department' => 'Engineering']
]);
// 获取列
$names = $data->column('name'); // ['John', 'Jane', 'Bob']
$idNameMap = $data->column('name', 'id'); // [1 => 'John', 2 => 'Jane', 3 => 'Bob']
// 分组
$byDepartment = $data->groupBy(function($item) {
return $item['department'];
});
/* 返回:
[
'Engineering' => [
['id' => 1, 'name' => 'John', 'department' => 'Engineering'],
['id' => 3, 'name' => 'Bob', 'department' => 'Engineering']
],
'Marketing' => [
['id' => 2, 'name' => 'Jane', 'department' => 'Marketing']
]
]
*/
// 分块
$chunks = $data->chunk(2); // 将数组分成每块2个元素
// 去重
$unique = $data->unique(); // 基于序列化去重
// 键值交换(仅支持字符串和整数)
$flipped = $data->flip();
搜索和查找
基础搜索
$data = new DataArray([
'users' => [
'john' => ['name' => 'John', 'age' => 30],
'jane' => ['name' => 'Jane', 'age' => 25],
'admin' => [
'root' => ['name' => 'Root', 'age' => 40]
]
]
]);
// 基础值搜索(返回第一个匹配的键)
$key = $data->search('Jane'); // 'users.jane.name'
// 递归值搜索(返回所有匹配路径)
$paths = $data->searchValueRecursive('John');
// 返回: ['users.john.name']
// 包含详细信息的递归搜索
$detailedResults = $data->searchValueRecursive('John', true, true);
/* 返回:
[
[
'path' => 'users.john.name',
'value' => 'John',
'key' => 'name'
]
]
*/
通配符键搜索
$data = new DataArray([
'user_name' => 'John',
'user_age' => 30,
'admin_name' => 'Jane',
'admin_role' => 'super',
'config' => [
'db_host' => 'localhost',
'db_port' => 3306,
'cache_ttl' => 3600
]
]);
// 搜索所有 user_ 开头的键
$userKeys = $data->searchKey('user_*');
// 返回: ['user_name', 'user_age']
// 搜索所有包含 'name' 的键
$nameKeys = $data->searchKey('*name*');
// 返回: ['user_name', 'admin_name']
// 搜索特定模式的键
$dbKeys = $data->searchKey('*.db_*');
// 返回: ['config.db_host', 'config.db_port']
回调函数搜索
$data = new DataArray([
'products' => [
'p1' => ['name' => 'iPhone', 'price' => 999, 'category' => 'electronics'],
'p2' => ['name' => 'MacBook', 'price' => 1999, 'category' => 'electronics'],
'p3' => ['name' => 'T-Shirt', 'price' => 29, 'category' => 'clothing'],
'p4' => ['name' => 'Shoes', 'price' => 89, 'category' => 'clothing']
]
]);
// 搜索价格大于100的产品
$expensiveProducts = $data->searchByCallback(function($value, $key, $path) {
return is_array($value) && isset($value['price']) && $value['price'] > 100;
});
/* 返回:
[
['name' => 'iPhone', 'price' => 999, 'category' => 'electronics'],
['name' => 'MacBook', 'price' => 1999, 'category' => 'electronics']
]
*/
// 搜索包含路径信息
$expensiveWithPaths = $data->searchByCallback(
function($value, $key, $path) {
return is_array($value) && isset($value['price']) && $value['price'] > 100;
},
true
);
/* 返回:
[
[
'path' => 'products.p1',
'key' => 'p1',
'value' => ['name' => 'iPhone', 'price' => 999, 'category' => 'electronics']
],
// ...
]
*/
高级搜索功能
// 搜索第一个匹配项
$firstMatch = $data->searchFirst('John');
// 返回第一个匹配的路径或元素
// 统计匹配数量
$count = $data->searchCount('electronics');
// 返回匹配的数量
// 递归获取所有键
$allKeys = $data->keysRecursive();
// 返回所有层级的键名
排序方法
基础排序
自定义排序
$data = new DataArray([
'user1' => ['name' => 'John', 'age' => 30],
'user2' => ['name' => 'Jane', 'age' => 25],
'user3' => ['name' => 'Bob', 'age' => 35]
]);
// 自定义值排序
$data->usort(function($a, $b) {
return $a['age'] <=> $b['age'];
});
// 自定义键排序
$data->uksort(function($a, $b) {
return strcmp($a, $b);
});
// 保持索引关联的自定义排序
$data->uasort(function($a, $b) {
return $a['name'] <=> $b['name'];
});
转换方法
数据格式转换
$data = new DataArray([
'user' => new DataArray(['name' => 'John']),
'skills' => ['PHP', 'JS'],
'config' => [
'nested' => new DataArray(['value' => 'test'])
]
]);
// 转换为普通数组(保持DataArray对象)
$array = $data->toArray();
// user 键对应的仍然是 DataArray 对象
// 递归转换为数组(所有DataArray对象都转换)
$recursiveArray = $data->toArrayRecursive();
// 所有层级的 DataArray 对象都转换为普通数组
// 转换为JSON
$json = $data->toJson();
$prettyJson = $data->toJson(JSON_PRETTY_PRINT);
// 转换为查询字符串
$queryString = $data->toQueryString();
// 清空数组
$data->clear(); // 清空所有数据
序列化方法
函数式编程
Map/Filter/Reduce
$data = new DataArray([1, 2, 3, 4, 5, 6]);
// Map - 对每个元素应用函数(返回新实例)
$doubled = $data->map(fn($n) => $n * 2); // [2, 4, 6, 8, 10, 12]
// Filter - 过滤元素(返回新实例)
$even = $data->filter(fn($n) => $n % 2 === 0); // [2, 4, 6]
// Reduce - 缩减为单一值
$sum = $data->reduce(fn($carry, $n) => $carry + $n, 0); // 21
// Each - 遍历执行(链式操作)
$data->each(function($value, $key) {
echo "Key: $key, Value: $value\n";
})->filter(fn($n) => $n > 3); // 链式调用
切片和遍历
// 数组切片(返回新实例)
$slice = $data->slice(1, 3); // 从索引1开始取3个元素
// 反向遍历
foreach ($data->reverse() as $key => $value) {
// 反向遍历数组
}
// 使用迭代器
$iterator = $data->getIterator();
foreach ($iterator as $key => $value) {
// 遍历数组
}
条件操作
$data = new DataArray([1, 2, 3, 4, 5]);
// When - 条件满足时执行
$result = $data->when(
count($data) > 3,
fn($d) => $d->filter(fn($n) => $n > 2),
fn($d) => $d->map(fn($n) => $n * 10)
);
// Unless - 条件不满足时执行
$result = $data->unless(
empty($data),
fn($d) => $d->sort(),
fn($d) => $d->add(['default' => 'value'])
);
// Pipe - 管道操作
$processed = $data->pipe(function($d) {
return $d->filter(fn($n) => $n > 2)
->map(fn($n) => $n * 10)
->toArray();
});
高级功能
只读模式
// 创建只读实例
$readOnly = DataArray::readOnly(['config' => 'value']);
try {
$readOnly->set('new_key', 'value'); // 抛出RuntimeException
} catch (RuntimeException $e) {
echo $e->getMessage(); // 不能修改只读的DataArray
}
// 创建可变副本
$mutable = $readOnly->mutable();
$mutable->set('new_key', 'value'); // 成功
// 创建副本
$copy = $readOnly->copy(); // 保持只读状态
// 检查只读状态
$isReadOnly = $readOnly->isReadOnly(); // true
链式操作
// 复杂的链式操作
$result = (new DataArray([5, 2, 8, 1, 9, 3, 2, 7]))
->filter(fn($n) => $n > 3) // [5, 8, 9, 7]
->unique() // [5, 8, 9, 7]
->map(fn($n) => $n * 2) // [10, 16, 18, 14]
->sort() // [10, 14, 16, 18]
->when(
count($data) > 2,
fn($d) => $d->slice(0, 2) // [10, 14]
)
->toArray();
调试方法
$data = new DataArray(['user' => ['name' => 'John', 'age' => 30]]);
// 调试输出(不终止)
$data->dump();
// 输出: array(1) { ['user'] => array(2) { ... } }
// 调试输出并终止
// $data->dd(); // 输出并终止脚本
// 链式调试
$data->filter(fn($v) => is_array($v))
->dump()
->map(fn($v) => array_keys($v))
->dd();