本章目标
- 掌握数组的基本概念和类型
- 学会创建和初始化数组
- 理解索引数组和关联数组的区别
- 掌握多维数组的使用
- 学会数组的遍历方法
- 掌握常用数组函数
- 了解数组的高级操作
5.1 数组基础
5.1.1 数组概念
<?php
// 数组是一个有序的映射,将值关联到键
// PHP中的数组实际上是一个有序映射
// 什么是数组?
// - 存储多个值的变量
// - 每个值都有一个键(索引)
// - 键可以是整数或字符串
// - 值可以是任何数据类型
// 数组的特点:
// 1. 动态大小
// 2. 混合数据类型
// 3. 键值对结构
// 4. 有序性
echo "PHP数组示例:\n";
// 简单数组示例
$fruits = ['apple', 'banana', 'orange'];
print_r($fruits);
// 关联数组示例
$person = [
'name' => '张三',
'age' => 25,
'email' => 'zhangsan@example.com'
];
print_r($person);
?>
5.1.2 数组类型
<?php
// 1. 索引数组(数值索引)
$indexedArray = [1, 2, 3, 4, 5];
$colors = ['red', 'green', 'blue'];
echo "索引数组:\n";
print_r($indexedArray);
print_r($colors);
// 2. 关联数组(字符串索引)
$associativeArray = [
'name' => '李四',
'age' => 30,
'city' => '北京'
];
echo "关联数组:\n";
print_r($associativeArray);
// 3. 混合数组(数值和字符串索引混合)
$mixedArray = [
0 => 'first',
'name' => '王五',
1 => 'second',
'age' => 28
];
echo "混合数组:\n";
print_r($mixedArray);
// 4. 多维数组
$multiArray = [
['张三', 25, '北京'],
['李四', 30, '上海'],
['王五', 28, '广州']
];
echo "多维数组:\n";
print_r($multiArray);
// 5. 嵌套关联数组
$nestedArray = [
'users' => [
[
'name' => '张三',
'profile' => [
'age' => 25,
'address' => [
'city' => '北京',
'district' => '朝阳区'
]
]
]
]
];
echo "嵌套关联数组:\n";
print_r($nestedArray);
?>
5.2 数组创建和初始化
5.2.1 创建数组的方法
<?php
// 方法1:使用array()函数
$array1 = array(1, 2, 3, 4, 5);
$array2 = array(
'name' => '张三',
'age' => 25
);
// 方法2:使用短数组语法[](PHP 5.4+)
$array3 = [1, 2, 3, 4, 5];
$array4 = [
'name' => '李四',
'age' => 30
];
// 方法3:逐个赋值
$array5 = [];
$array5[0] = 'first';
$array5[1] = 'second';
$array5['name'] = '王五';
// 方法4:使用range()函数
$numbers = range(1, 10); // [1, 2, 3, ..., 10]
$letters = range('a', 'z'); // ['a', 'b', 'c', ..., 'z']
$evens = range(2, 20, 2); // [2, 4, 6, ..., 20]
echo "range()创建的数组:\n";
print_r($numbers);
print_r($letters);
print_r($evens);
// 方法5:使用array_fill()函数
$filled = array_fill(0, 5, 'default'); // 5个'default'值
$keys = array_fill_keys(['a', 'b', 'c'], 0); // 指定键名
echo "array_fill()创建的数组:\n";
print_r($filled);
print_r($keys);
// 方法6:从字符串创建
$string = "apple,banana,orange";
$fruits = explode(',', $string);
echo "从字符串创建的数组:\n";
print_r($fruits);
// 方法7:从其他数组创建
$original = [1, 2, 3];
$copy = $original; // 复制
$slice = array_slice($original, 1, 2); // 切片
echo "从其他数组创建:\n";
print_r($copy);
print_r($slice);
?>
5.2.2 数组初始化技巧
<?php
// 1. 预定义大小的数组
function createFixedArray($size, $defaultValue = null) {
return array_fill(0, $size, $defaultValue);
}
$fixedArray = createFixedArray(10, 0);
echo "固定大小数组:\n";
print_r($fixedArray);
// 2. 二维数组初始化
function create2DArray($rows, $cols, $defaultValue = 0) {
$array = [];
for ($i = 0; $i < $rows; $i++) {
$array[$i] = array_fill(0, $cols, $defaultValue);
}
return $array;
}
$matrix = create2DArray(3, 4, 0);
echo "二维数组:\n";
print_r($matrix);
// 3. 使用回调函数初始化
function initializeWithCallback($size, $callback) {
$array = [];
for ($i = 0; $i < $size; $i++) {
$array[$i] = $callback($i);
}
return $array;
}
$squares = initializeWithCallback(5, function($i) {
return $i * $i;
});
echo "使用回调初始化:\n";
print_r($squares);
// 4. 条件初始化
$conditionalArray = [];
for ($i = 1; $i <= 20; $i++) {
if ($i % 2 === 0) {
$conditionalArray[] = $i;
}
}
echo "条件初始化(偶数):\n";
print_r($conditionalArray);
// 5. 从配置文件初始化
$config = [
'database' => [
'host' => 'localhost',
'port' => 3306,
'username' => 'root',
'password' => '',
'database' => 'test'
],
'cache' => [
'driver' => 'redis',
'host' => '127.0.0.1',
'port' => 6379
]
];
echo "配置数组:\n";
print_r($config);
// 6. 使用生成器初始化大数组
function generateLargeArray($size) {
for ($i = 0; $i < $size; $i++) {
yield $i => $i * 2;
}
}
// 转换为数组
$largeArray = iterator_to_array(generateLargeArray(1000));
echo "大数组前10个元素:\n";
print_r(array_slice($largeArray, 0, 10, true));
?>
5.3 数组访问和修改
5.3.1 数组元素访问
<?php
$fruits = ['apple', 'banana', 'orange', 'grape'];
$person = [
'name' => '张三',
'age' => 25,
'email' => 'zhangsan@example.com'
];
// 1. 基本访问
echo "第一个水果:" . $fruits[0] . "\n"; // apple
echo "姓名:" . $person['name'] . "\n"; // 张三
// 2. 检查键是否存在
if (isset($fruits[1])) {
echo "第二个水果:" . $fruits[1] . "\n";
}
if (array_key_exists('age', $person)) {
echo "年龄:" . $person['age'] . "\n";
}
// 3. 使用null合并操作符(PHP 7+)
echo "电话:" . ($person['phone'] ?? '未提供') . "\n";
// 4. 动态键访问
$key = 'email';
echo "邮箱:" . $person[$key] . "\n";
// 5. 多维数组访问
$users = [
[
'name' => '张三',
'profile' => [
'age' => 25,
'address' => [
'city' => '北京',
'district' => '朝阳区'
]
]
]
];
echo "用户姓名:" . $users[0]['name'] . "\n";
echo "用户年龄:" . $users[0]['profile']['age'] . "\n";
echo "用户城市:" . $users[0]['profile']['address']['city'] . "\n";
// 6. 安全的多维数组访问
function getNestedValue($array, $keys, $default = null) {
foreach ($keys as $key) {
if (is_array($array) && array_key_exists($key, $array)) {
$array = $array[$key];
} else {
return $default;
}
}
return $array;
}
$city = getNestedValue($users, [0, 'profile', 'address', 'city'], '未知');
echo "安全访问城市:" . $city . "\n";
// 7. 使用变量变量访问
$arrayName = 'fruits';
$index = 0;
echo "变量变量访问:" . ${$arrayName}[$index] . "\n";
?>
5.3.2 数组元素修改
<?php
$fruits = ['apple', 'banana', 'orange'];
$person = ['name' => '张三', 'age' => 25];
// 1. 直接修改
$fruits[1] = 'mango'; // 修改现有元素
$fruits[3] = 'grape'; // 添加新元素
$person['age'] = 26; // 修改现有元素
$person['email'] = 'zhangsan@example.com'; // 添加新元素
echo "修改后的数组:\n";
print_r($fruits);
print_r($person);
// 2. 使用array_push()添加元素
array_push($fruits, 'kiwi', 'pear');
echo "使用array_push()后:\n";
print_r($fruits);
// 3. 使用[]操作符添加元素
$fruits[] = 'watermelon';
echo "使用[]添加后:\n";
print_r($fruits);
// 4. 使用array_unshift()在开头添加
array_unshift($fruits, 'strawberry');
echo "在开头添加后:\n";
print_r($fruits);
// 5. 删除元素
unset($fruits[2]); // 删除指定索引
unset($person['email']); // 删除指定键
echo "删除元素后:\n";
print_r($fruits);
print_r($person);
// 6. 使用array_pop()和array_shift()
$lastFruit = array_pop($fruits); // 删除并返回最后一个
$firstFruit = array_shift($fruits); // 删除并返回第一个
echo "删除的水果:$lastFruit, $firstFruit\n";
echo "删除后的数组:\n";
print_r($fruits);
// 7. 批量修改
$numbers = [1, 2, 3, 4, 5];
// 使用array_map()修改所有元素
$doubled = array_map(function($n) {
return $n * 2;
}, $numbers);
echo "翻倍后的数组:\n";
print_r($doubled);
// 8. 条件修改
$scores = [85, 92, 78, 96, 88];
for ($i = 0; $i < count($scores); $i++) {
if ($scores[$i] < 80) {
$scores[$i] += 5; // 给低分加5分
}
}
echo "调整后的分数:\n";
print_r($scores);
// 9. 多维数组修改
$users = [
['name' => '张三', 'age' => 25],
['name' => '李四', 'age' => 30]
];
$users[0]['age'] = 26; // 修改嵌套值
$users[1]['email'] = 'lisi@example.com'; // 添加嵌套值
echo "修改后的用户数组:\n";
print_r($users);
?>
5.4 数组遍历
5.4.1 基本遍历方法
<?php
$fruits = ['apple', 'banana', 'orange', 'grape'];
$person = [
'name' => '张三',
'age' => 25,
'email' => 'zhangsan@example.com'
];
// 1. for循环(仅适用于数值索引数组)
echo "使用for循环:\n";
for ($i = 0; $i < count($fruits); $i++) {
echo "$i: {$fruits[$i]}\n";
}
// 2. foreach循环(推荐)
echo "\n使用foreach循环(值):\n";
foreach ($fruits as $fruit) {
echo "$fruit\n";
}
echo "\n使用foreach循环(键值):\n";
foreach ($person as $key => $value) {
echo "$key: $value\n";
}
// 3. while循环配合each()(PHP 7.2后废弃)
// 使用current(), key(), next()替代
echo "\n使用while循环:\n";
reset($fruits); // 重置内部指针
while (($value = current($fruits)) !== false) {
$key = key($fruits);
echo "$key: $value\n";
next($fruits);
}
// 4. 使用array_walk()
echo "\n使用array_walk():\n";
array_walk($person, function($value, $key) {
echo "$key: $value\n";
});
// 5. 使用array_map()(返回新数组)
echo "\n使用array_map():\n";
$upperFruits = array_map('strtoupper', $fruits);
print_r($upperFruits);
// 6. 递归遍历多维数组
function printArrayRecursive($array, $level = 0) {
$indent = str_repeat(' ', $level);
foreach ($array as $key => $value) {
if (is_array($value)) {
echo "{$indent}$key:\n";
printArrayRecursive($value, $level + 1);
} else {
echo "{$indent}$key: $value\n";
}
}
}
$nestedArray = [
'user' => [
'name' => '张三',
'profile' => [
'age' => 25,
'address' => [
'city' => '北京',
'district' => '朝阳区'
]
]
]
];
echo "\n递归遍历多维数组:\n";
printArrayRecursive($nestedArray);
?>
5.4.2 高级遍历技巧
<?php
$products = [
['name' => '笔记本', 'price' => 5000, 'category' => '电子'],
['name' => '手机', 'price' => 3000, 'category' => '电子'],
['name' => '书籍', 'price' => 50, 'category' => '图书'],
['name' => '衣服', 'price' => 200, 'category' => '服装']
];
// 1. 条件遍历
echo "价格大于1000的产品:\n";
foreach ($products as $product) {
if ($product['price'] > 1000) {
echo "{$product['name']}: {$product['price']}元\n";
}
}
// 2. 分组遍历
$groupedProducts = [];
foreach ($products as $product) {
$category = $product['category'];
$groupedProducts[$category][] = $product;
}
echo "\n按类别分组:\n";
foreach ($groupedProducts as $category => $items) {
echo "$category:\n";
foreach ($items as $item) {
echo " {$item['name']}: {$item['price']}元\n";
}
}
// 3. 带索引的遍历
echo "\n带索引的遍历:\n";
foreach ($products as $index => $product) {
echo "第" . ($index + 1) . "个产品:{$product['name']}\n";
}
// 4. 引用遍历(修改原数组)
echo "\n给所有产品打9折:\n";
foreach ($products as &$product) {
$product['price'] *= 0.9;
}
unset($product); // 取消引用
foreach ($products as $product) {
echo "{$product['name']}: {$product['price']}元\n";
}
// 5. 多数组同时遍历
$names = ['张三', '李四', '王五'];
$ages = [25, 30, 28];
$cities = ['北京', '上海', '广州'];
echo "\n多数组同时遍历:\n";
$count = min(count($names), count($ages), count($cities));
for ($i = 0; $i < $count; $i++) {
echo "{$names[$i]}, {$ages[$i]}岁, 来自{$cities[$i]}\n";
}
// 6. 使用ArrayIterator
echo "\n使用ArrayIterator:\n";
$iterator = new ArrayIterator($products);
while ($iterator->valid()) {
$product = $iterator->current();
$index = $iterator->key();
echo "索引$index: {$product['name']}\n";
$iterator->next();
}
// 7. 自定义遍历函数
function forEachWithBreak($array, $callback) {
foreach ($array as $key => $value) {
$result = $callback($value, $key);
if ($result === false) {
break;
}
}
}
echo "\n自定义遍历(找到第一个电子产品就停止):\n";
forEachWithBreak($products, function($product, $index) {
echo "检查:{$product['name']}\n";
if ($product['category'] === '电子') {
echo "找到电子产品:{$product['name']}\n";
return false; // 停止遍历
}
return true;
});
?>
5.5 数组函数
5.5.1 数组信息函数
<?php
$fruits = ['apple', 'banana', 'orange'];
$numbers = [1, 2, 3, 4, 5];
$mixed = [1, 'hello', 3.14, true, null];
$empty = [];
// 1. 数组长度和大小
echo "数组长度:\n";
echo "count(fruits): " . count($fruits) . "\n"; // 3
echo "sizeof(numbers): " . sizeof($numbers) . "\n"; // 5 (count的别名)
echo "count(empty): " . count($empty) . "\n"; // 0
// 2. 数组类型检查
echo "\n数组类型检查:\n";
var_dump(is_array($fruits)); // true
var_dump(is_array('not array')); // false
// 3. 数组空值检查
echo "\n数组空值检查:\n";
var_dump(empty($empty)); // true
var_dump(empty($fruits)); // false
// 4. 键和值的存在性检查
echo "\n键和值的存在性检查:\n";
var_dump(array_key_exists(1, $fruits)); // true
var_dump(array_key_exists(5, $fruits)); // false
var_dump(in_array('apple', $fruits)); // true
var_dump(in_array('grape', $fruits)); // false
// 5. 搜索函数
echo "\n搜索函数:\n";
echo "array_search('banana', fruits): " . array_search('banana', $fruits) . "\n"; // 1
var_dump(array_search('grape', $fruits)); // false
// 6. 数组键和值
echo "\n数组键和值:\n";
print_r(array_keys($fruits)); // [0, 1, 2]
print_r(array_values($fruits)); // ['apple', 'banana', 'orange']
$person = ['name' => '张三', 'age' => 25];
print_r(array_keys($person)); // ['name', 'age']
print_r(array_values($person)); // ['张三', 25]
// 7. 数组统计
echo "\n数组统计:\n";
print_r(array_count_values(['a', 'b', 'a', 'c', 'b', 'a'])); // 统计值出现次数
// 8. 数组唯一性
echo "\n数组唯一性:\n";
$duplicates = [1, 2, 2, 3, 3, 3, 4];
print_r(array_unique($duplicates)); // [1, 2, 3, 4]
// 9. 数组比较
echo "\n数组比较:\n";
$array1 = [1, 2, 3];
$array2 = [1, 2, 3];
$array3 = [3, 2, 1];
var_dump($array1 == $array2); // true
var_dump($array1 === $array2); // true
var_dump($array1 == $array3); // false
// 10. 数组差集和交集
echo "\n数组差集和交集:\n";
$set1 = [1, 2, 3, 4, 5];
$set2 = [3, 4, 5, 6, 7];
print_r(array_diff($set1, $set2)); // [1, 2]
print_r(array_intersect($set1, $set2)); // [3, 4, 5]
?>
5.5.2 数组操作函数
<?php
// 1. 数组添加和删除
$fruits = ['apple', 'banana'];
echo "原始数组:\n";
print_r($fruits);
// 在末尾添加
array_push($fruits, 'orange', 'grape');
echo "\narray_push后:\n";
print_r($fruits);
// 在开头添加
array_unshift($fruits, 'mango', 'kiwi');
echo "\narray_unshift后:\n";
print_r($fruits);
// 从末尾删除
$lastFruit = array_pop($fruits);
echo "\n删除的最后一个:$lastFruit\n";
print_r($fruits);
// 从开头删除
$firstFruit = array_shift($fruits);
echo "\n删除的第一个:$firstFruit\n";
print_r($fruits);
// 2. 数组切片和拼接
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
echo "\n数组切片:\n";
print_r(array_slice($numbers, 2, 4)); // [3, 4, 5, 6]
print_r(array_slice($numbers, -3)); // [8, 9, 10]
print_r(array_slice($numbers, 1, -2)); // [2, 3, 4, 5, 6, 7, 8]
// 数组拼接(删除并插入)
$original = [1, 2, 3, 4, 5];
$removed = array_splice($original, 2, 2, ['a', 'b', 'c']);
echo "\n拼接后的数组:\n";
print_r($original); // [1, 2, 'a', 'b', 'c', 5]
echo "删除的元素:\n";
print_r($removed); // [3, 4]
// 3. 数组合并
echo "\n数组合并:\n";
$array1 = [1, 2, 3];
$array2 = [4, 5, 6];
$array3 = ['a' => 'apple', 'b' => 'banana'];
$array4 = ['b' => 'blueberry', 'c' => 'cherry'];
print_r(array_merge($array1, $array2)); // [1, 2, 3, 4, 5, 6]
print_r(array_merge($array3, $array4)); // 后面的值覆盖前面的
print_r($array1 + $array2); // [1, 2, 3] (+ 操作符不会重新索引)
// 4. 数组翻转和随机
echo "\n数组翻转和随机:\n";
$original = [1, 2, 3, 4, 5];
print_r(array_reverse($original)); // [5, 4, 3, 2, 1]
print_r(array_flip(['a' => 1, 'b' => 2])); // [1 => 'a', 2 => 'b']
$shuffled = $original;
shuffle($shuffled); // 随机打乱
print_r($shuffled);
// 5. 数组填充和重复
echo "\n数组填充和重复:\n";
print_r(array_fill(0, 5, 'default')); // 5个'default'
print_r(array_fill_keys(['a', 'b', 'c'], 0)); // 指定键名填充
print_r(array_pad([1, 2, 3], 6, 0)); // 填充到指定长度
print_r(array_repeat([1, 2], 3)); // 重复数组
// 6. 数组分块
echo "\n数组分块:\n";
$data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
print_r(array_chunk($data, 3)); // 每3个一组
print_r(array_chunk($data, 3, true)); // 保持键名
// 7. 数组组合
echo "\n数组组合:\n";
$keys = ['name', 'age', 'city'];
$values = ['张三', 25, '北京'];
print_r(array_combine($keys, $values)); // 组合成关联数组
?>
5.5.3 数组排序函数
<?php
// 1. 基本排序
$numbers = [3, 1, 4, 1, 5, 9, 2, 6];
$fruits = ['banana', 'apple', 'orange', 'grape'];
echo "原始数组:\n";
print_r($numbers);
print_r($fruits);
// 升序排序(重新索引)
$sorted1 = $numbers;
sort($sorted1);
echo "\nsort()升序:\n";
print_r($sorted1);
// 降序排序(重新索引)
$sorted2 = $numbers;
rsort($sorted2);
echo "\nrsort()降序:\n";
print_r($sorted2);
// 2. 保持键名的排序
$assoc = ['b' => 2, 'a' => 1, 'd' => 4, 'c' => 3];
echo "\n关联数组原始:\n";
print_r($assoc);
// 按值排序(保持键名)
$sorted3 = $assoc;
asort($sorted3);
echo "\nasort()按值升序:\n";
print_r($sorted3);
// 按值降序排序(保持键名)
$sorted4 = $assoc;
arsort($sorted4);
echo "\narsort()按值降序:\n";
print_r($sorted4);
// 按键排序
$sorted5 = $assoc;
ksort($sorted5);
echo "\nksort()按键升序:\n";
print_r($sorted5);
// 按键降序排序
$sorted6 = $assoc;
krsort($sorted6);
echo "\nkrsort()按键降序:\n";
print_r($sorted6);
// 3. 自定义排序
$students = [
['name' => '张三', 'score' => 85],
['name' => '李四', 'score' => 92],
['name' => '王五', 'score' => 78],
['name' => '赵六', 'score' => 96]
];
echo "\n学生原始数据:\n";
print_r($students);
// 使用usort()按分数排序
$sorted7 = $students;
usort($sorted7, function($a, $b) {
return $b['score'] - $a['score']; // 降序
});
echo "\n按分数降序排序:\n";
print_r($sorted7);
// 使用uasort()保持键名
$sorted8 = $students;
uasort($sorted8, function($a, $b) {
return strcmp($a['name'], $b['name']); // 按姓名字母顺序
});
echo "\n按姓名排序(保持键名):\n";
print_r($sorted8);
// 4. 多字段排序
function multiSort($array, $fields) {
usort($array, function($a, $b) use ($fields) {
foreach ($fields as $field => $order) {
$result = 0;
if (is_numeric($a[$field]) && is_numeric($b[$field])) {
$result = $a[$field] - $b[$field];
} else {
$result = strcmp($a[$field], $b[$field]);
}
if ($result !== 0) {
return $order === 'desc' ? -$result : $result;
}
}
return 0;
});
return $array;
}
$employees = [
['name' => '张三', 'department' => 'IT', 'salary' => 8000],
['name' => '李四', 'department' => 'HR', 'salary' => 6000],
['name' => '王五', 'department' => 'IT', 'salary' => 9000],
['name' => '赵六', 'department' => 'HR', 'salary' => 7000]
];
echo "\n员工原始数据:\n";
print_r($employees);
$sorted9 = multiSort($employees, [
'department' => 'asc',
'salary' => 'desc'
]);
echo "\n按部门升序、薪资降序排序:\n";
print_r($sorted9);
// 5. 自然排序
$versions = ['v1.10', 'v1.2', 'v1.1', 'v2.0', 'v1.20'];
echo "\n版本号原始:\n";
print_r($versions);
$sorted10 = $versions;
natsort($sorted10);
echo "\n自然排序:\n";
print_r($sorted10);
$sorted11 = $versions;
natcasesort($sorted11); // 忽略大小写的自然排序
echo "\n忽略大小写的自然排序:\n";
print_r($sorted11);
?>
5.5.4 数组过滤和映射函数
<?php
// 1. array_filter() - 过滤数组
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
echo "原始数组:\n";
print_r($numbers);
// 过滤偶数
$evens = array_filter($numbers, function($n) {
return $n % 2 === 0;
});
echo "\n偶数:\n";
print_r($evens);
// 过滤大于5的数
$greaterThan5 = array_filter($numbers, function($n) {
return $n > 5;
});
echo "\n大于5的数:\n";
print_r($greaterThan5);
// 过滤空值
$mixed = [1, '', 0, 'hello', null, false, 'world', []];
$filtered = array_filter($mixed); // 默认过滤"假"值
echo "\n过滤空值后:\n";
print_r($filtered);
// 使用ARRAY_FILTER_USE_KEY过滤键
$assoc = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4];
$keyFiltered = array_filter($assoc, function($key) {
return in_array($key, ['a', 'c']);
}, ARRAY_FILTER_USE_KEY);
echo "\n按键过滤:\n";
print_r($keyFiltered);
// 使用ARRAY_FILTER_USE_BOTH同时使用键和值
$bothFiltered = array_filter($assoc, function($value, $key) {
return $value > 2 && $key !== 'd';
}, ARRAY_FILTER_USE_BOTH);
echo "\n按键值过滤:\n";
print_r($bothFiltered);
// 2. array_map() - 映射数组
echo "\n=== array_map() 示例 ===\n";
// 基本映射
$squared = array_map(function($n) {
return $n * $n;
}, $numbers);
echo "\n平方:\n";
print_r($squared);
// 字符串处理
$words = ['hello', 'world', 'php', 'programming'];
$uppercase = array_map('strtoupper', $words);
echo "\n转大写:\n";
print_r($uppercase);
// 多个数组映射
$names = ['张三', '李四', '王五'];
$ages = [25, 30, 28];
$combined = array_map(function($name, $age) {
return "$name ($age岁)";
}, $names, $ages);
echo "\n组合信息:\n";
print_r($combined);
// 3. array_reduce() - 归约数组
echo "\n=== array_reduce() 示例 ===\n";
// 求和
$sum = array_reduce($numbers, function($carry, $item) {
return $carry + $item;
}, 0);
echo "\n数组求和:$sum\n";
// 求最大值
$max = array_reduce($numbers, function($carry, $item) {
return $item > $carry ? $item : $carry;
}, 0);
echo "最大值:$max\n";
// 字符串连接
$sentence = array_reduce($words, function($carry, $item) {
return $carry . ' ' . $item;
}, '');
echo "连接字符串:" . trim($sentence) . "\n";
// 构建关联数组
$products = [
['id' => 1, 'name' => '笔记本', 'price' => 5000],
['id' => 2, 'name' => '手机', 'price' => 3000],
['id' => 3, 'name' => '平板', 'price' => 2000]
];
$indexed = array_reduce($products, function($carry, $item) {
$carry[$item['id']] = $item;
return $carry;
}, []);
echo "\n按ID索引的产品:\n";
print_r($indexed);
// 4. array_walk() - 遍历数组
echo "\n=== array_walk() 示例 ===\n";
$prices = [100, 200, 300, 400];
// 修改数组值(需要引用)
array_walk($prices, function(&$value, $key) {
$value *= 1.1; // 涨价10%
});
echo "\n涨价后:\n";
print_r($prices);
// 带额外参数
array_walk($prices, function(&$value, $key, $tax) {
$value *= (1 + $tax);
}, 0.08); // 8%税率
echo "\n加税后:\n";
print_r($prices);
// 递归遍历
$nested = [
'user' => [
'name' => '张三',
'profile' => [
'age' => 25,
'city' => '北京'
]
]
];
array_walk_recursive($nested, function($value, $key) {
echo "$key: $value\n";
});
// 5. 组合使用
echo "\n=== 组合使用示例 ===\n";
$students = [
['name' => '张三', 'scores' => [85, 90, 88]],
['name' => '李四', 'scores' => [92, 87, 95]],
['name' => '王五', 'scores' => [78, 82, 80]]
];
// 计算每个学生的平均分,并过滤出平均分大于85的学生
$result = array_filter(
array_map(function($student) {
$average = array_sum($student['scores']) / count($student['scores']);
return [
'name' => $student['name'],
'average' => round($average, 2)
];
}, $students),
function($student) {
return $student['average'] > 85;
}
);
echo "平均分大于85的学生:\n";
print_r($result);
?>
5.6 多维数组
5.6.1 创建和访问多维数组
<?php
// 1. 二维数组
$matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
echo "二维数组:\n";
print_r($matrix);
// 访问二维数组元素
echo "\n访问元素:\n";
echo "matrix[1][2] = " . $matrix[1][2] . "\n"; // 6
// 修改二维数组元素
$matrix[0][0] = 10;
echo "修改后 matrix[0][0] = " . $matrix[0][0] . "\n";
// 2. 关联多维数组
$users = [
[
'id' => 1,
'name' => '张三',
'profile' => [
'age' => 25,
'email' => 'zhangsan@example.com',
'address' => [
'city' => '北京',
'district' => '朝阳区',
'street' => '建国路1号'
]
],
'skills' => ['PHP', 'JavaScript', 'MySQL']
],
[
'id' => 2,
'name' => '李四',
'profile' => [
'age' => 30,
'email' => 'lisi@example.com',
'address' => [
'city' => '上海',
'district' => '浦东新区',
'street' => '世纪大道100号'
]
],
'skills' => ['Python', 'Django', 'PostgreSQL']
]
];
echo "\n用户数据:\n";
print_r($users);
// 访问嵌套数据
echo "\n访问嵌套数据:\n";
echo "第一个用户姓名:" . $users[0]['name'] . "\n";
echo "第一个用户年龄:" . $users[0]['profile']['age'] . "\n";
echo "第一个用户城市:" . $users[0]['profile']['address']['city'] . "\n";
echo "第一个用户第一个技能:" . $users[0]['skills'][0] . "\n";
// 3. 动态创建多维数组
function createMatrix($rows, $cols, $defaultValue = 0) {
$matrix = [];
for ($i = 0; $i < $rows; $i++) {
for ($j = 0; $j < $cols; $j++) {
$matrix[$i][$j] = $defaultValue;
}
}
return $matrix;
}
$dynamicMatrix = createMatrix(3, 4, 1);
echo "\n动态创建的矩阵:\n";
print_r($dynamicMatrix);
// 4. 三维数组示例
$cube = [
[ // 第一层
[1, 2],
[3, 4]
],
[ // 第二层
[5, 6],
[7, 8]
]
];
echo "\n三维数组:\n";
print_r($cube);
echo "cube[1][0][1] = " . $cube[1][0][1] . "\n"; // 6
// 5. 表格数据结构
$table = [
'headers' => ['姓名', '年龄', '城市', '薪资'],
'rows' => [
['张三', 25, '北京', 8000],
['李四', 30, '上海', 12000],
['王五', 28, '广州', 10000]
]
];
echo "\n表格数据:\n";
echo "表头:";
print_r($table['headers']);
echo "数据行:\n";
foreach ($table['rows'] as $index => $row) {
echo "第" . ($index + 1) . "行:";
print_r($row);
}
?>
5.6.2 多维数组操作
<?php
// 1. 多维数组遍历
$products = [
[
'id' => 1,
'name' => '笔记本电脑',
'category' => '电子产品',
'specs' => [
'cpu' => 'Intel i7',
'memory' => '16GB',
'storage' => '512GB SSD'
],
'prices' => [
'cost' => 4000,
'retail' => 6000,
'discount' => 5500
]
],
[
'id' => 2,
'name' => '智能手机',
'category' => '电子产品',
'specs' => [
'cpu' => 'Snapdragon 888',
'memory' => '8GB',
'storage' => '256GB'
],
'prices' => [
'cost' => 2000,
'retail' => 3500,
'discount' => 3200
]
]
];
echo "产品信息遍历:\n";
foreach ($products as $product) {
echo "产品:{$product['name']}\n";
echo " 规格:\n";
foreach ($product['specs'] as $spec => $value) {
echo " $spec: $value\n";
}
echo " 价格:\n";
foreach ($product['prices'] as $type => $price) {
echo " $type: $price元\n";
}
echo "\n";
}
// 2. 多维数组搜索
function searchMultiArray($array, $key, $value) {
$results = [];
foreach ($array as $index => $item) {
if (isset($item[$key]) && $item[$key] === $value) {
$results[] = $item;
}
}
return $results;
}
$electronics = searchMultiArray($products, 'category', '电子产品');
echo "电子产品:\n";
print_r($electronics);
// 3. 多维数组排序
function sortMultiArray($array, $key, $order = 'asc') {
usort($array, function($a, $b) use ($key, $order) {
$valueA = $a[$key] ?? 0;
$valueB = $b[$key] ?? 0;
if ($order === 'desc') {
return $valueB <=> $valueA;
}
return $valueA <=> $valueB;
});
return $array;
}
// 按零售价排序
$sortedByPrice = sortMultiArray($products, 'prices');
// 注意:这里需要修改排序逻辑来处理嵌套数组
usort($products, function($a, $b) {
return $a['prices']['retail'] <=> $b['prices']['retail'];
});
echo "按零售价排序:\n";
foreach ($products as $product) {
echo "{$product['name']}: {$product['prices']['retail']}元\n";
}
// 4. 多维数组过滤
function filterMultiArray($array, $callback) {
return array_filter($array, $callback);
}
$expensiveProducts = filterMultiArray($products, function($product) {
return $product['prices']['retail'] > 5000;
});
echo "\n价格超过5000元的产品:\n";
foreach ($expensiveProducts as $product) {
echo "{$product['name']}: {$product['prices']['retail']}元\n";
}
// 5. 多维数组转换
function flattenArray($array, $prefix = '') {
$result = [];
foreach ($array as $key => $value) {
$newKey = $prefix ? $prefix . '.' . $key : $key;
if (is_array($value)) {
$result = array_merge($result, flattenArray($value, $newKey));
} else {
$result[$newKey] = $value;
}
}
return $result;
}
echo "\n扁平化第一个产品:\n";
$flattened = flattenArray($products[0]);
print_r($flattened);
// 6. 多维数组分组
function groupBy($array, $key) {
$groups = [];
foreach ($array as $item) {
$groupKey = $item[$key] ?? 'unknown';
$groups[$groupKey][] = $item;
}
return $groups;
}
$groupedProducts = groupBy($products, 'category');
echo "\n按类别分组:\n";
print_r($groupedProducts);
// 7. 多维数组统计
function getStatistics($array, $path) {
$values = [];
foreach ($array as $item) {
$value = $item;
foreach (explode('.', $path) as $key) {
if (isset($value[$key])) {
$value = $value[$key];
} else {
$value = null;
break;
}
}
if ($value !== null && is_numeric($value)) {
$values[] = $value;
}
}
if (empty($values)) {
return null;
}
return [
'count' => count($values),
'sum' => array_sum($values),
'average' => array_sum($values) / count($values),
'min' => min($values),
'max' => max($values)
];
}
echo "\n零售价统计:\n";
$priceStats = getStatistics($products, 'prices.retail');
print_r($priceStats);
?>
5.6.3 多维数组实际应用
<?php
// 1. 购物车系统
class ShoppingCart {
private $items = [];
public function addItem($productId, $name, $price, $quantity = 1) {
if (isset($this->items[$productId])) {
$this->items[$productId]['quantity'] += $quantity;
} else {
$this->items[$productId] = [
'name' => $name,
'price' => $price,
'quantity' => $quantity
];
}
}
public function removeItem($productId) {
unset($this->items[$productId]);
}
public function updateQuantity($productId, $quantity) {
if (isset($this->items[$productId])) {
if ($quantity <= 0) {
$this->removeItem($productId);
} else {
$this->items[$productId]['quantity'] = $quantity;
}
}
}
public function getTotal() {
$total = 0;
foreach ($this->items as $item) {
$total += $item['price'] * $item['quantity'];
}
return $total;
}
public function getItems() {
return $this->items;
}
public function getItemCount() {
$count = 0;
foreach ($this->items as $item) {
$count += $item['quantity'];
}
return $count;
}
}
$cart = new ShoppingCart();
$cart->addItem(1, '笔记本电脑', 6000, 1);
$cart->addItem(2, '鼠标', 100, 2);
$cart->addItem(3, '键盘', 300, 1);
echo "购物车内容:\n";
foreach ($cart->getItems() as $id => $item) {
echo "ID: $id, 商品: {$item['name']}, 单价: {$item['price']}元, 数量: {$item['quantity']}\n";
}
echo "总计:{$cart->getTotal()}元\n";
echo "商品总数:{$cart->getItemCount()}件\n\n";
// 2. 学生成绩管理系统
class GradeManager {
private $students = [];
public function addStudent($id, $name) {
$this->students[$id] = [
'name' => $name,
'subjects' => []
];
}
public function addGrade($studentId, $subject, $score) {
if (isset($this->students[$studentId])) {
if (!isset($this->students[$studentId]['subjects'][$subject])) {
$this->students[$studentId]['subjects'][$subject] = [];
}
$this->students[$studentId]['subjects'][$subject][] = $score;
}
}
public function getStudentAverage($studentId) {
if (!isset($this->students[$studentId])) {
return null;
}
$totalScore = 0;
$totalCount = 0;
foreach ($this->students[$studentId]['subjects'] as $scores) {
$totalScore += array_sum($scores);
$totalCount += count($scores);
}
return $totalCount > 0 ? $totalScore / $totalCount : 0;
}
public function getSubjectAverage($subject) {
$totalScore = 0;
$totalCount = 0;
foreach ($this->students as $student) {
if (isset($student['subjects'][$subject])) {
$totalScore += array_sum($student['subjects'][$subject]);
$totalCount += count($student['subjects'][$subject]);
}
}
return $totalCount > 0 ? $totalScore / $totalCount : 0;
}
public function getTopStudents($limit = 3) {
$averages = [];
foreach ($this->students as $id => $student) {
$averages[$id] = [
'name' => $student['name'],
'average' => $this->getStudentAverage($id)
];
}
// 按平均分降序排序
uasort($averages, function($a, $b) {
return $b['average'] <=> $a['average'];
});
return array_slice($averages, 0, $limit, true);
}
public function getStudents() {
return $this->students;
}
}
$gradeManager = new GradeManager();
$gradeManager->addStudent(1, '张三');
$gradeManager->addStudent(2, '李四');
$gradeManager->addStudent(3, '王五');
// 添加成绩
$gradeManager->addGrade(1, '数学', 85);
$gradeManager->addGrade(1, '数学', 90);
$gradeManager->addGrade(1, '英语', 88);
$gradeManager->addGrade(2, '数学', 92);
$gradeManager->addGrade(2, '英语', 85);
$gradeManager->addGrade(3, '数学', 78);
$gradeManager->addGrade(3, '英语', 82);
echo "学生平均分:\n";
foreach ($gradeManager->getStudents() as $id => $student) {
$average = $gradeManager->getStudentAverage($id);
echo "{$student['name']}: " . round($average, 2) . "分\n";
}
echo "\n数学平均分:" . round($gradeManager->getSubjectAverage('数学'), 2) . "分\n";
echo "英语平均分:" . round($gradeManager->getSubjectAverage('英语'), 2) . "分\n";
echo "\n前3名学生:\n";
$topStudents = $gradeManager->getTopStudents(3);
foreach ($topStudents as $id => $student) {
echo "{$student['name']}: " . round($student['average'], 2) . "分\n";
}
// 3. 配置管理系统
$config = [
'database' => [
'default' => [
'driver' => 'mysql',
'host' => 'localhost',
'port' => 3306,
'database' => 'myapp',
'username' => 'root',
'password' => '',
'charset' => 'utf8mb4',
'options' => [
'timeout' => 30,
'retry' => 3
]
],
'cache' => [
'driver' => 'redis',
'host' => '127.0.0.1',
'port' => 6379,
'database' => 0
]
],
'mail' => [
'driver' => 'smtp',
'host' => 'smtp.gmail.com',
'port' => 587,
'encryption' => 'tls',
'username' => 'user@gmail.com',
'password' => 'password'
],
'app' => [
'name' => 'My Application',
'version' => '1.0.0',
'debug' => true,
'timezone' => 'Asia/Shanghai',
'locale' => 'zh_CN'
]
];
function getConfig($path, $default = null) {
global $config;
$keys = explode('.', $path);
$value = $config;
foreach ($keys as $key) {
if (is_array($value) && array_key_exists($key, $value)) {
$value = $value[$key];
} else {
return $default;
}
}
return $value;
}
echo "\n配置示例:\n";
echo "应用名称:" . getConfig('app.name') . "\n";
echo "数据库主机:" . getConfig('database.default.host') . "\n";
echo "邮件驱动:" . getConfig('mail.driver') . "\n";
echo "不存在的配置:" . (getConfig('nonexistent.key', '默认值') ?? '默认值') . "\n";
?>
5.7 数组性能优化
5.7.1 性能考虑
<?php
// 1. 数组大小和内存使用
function measureArrayMemory() {
$memoryBefore = memory_get_usage();
// 创建大数组
$largeArray = range(1, 100000);
$memoryAfter = memory_get_usage();
$memoryUsed = $memoryAfter - $memoryBefore;
echo "数组内存使用:" . number_format($memoryUsed) . " 字节\n";
echo "数组元素数量:" . count($largeArray) . "\n";
echo "平均每个元素:" . round($memoryUsed / count($largeArray), 2) . " 字节\n";
}
measureArrayMemory();
// 2. 不同遍历方式的性能比较
function compareLoopPerformance() {
$array = range(1, 100000);
$iterations = 1;
// foreach循环
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
foreach ($array as $value) {
// 简单操作
$temp = $value * 2;
}
}
$foreachTime = microtime(true) - $start;
// for循环
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$count = count($array);
for ($j = 0; $j < $count; $j++) {
$temp = $array[$j] * 2;
}
}
$forTime = microtime(true) - $start;
// array_map
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$result = array_map(function($value) {
return $value * 2;
}, $array);
}
$mapTime = microtime(true) - $start;
echo "\n性能比较({$iterations}次迭代):\n";
echo "foreach: " . number_format($foreachTime * 1000, 3) . "ms\n";
echo "for: " . number_format($forTime * 1000, 3) . "ms\n";
echo "array_map: " . number_format($mapTime * 1000, 3) . "ms\n";
}
compareLoopPerformance();
// 3. 数组查找性能优化
function compareSearchMethods() {
$array = range(1, 10000);
$searchValue = 8888;
$iterations = 1000;
// 使用in_array
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$found = in_array($searchValue, $array);
}
$inArrayTime = microtime(true) - $start;
// 使用array_search
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$index = array_search($searchValue, $array);
}
$searchTime = microtime(true) - $start;
// 使用关联数组(哈希表)
$hashArray = array_flip($array);
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$found = isset($hashArray[$searchValue]);
}
$hashTime = microtime(true) - $start;
echo "\n查找性能比较({$iterations}次查找):\n";
echo "in_array: " . number_format($inArrayTime * 1000, 3) . "ms\n";
echo "array_search: " . number_format($searchTime * 1000, 3) . "ms\n";
echo "hash lookup: " . number_format($hashTime * 1000, 3) . "ms\n";
}
compareSearchMethods();
?>
5.7.2 优化技巧
<?php
// 1. 预分配数组大小
function createOptimizedArray($size) {
// 预分配数组
$array = array_fill(0, $size, null);
// 填充数据
for ($i = 0; $i < $size; $i++) {
$array[$i] = $i * 2;
}
return $array;
}
// 2. 使用引用避免复制
function processArrayByReference(&$array) {
foreach ($array as &$value) {
$value *= 2; // 直接修改原数组
}
unset($value); // 取消引用
}
$numbers = [1, 2, 3, 4, 5];
processArrayByReference($numbers);
print_r($numbers);
// 3. 批量操作优化
function batchProcess($data, $batchSize = 1000) {
$batches = array_chunk($data, $batchSize);
$results = [];
foreach ($batches as $batch) {
// 批量处理
$batchResult = array_map(function($item) {
// 复杂处理逻辑
return $item * $item;
}, $batch);
$results = array_merge($results, $batchResult);
}
return $results;
}
// 4. 缓存计算结果
class ArrayCache {
private static $cache = [];
public static function memoize($key, $callback) {
if (!isset(self::$cache[$key])) {
self::$cache[$key] = $callback();
}
return self::$cache[$key];
}
public static function clearCache() {
self::$cache = [];
}
}
function expensiveArrayOperation($array) {
$key = md5(serialize($array));
return ArrayCache::memoize($key, function() use ($array) {
// 模拟耗时操作
usleep(1000); // 1ms
return array_sum($array);
});
}
$testArray = [1, 2, 3, 4, 5];
echo "第一次调用:" . expensiveArrayOperation($testArray) . "\n";
echo "第二次调用(缓存):" . expensiveArrayOperation($testArray) . "\n";
// 5. 生成器优化大数据处理
function generateLargeDataset($size) {
for ($i = 0; $i < $size; $i++) {
yield $i => $i * $i;
}
}
function processLargeDataset($size) {
$sum = 0;
foreach (generateLargeDataset($size) as $value) {
$sum += $value;
if ($sum > 1000000) {
break; // 提前退出
}
}
return $sum;
}
echo "\n大数据集处理结果:" . processLargeDataset(10000) . "\n";
?>
5.8 数组最佳实践
5.8.1 编码规范
<?php
// 1. 数组命名规范
$users = []; // 好:复数形式
$userList = []; // 好:明确表示列表
$userData = []; // 好:明确数据类型
// 避免
$data = []; // 不好:太泛化
$arr = []; // 不好:缩写
$temp = []; // 不好:临时变量名
// 2. 数组结构一致性
$products = [
[
'id' => 1,
'name' => '产品A',
'price' => 100.00,
'category' => '电子'
],
[
'id' => 2,
'name' => '产品B',
'price' => 200.00,
'category' => '电子'
]
];
// 3. 使用常量作为数组键
class ProductKeys {
const ID = 'id';
const NAME = 'name';
const PRICE = 'price';
const CATEGORY = 'category';
}
$product = [
ProductKeys::ID => 1,
ProductKeys::NAME => '产品A',
ProductKeys::PRICE => 100.00,
ProductKeys::CATEGORY => '电子'
];
// 4. 数组验证
function validateProductArray($product) {
$requiredKeys = [ProductKeys::ID, ProductKeys::NAME, ProductKeys::PRICE];
foreach ($requiredKeys as $key) {
if (!array_key_exists($key, $product)) {
throw new InvalidArgumentException("缺少必需的键:$key");
}
}
if (!is_numeric($product[ProductKeys::PRICE]) || $product[ProductKeys::PRICE] < 0) {
throw new InvalidArgumentException("价格必须是非负数");
}
return true;
}
try {
validateProductArray($product);
echo "产品数据验证通过\n";
} catch (InvalidArgumentException $e) {
echo "验证失败:" . $e->getMessage() . "\n";
}
// 5. 数组文档注释
/**
* 用户信息数组结构
*
* @var array $user {
* @type int $id 用户ID
* @type string $name 用户姓名
* @type string $email 邮箱地址
* @type int $age 年龄
* @type array $profile 用户资料 {
* @type string $avatar 头像URL
* @type string $bio 个人简介
* @type array $address 地址信息 {
* @type string $city 城市
* @type string $district 区域
* @type string $street 街道
* }
* }
* }
*/
$user = [
'id' => 1,
'name' => '张三',
'email' => 'zhangsan@example.com',
'age' => 25,
'profile' => [
'avatar' => 'https://example.com/avatar.jpg',
'bio' => '这是个人简介',
'address' => [
'city' => '北京',
'district' => '朝阳区',
'street' => '建国路1号'
]
]
];
?>
5.8.2 安全考虑
<?php
// 1. 输入验证
function sanitizeArrayInput($input) {
if (!is_array($input)) {
throw new InvalidArgumentException('输入必须是数组');
}
$sanitized = [];
foreach ($input as $key => $value) {
// 验证键名
if (!is_string($key) && !is_int($key)) {
continue; // 跳过无效键
}
// 清理值
if (is_string($value)) {
$sanitized[$key] = htmlspecialchars(trim($value), ENT_QUOTES, 'UTF-8');
} elseif (is_numeric($value)) {
$sanitized[$key] = $value;
} elseif (is_array($value)) {
$sanitized[$key] = sanitizeArrayInput($value); // 递归处理
}
}
return $sanitized;
}
// 2. 防止数组注入
function safeArrayMerge($array1, $array2, $allowedKeys = []) {
if (!empty($allowedKeys)) {
$array2 = array_intersect_key($array2, array_flip($allowedKeys));
}
return array_merge($array1, $array2);
}
$userInput = [
'name' => '张三',
'email' => 'zhangsan@example.com',
'admin' => true, // 恶意输入
'role' => 'admin' // 恶意输入
];
$allowedFields = ['name', 'email'];
$safeData = safeArrayMerge([], $userInput, $allowedFields);
print_r($safeData); // 只包含允许的字段
// 3. 深度限制
function limitArrayDepth($array, $maxDepth = 10, $currentDepth = 0) {
if ($currentDepth >= $maxDepth) {
return null; // 超过深度限制
}
$result = [];
foreach ($array as $key => $value) {
if (is_array($value)) {
$result[$key] = limitArrayDepth($value, $maxDepth, $currentDepth + 1);
} else {
$result[$key] = $value;
}
}
return $result;
}
// 4. 大小限制
function limitArraySize($array, $maxSize = 1000) {
if (count($array, COUNT_RECURSIVE) > $maxSize) {
throw new InvalidArgumentException('数组大小超过限制');
}
return $array;
}
// 5. 类型检查
function validateArrayStructure($array, $schema) {
foreach ($schema as $key => $expectedType) {
if (!array_key_exists($key, $array)) {
throw new InvalidArgumentException("缺少必需的键:$key");
}
$value = $array[$key];
$actualType = gettype($value);
if (is_array($expectedType)) {
if (!is_array($value)) {
throw new InvalidArgumentException("键 $key 应该是数组");
}
validateArrayStructure($value, $expectedType);
} elseif ($actualType !== $expectedType) {
throw new InvalidArgumentException("键 $key 应该是 $expectedType 类型,实际是 $actualType");
}
}
return true;
}
$schema = [
'name' => 'string',
'age' => 'integer',
'profile' => [
'email' => 'string',
'active' => 'boolean'
]
];
$testData = [
'name' => '张三',
'age' => 25,
'profile' => [
'email' => 'zhangsan@example.com',
'active' => true
]
];
try {
validateArrayStructure($testData, $schema);
echo "数组结构验证通过\n";
} catch (InvalidArgumentException $e) {
echo "验证失败:" . $e->getMessage() . "\n";
}
?>
5.9 小结
本章全面介绍了PHP数组的各个方面:
- 数组基础:概念、类型、创建方法
- 数组操作:访问、修改、遍历
- 数组函数:信息函数、操作函数、排序函数、过滤映射函数
- 多维数组:创建、操作、实际应用
- 性能优化:性能考虑、优化技巧
- 最佳实践:编码规范、安全考虑
数组是PHP中最重要的数据结构之一,掌握数组的使用对于PHP开发至关重要。
5.10 实践练习
基础练习:
- 创建不同类型的数组
- 实现数组的基本操作
- 练习数组遍历方法
函数练习:
- 使用各种数组函数
- 实现自定义数组操作函数
- 练习数组排序和过滤
实际应用练习:
- 实现购物车系统
- 创建学生成绩管理
- 构建配置管理系统
性能优化练习:
- 比较不同操作的性能
- 优化大数组处理
- 实现缓存机制
5.11 扩展阅读
下一章预告:在下一章中,我们将学习PHP的字符串处理,包括字符串操作、正则表达式、字符编码等内容。