PHP 多维数组详解

多维数组是包含一个或多个数组的数组,可以创建复杂的数据结构来组织和处理层次化数据。在 PHP 中,我们可以创建二维、三维甚至更高维度的数组。

什么是多维数组?

多维数组是指数组中的元素本身也是数组,这种嵌套结构允许我们创建更复杂的数据组织形式。

多维数组的特点:

  • 数组中的元素可以是另一个数组
  • 支持创建二维、三维甚至更高维度的数据结构
  • 适合表示表格数据、树状结构等复杂数据
  • 可以通过多层索引访问元素
  • 提供灵活的数据组织方式

一维数组

简单的值列表

$array[index]

二维数组

数组的数组(表格)

$array[row][col]

三维数组

数组的数组的数组(立方体)

$array[x][y][z]

创建多维数组

PHP 提供了多种创建多维数组的方式:

使用 array() 函数创建

基础二维数组

<?php
// 二维数组:汽车数据
$cars = array(
    array("Volvo", 100, 96),
    array("BMW", 60, 59),
    array("Toyota", 110, 100)
);

// 访问二维数组元素
echo "品牌: " . $cars[0][0] . "<br>"; // 输出: Volvo
echo "库存: " . $cars[0][1] . "<br>"; // 输出: 100
echo "销量: " . $cars[0][2] . "<br>"; // 输出: 96
?>

使用短数组语法创建(PHP 5.4+)

现代语法创建多维数组

<?php
// 使用方括号语法
$students = [
    ["张三", 20, "计算机科学"],
    ["李四", 21, "软件工程"],
    ["王五", 19, "信息安全"]
];

// 关联多维数组
$families = [
    "Griffin" => ["Peter", "Lois", "Megan"],
    "Quagmire" => ["Glenn"],
    "Brown" => ["Cleveland", "Loretta", "Junior"]
];

echo $families['Griffin'][2] . " 是 Griffin 家族的成员<br>";
?>

动态创建多维数组

逐步构建多维数组

<?php
// 动态创建二维数组
$matrix = [];

// 添加第一行
$matrix[0] = [1, 2, 3];
// 添加第二行
$matrix[1] = [4, 5, 6];
// 添加第三行
$matrix[2] = [7, 8, 9];

// 或者使用更简洁的方式
$table = [];
$table[] = ['ID', '姓名', '年龄'];
$table[] = [1, '张三', 25];
$table[] = [2, '李四', 30];

print_r($table);
?>

二维数组详解

二维数组是最常见的多维数组形式,通常用于表示表格数据。

索引二维数组

表格数据表示

<?php
// 学生成绩表
$grades = [
    [85, 92, 78],
    [90, 88, 95],
    [76, 85, 80],
    [92, 96, 88]
];

echo "学生成绩表: <br>";
for ($i = 0; $i < count($grades); $i++) {
    echo "学生 " . ($i + 1) . ": ";
    for ($j = 0; $j < count($grades[$i]); $j++) {
        echo $grades[$i][$j] . " ";
    }
    echo "<br>";
}

// 计算每个学生的平均分
echo "<br>学生平均分: <br>";
foreach ($grades as $index => $studentGrades) {
    $average = array_sum($studentGrades) / count($studentGrades);
    echo "学生 " . ($index + 1) . " 平均分: " . round($average, 2) . "<br>";
}
?>

关联二维数组

使用有意义的键名

<?php
// 员工信息表(关联二维数组)
$employees = [
    [
        "id" => 1,
        "name" => "张三",
        "department" => "技术部",
        "salary" => 8000,
        "join_date" => "2020-05-15"
    ],
    [
        "id" => 2,
        "name" => "李四",
        "department" => "市场部",
        "salary" => 7500,
        "join_date" => "2019-08-20"
    ],
    [
        "id" => 3,
        "name" => "王五",
        "department" => "财务部",
        "salary" => 9000,
        "join_date" => "2021-01-10"
    ]
];

// 访问特定员工信息
echo "员工信息: <br>";
echo "姓名: " . $employees[0]['name'] . "<br>";
echo "部门: " . $employees[0]['department'] . "<br>";
echo "薪资: " . $employees[0]['salary'] . "<br>";

// 查找特定部门的员工
echo "<br>技术部员工: <br>";
foreach ($employees as $employee) {
    if ($employee['department'] === '技术部') {
        echo $employee['name'] . "<br>";
    }
}
?>

三维数组

三维数组用于表示更复杂的数据结构,如时间序列数据、3D空间数据等。

创建和访问三维数组

<?php
// 三维数组:学校-班级-学生
$school = [
    "一年级" => [
        "一班" => ["张三", "李四", "王五"],
        "二班" => ["赵六", "钱七", "孙八"]
    ],
    "二年级" => [
        "一班" => ["周九", "吴十", "郑十一"],
        "二班" => ["王十二", "冯十三", "陈十四"]
    ]
];

// 访问三维数组元素
echo $school["一年级"]["一班"][0] . "<br>"; // 输出: 张三
echo $school["二年级"]["二班"][2] . "<br>"; // 输出: 陈十四

// 遍历三维数组
foreach ($school as $grade => $classes) {
    echo "<h3>$grade</h3>";
    foreach ($classes as $className => $students) {
        echo "<strong>$className:</strong> ";
        echo implode(", ", $students) . "<br>";
    }
}
?>

三维数组实际应用

<?php
// 三维数组:产品库存(仓库-货架-产品)
$inventory = [
    "北京仓库" => [
        "A区" => [
            "电子产品" => ["iPhone" => 50, "iPad" => 30],
            "家电" => ["电视" => 20, "冰箱" => 15]
        ],
        "B区" => [
            "服装" => ["T恤" => 100, "牛仔裤" => 80],
            "鞋类" => ["运动鞋" => 60, "皮鞋" => 40]
        ]
    ],
    "上海仓库" => [
        "A区" => [
            "图书" => ["小说" => 200, "教材" => 150],
            "文具" => ["笔" => 300, "本子" => 250]
        ]
    ]
];

// 查询特定产品的库存
$product = "iPhone";
$location = "北京仓库";
$area = "A区";
$category = "电子产品";

if (isset($inventory[$location][$area][$category][$product])) {
    $stock = $inventory[$location][$area][$category][$product];
    echo "$location $area 的 $product 库存: $stock 件<br>";
} else {
    echo "未找到该产品的库存信息<br>";
}

// 统计总库存
$totalStock = 0;
foreach ($inventory as $warehouse => $areas) {
    foreach ($areas as $area => $categories) {
        foreach ($categories as $category => $products) {
            foreach ($products as $product => $quantity) {
                $totalStock += $quantity;
            }
        }
    }
}
echo "总库存数量: $totalStock 件<br>";
?>

遍历多维数组

遍历多维数组需要使用嵌套循环,根据数组的维度决定循环的层数。

使用嵌套 foreach 循环

通用多维数组遍历方法

<?php
// 复杂的多维数组
$company = [
    "技术部" => [
        "开发组" => ["前端开发", "后端开发", "移动开发"],
        "测试组" => ["功能测试", "性能测试"]
    ],
    "市场部" => [
        "推广组" => ["线上推广", "线下活动"],
        "销售组" => ["国内销售", "国际销售"]
    ],
    "人事部" => [
        "招聘组" => ["社会招聘", "校园招聘"],
        "培训组" => ["新员工培训", "技能培训"]
    ]
];

// 递归遍历函数
function displayArray($array, $level = 0) {
    $indent = str_repeat("    ", $level);

    foreach ($array as $key => $value) {
        if (is_array($value)) {
            echo $indent . "<strong>$key:</strong><br>";
            displayArray($value, $level + 1);
        } else {
            echo $indent . "- $value<br>";
        }
    }
}

echo "公司组织结构: <br>";
displayArray($company);
?>

使用递归迭代器

处理未知深度的多维数组

<?php
// 使用 RecursiveIteratorIterator 遍历多维数组
$nestedArray = [
    "level1" => [
        "level2a" => ["value1", "value2"],
        "level2b" => [
            "level3a" => ["value3", "value4"],
            "level3b" => "value5"
        ]
    ]
];

function flattenArray($array) {
    $result = [];
    $iterator = new RecursiveIteratorIterator(
        new RecursiveArrayIterator($array),
        RecursiveIteratorIterator::SELF_FIRST
    );

    foreach ($iterator as $key => $value) {
        if (!is_array($value)) {
            $result[] = $value;
        }
    }

    return $result;
}

$flatValues = flattenArray($nestedArray);
echo "所有值: " . implode(", ", $flatValues) . "<br>";
?>

多维数组操作

添加和修改元素

动态操作多维数组

<?php
// 初始数组
$data = [
    "users" => [
        "john" => ["age" => 25, "city" => "New York"],
        "jane" => ["age" => 30, "city" => "London"]
    ]
];

// 添加新用户
$data["users"]["bob"] = ["age" => 28, "city" => "Paris"];

// 修改用户信息
$data["users"]["john"]["age"] = 26;
$data["users"]["john"]["country"] = "USA"; // 添加新字段

// 删除用户
unset($data["users"]["jane"]);

print_r($data);
?>

搜索和过滤

在多维数组中查找数据

<?php
$products = [
    ["id" => 1, "name" => "iPhone", "price" => 5999, "category" => "electronics"],
    ["id" => 2, "name" => "T-shirt", "price" => 99, "category" => "clothing"],
    ["id" => 3, "name" => "Book", "price" => 49, "category" => "education"],
    ["id" => 4, "name" => "iPad", "price" => 3299, "category" => "electronics"]
];

// 搜索特定产品
function searchProducts($products, $searchTerm) {
    $results = [];
    foreach ($products as $product) {
        if (stripos($product['name'], $searchTerm) !== false) {
            $results[] = $product;
        }
    }
    return $results;
}

// 按类别过滤
function filterByCategory($products, $category) {
    return array_filter($products, function($product) use ($category) {
        return $product['category'] === $category;
    });
}

// 使用搜索和过滤
$appleProducts = searchProducts($products, "iP");
$electronicProducts = filterByCategory($products, "electronics");

echo "Apple 产品: <br>";
foreach ($appleProducts as $product) {
    echo $product['name'] . " - ¥" . $product['price'] . "<br>";
}

echo "<br>电子产品: <br>";
foreach ($electronicProducts as $product) {
    echo $product['name'] . " - ¥" . $product['price'] . "<br>";
}
?>

实际应用场景

配置管理系统

使用多维数组管理配置

<?php
// 应用配置数组
$config = [
    'database' => [
        'default' => [
            'host' => 'localhost',
            'name' => 'myapp_db',
            'user' => 'app_user',
            'pass' => 'secure_password',
            'charset' => 'utf8mb4'
        ],
        'backup' => [
            'host' => 'backup.server.com',
            'name' => 'backup_db',
            'user' => 'backup_user',
            'pass' => 'backup_password'
        ]
    ],
    'app' => [
        'name' => '我的应用',
        'version' => '1.0.0',
        'debug' => true,
        'timezone' => 'Asia/Shanghai'
    ],
    'services' => [
        'cache' => [
            'driver' => 'redis',
            'host' => '127.0.0.1',
            'port' => 6379
        ],
        'queue' => [
            'driver' => 'database',
            'connection' => 'default'
        ]
    ]
];

// 配置访问函数
function getConfig($path, $config) {
    $keys = explode('.', $path);
    $value = $config;

    foreach ($keys as $key) {
        if (isset($value[$key])) {
            $value = $value[$key];
        } else {
            return null;
        }
    }

    return $value;
}

// 使用配置
$dbHost = getConfig('database.default.host', $config);
$appName = getConfig('app.name', $config);
$cacheDriver = getConfig('services.cache.driver', $config);

echo "数据库主机: $dbHost<br>";
echo "应用名称: $appName<br>";
echo "缓存驱动: $cacheDriver<br>";
?>

数据报表系统

生成复杂数据报表

<?php
// 销售数据报表
$salesReport = [
    '2023' => [
        'Q1' => [
            'January' => ['revenue' => 150000, 'profit' => 45000],
            'February' => ['revenue' => 165000, 'profit' => 52000],
            'March' => ['revenue' => 142000, 'profit' => 41000]
        ],
        'Q2' => [
            'April' => ['revenue' => 178000, 'profit' => 58000],
            'May' => ['revenue' => 192000, 'profit' => 65000],
            'June' => ['revenue' => 185000, 'profit' => 62000]
        ]
    ],
    '2024' => [
        'Q1' => [
            'January' => ['revenue' => 210000, 'profit' => 75000],
            'February' => ['revenue' => 198000, 'profit' => 68000],
            'March' => ['revenue' => 225000, 'profit' => 82000]
        ]
    ]
];

// 生成季度报表
function generateQuarterlyReport($salesReport) {
    $quarterlyData = [];

    foreach ($salesReport as $year => $quarters) {
        $quarterlyData[$year] = [];

        foreach ($quarters as $quarter => $months) {
            $totalRevenue = 0;
            $totalProfit = 0;

            foreach ($months as $month => $data) {
                $totalRevenue += $data['revenue'];
                $totalProfit += $data['profit'];
            }

            $quarterlyData[$year][$quarter] = [
                'revenue' => $totalRevenue,
                'profit' => $totalProfit,
                'profit_margin' => round(($totalProfit / $totalRevenue) * 100, 2)
            ];
        }
    }

    return $quarterlyData;
}

$quarterlyReport = generateQuarterlyReport($salesReport);

echo "季度销售报表: <br>";
foreach ($quarterlyReport as $year => $quarters) {
    echo "<h3>$year 年</h3>";
    foreach ($quarters as $quarter => $data) {
        echo "$quarter: 收入 ¥" . number_format($data['revenue']) .
             ", 利润 ¥" . number_format($data['profit']) .
             ", 利润率 " . $data['profit_margin'] . "%<br>";
    }
}
?>

菜单导航系统

动态生成网站导航

<?php
// 网站导航菜单
$navigation = [
    'home' => [
        'title' => '首页',
        'url' => '/',
        'children' => []
    ],
    'products' => [
        'title' => '产品',
        'url' => '/products',
        'children' => [
            'electronics' => [
                'title' => '电子产品',
                'url' => '/products/electronics',
                'children' => [
                    'phones' => ['title' => '手机', 'url' => '/products/electronics/phones'],
                    'laptops' => ['title' => '笔记本电脑', 'url' => '/products/electronics/laptops']
                ]
            ],
            'clothing' => [
                'title' => '服装',
                'url' => '/products/clothing',
                'children' => [
                    'men' => ['title' => '男装', 'url' => '/products/clothing/men'],
                    'women' => ['title' => '女装', 'url' => '/products/clothing/women']
                ]
            ]
        ]
    ],
    'about' => [
        'title' => '关于我们',
        'url' => '/about',
        'children' => [
            'company' => ['title' => '公司简介', 'url' => '/about/company'],
            'team' => ['title' => '团队介绍', 'url' => '/about/team']
        ]
    ]
];

// 递归生成导航菜单
function generateMenu($menu, $level = 0) {
    $output = '';
    $indent = str_repeat('  ', $level * 2);

    $output .= $indent . "<ul>\n";

    foreach ($menu as $item) {
        $output .= $indent . "  <li>\n";
        $output .= $indent . "    <a href='{$item['url']}'>{$item['title']}</a>\n";

        if (!empty($item['children'])) {
            $output .= generateMenu($item['children'], $level + 1);
        }

        $output .= $indent . "  </li>\n";
    }

    $output .= $indent . "</ul>\n";
    return $output;
}

// 生成顶级菜单
$topLevelMenu = array_map(function($item) {
    return [
        'title' => $item['title'],
        'url' => $item['url'],
        'children' => []
    ];
}, $navigation);

echo "网站导航菜单: <br>";
echo generateMenu($topLevelMenu);
?>

多维数组排序

按特定字段排序

使用 usort 排序多维数组

<?php
$students = [
    ['name' => '张三', 'score' => 85, 'age' => 20],
    ['name' => '李四', 'score' => 92, 'age' => 22],
    ['name' => '王五', 'score' => 78, 'age' => 19],
    ['name' => '赵六', 'score' => 88, 'age' => 21]
];

// 按分数降序排序
usort($students, function($a, $b) {
    return $b['score'] - $a['score'];
});

echo "按分数排序: <br>";
foreach ($students as $student) {
    echo $student['name'] . ": " . $student['score'] . "分<br>";
}

echo "<br>";

// 按年龄升序排序
usort($students, function($a, $b) {
    return $a['age'] - $b['age'];
});

echo "按年龄排序: <br>";
foreach ($students as $student) {
    echo $student['name'] . ": " . $student['age'] . "岁<br>";
}
?>

多级排序

多个字段的复杂排序

<?php
$products = [
    ['name' => 'iPhone', 'price' => 5999, 'rating' => 4.5],
    ['name' => 'Samsung', 'price' => 4999, 'rating' => 4.3],
    ['name' => 'Xiaomi', 'price' => 2999, 'rating' => 4.6],
    ['name' => 'Huawei', 'price' => 4599, 'rating' => 4.5]
];

// 多级排序:先按评分降序,再按价格升序
usort($products, function($a, $b) {
    // 先比较评分
    $ratingCompare = $b['rating'] * 10 - $a['rating'] * 10;
    if ($ratingCompare != 0) {
        return $ratingCompare;
    }
    // 评分相同,比较价格
    return $a['price'] - $b['price'];
});

echo "多级排序结果: <br>";
foreach ($products as $product) {
    echo $product['name'] . " - 评分: " . $product['rating'] . " - 价格: ¥" . $product['price'] . "<br>";
}
?>

性能优化和最佳实践

多维数组使用建议:

  • 根据数据特性选择合适的数组维度
  • 使用有意义的键名提高代码可读性
  • 避免创建过深的多维数组(通常不超过3-4层)
  • 对于大型多维数组,考虑使用数据库或缓存
  • 使用适当的函数处理多维数组操作
  • 在遍历前检查数组维度,避免不必要的循环

内存使用优化

高效处理大型多维数组

<?php
// 优化前:一次性加载所有数据
/*
$hugeArray = []; // 包含数百万元素的多维数组
foreach ($hugeArray as $item) {
    // 处理逻辑
}
*/

// 优化后:分批处理或使用生成器
function processLargeArray($array, $batchSize = 1000) {
    $total = count($array);
    $processed = 0;

    while ($processed < $total) {
        $batch = array_slice($array, $processed, $batchSize);

        foreach ($batch as $item) {
            // 处理逻辑
            processItem($item);
        }

        $processed += $batchSize;
        // 可选:释放内存
        gc_collect_cycles();
    }
}

function processItem($item) {
    // 处理单个项目
    return $item;
}

// 使用示例
$largeData = range(1, 10000); // 模拟大数据
processLargeArray($largeData, 500);
?>

数据验证和安全

安全访问多维数组

<?php
// 安全访问函数
function safeArrayAccess($array, $keys, $default = null) {
    $current = $array;

    foreach ($keys as $key) {
        if (!is_array($current) || !array_key_exists($key, $current)) {
            return $default;
        }
        $current = $current[$key];
    }

    return $current;
}

// 示例数组
$config = [
    'database' => [
        'default' => [
            'host' => 'localhost'
        ]
    ]
];

// 安全访问
$host = safeArrayAccess($config, ['database', 'default', 'host'], '127.0.0.1');
$port = safeArrayAccess($config, ['database', 'default', 'port'], 3306);

echo "数据库主机: $host<br>";
echo "数据库端口: $port<br>";

// 不安全的方式(可能产生警告)
// $unsafePort = $config['database']['default']['port'];
?>

PHP 7/8 新特性

空合并运算符在多维数组中的应用

PHP 7+ 空合并运算符

<?php
$user = [
    'profile' => [
        'name' => '张三',
        'email' => 'zhangsan@example.com'
    ]
];

// PHP 7+ 空合并运算符
$phone = $user['profile']['phone'] ?? '未设置';
$address = $user['profile']['address'] ?? '未知地址';

echo "电话: $phone<br>";
echo "地址: $address<br>";

// 嵌套空合并(PHP 7.4+)
$deepValue = $user['profile']['settings']['notifications'] ?? '默认值';
echo "通知设置: $deepValue<br>";
?>

数组解构在多维数组中的应用

PHP 7.1+ 数组解构

<?php
$student = ['张三', 20, ['数学' => 85, '英语' => 92]];

// 解构多维数组
[$name, $age, $scores] = $student;
['数学' => $math, '英语' => $english] = $scores;

echo "姓名: $name<br>";
echo "年龄: $age<br>";
echo "数学成绩: $math<br>";
echo "英语成绩: $english<br>";

// 在循环中使用解构
$students = [
    ['李四', 21, 88],
    ['王五', 19, 76]
];

foreach ($students as [$name, $age, $score]) {
    echo "$name ($age 岁): $score 分<br>";
}
?>

总结

  • 多维数组是包含一个或多个数组的数组,支持创建复杂的数据结构
  • 二维数组用于表示表格数据,三维数组用于更复杂的层次结构
  • 可以使用 array() 函数或短数组语法创建多维数组
  • 遍历多维数组需要使用嵌套循环或递归函数
  • 多维数组适合表示配置数据、报表数据、导航菜单等复杂结构
  • 使用适当的排序和搜索函数处理多维数组数据
  • 遵循最佳实践可以提高代码性能和可维护性
  • PHP 7/8 的新特性为多维数组操作提供了更多便利