数组和对象
概述
数组和对象是PHP中的基本数据结构。数组存储数据集合,而对象封装数据和行为。本章涵盖数组操作、面向对象编程基础和复杂数据结构的处理。
数组深入探讨
数组创建和类型
php
<?php
// 索引数组
$fruits = array("apple", "banana", "orange");
$numbers = [1, 2, 3, 4, 5]; // 简短语法(PHP 5.4+)
// 关联数组
$person = array(
"name" => "张三",
"age" => 30,
"city" => "北京"
);
$config = [
"database" => "mysql",
"host" => "localhost",
"port" => 3306
];
// 混合数组
$mixed = [
0 => "第一个项目",
"key" => "值",
1 => "第二个项目",
"nested" => ["a", "b", "c"]
];
// 多维数组
$matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
$users = [
[
"id" => 1,
"name" => "小明",
"email" => "xiaoming@example.com",
"roles" => ["user", "editor"]
],
[
"id" => 2,
"name" => "小红",
"email" => "xiaohong@example.com",
"roles" => ["user"]
]
];
?>数组访问和修改
php
<?php
$fruits = ["apple", "banana", "orange"];
// 访问元素
echo $fruits[0]; // "apple"
echo $fruits[1]; // "banana"
// 修改元素
$fruits[1] = "grape";
echo $fruits[1]; // "grape"
// 添加元素
$fruits[] = "kiwi"; // 附加到末尾
$fruits[10] = "mango"; // 指定索引
array_push($fruits, "peach"); // 使用函数附加
array_unshift($fruits, "strawberry"); // 前置
// 删除元素
unset($fruits[2]); // 删除指定索引
$lastFruit = array_pop($fruits); // 删除并返回最后一个
$firstFruit = array_shift($fruits); // 删除并返回第一个
// 关联数组操作
$person = ["name" => "张三", "age" => 30];
// 添加/修改
$person["email"] = "zhangsan@example.com";
$person["age"] = 31;
// 检查存在
if (isset($person["email"])) {
echo "邮箱存在:" . $person["email"];
}
if (array_key_exists("phone", $person)) {
echo "电话存在";
} else {
echo "电话未设置";
}
// 删除
unset($person["age"]);
?>数组函数和操作
php
<?php
$numbers = [3, 1, 4, 1, 5, 9, 2, 6];
// 数组信息
echo count($numbers); // 8(长度)
echo sizeof($numbers); // 8(count的别名)
echo array_sum($numbers); // 31(求和)
echo array_product($numbers); // 6480(乘积)
// 最小/最大值
echo min($numbers); // 1
echo max($numbers); // 9
// 搜索
$position = array_search(5, $numbers); // 返回第一个匹配的索引
$exists = in_array(4, $numbers); // true/false
// 排序
$sorted = $numbers;
sort($sorted); // 对值排序,丢失键
print_r($sorted);
$reversed = $numbers;
rsort($reversed); // 逆序排序
print_r($reversed);
// 关联数组排序
$people = [
"zhangsan" => 30,
"lisi" => 25,
"wangwu" => 35
];
asort($people); // 按值排序,保持键
print_r($people); // lisi=>25, zhangsan=>30, wangwu=>35
ksort($people); // 按键排序
print_r($people); // lisi=>25, wangwu=>35, zhangsan=>30
// 自定义排序
$users = [
["name" => "张三", "age" => 30],
["name" => "李四", "age" => 25],
["name" => "王五", "age" => 35]
];
usort($users, function($a, $b) {
return $a["age"] <=> $b["age"]; // 按年龄排序
});
print_r($users);
?>数组操作函数
php
<?php
$numbers = [1, 2, 3, 4, 5];
// Map - 转换每个元素
$doubled = array_map(function($n) {
return $n * 2;
}, $numbers);
print_r($doubled); // [2, 4, 6, 8, 10]
// Filter - 根据条件筛选元素
$evens = array_filter($numbers, function($n) {
return $n % 2 === 0;
});
print_r($evens); // [2, 4]
// Reduce - 将元素合并为单个值
$sum = array_reduce($numbers, function($carry, $item) {
return $carry + $item;
}, 0);
echo $sum; // 15
// 数组合并
$arr1 = [1, 2, 3];
$arr2 = [4, 5, 6];
$merged = array_merge($arr1, $arr2);
print_r($merged); // [1, 2, 3, 4, 5, 6]
// 数组切片
$slice = array_slice($numbers, 1, 3); // 从索引1开始,取3个元素
print_r($slice); // [2, 3, 4]
// 数组分块
$chunks = array_chunk($numbers, 2);
print_r($chunks); // [[1, 2], [3, 4], [5]]
// 数组键和值
$person = ["name" => "张三", "age" => 30, "city" => "北京"];
$keys = array_keys($person); // ["name", "age", "city"]
$values = array_values($person); // ["张三", 30, "北京"]
// 翻转键和值
$flipped = array_flip($person);
print_r($flipped); // ["张三" => "name", 30 => "age", "北京" => "city"]
?>高级数组技术
php
<?php
// 数组遍历 - 对每个元素应用函数
$fruits = ["apple", "banana", "orange"];
array_walk($fruits, function(&$fruit, $key) {
$fruit = strtoupper($fruit);
});
print_r($fruits); // ["APPLE", "BANANA", "ORANGE"]
// 数组列提取 - 从多维数组中提取列
$users = [
["id" => 1, "name" => "张三", "email" => "zhangsan@example.com"],
["id" => 2, "name" => "李四", "email" => "lisi@example.com"],
["id" => 3, "name" => "王五", "email" => "wangwu@example.com"]
];
$names = array_column($users, "name");
print_r($names); // ["张三", "李四", "王五"]
$emailsById = array_column($users, "email", "id");
print_r($emailsById); // [1 => "zhangsan@example.com", 2 => "lisi@example.com", ...]
// 数组组合 - 使用一个数组作为键,另一个作为值来创建数组
$keys = ["name", "age", "city"];
$values = ["张三", 30, "北京"];
$combined = array_combine($keys, $values);
print_r($combined); // ["name" => "张三", "age" => 30, "city" => "北京"]
// 数组交集和差集
$array1 = [1, 2, 3, 4, 5];
$array2 = [3, 4, 5, 6, 7];
$intersection = array_intersect($array1, $array2); // [3, 4, 5]
$difference = array_diff($array1, $array2); // [1, 2]
// 唯一值
$duplicates = [1, 2, 2, 3, 3, 3, 4];
$unique = array_unique($duplicates);
print_r($unique); // [1, 2, 3, 4]
?>对象基础
类定义和实例化
php
<?php
// 基本类定义
class Person {
// 属性(特性)
public $name;
public $age;
public $email;
// 构造函数
public function __construct($name, $age, $email) {
$this->name = $name;
$this->age = $age;
$this->email = $email;
}
// 方法(函数)
public function introduce() {
return "你好,我是{$this->name},今年{$this->age}岁。";
}
public function getEmail() {
return $this->email;
}
public function setEmail($email) {
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->email = $email;
return true;
}
return false;
}
}
// 创建对象(实例化)
$person1 = new Person("小红", 25, "xiaohong@example.com");
$person2 = new Person("小明", 30, "xiaoming@example.com");
// 使用对象
echo $person1->introduce(); // "你好,我是小红,今年25岁。"
echo $person1->name; // "小红"
$person1->setEmail("xiaohong.new@example.com");
echo $person1->getEmail(); // "xiaohong.new@example.com"
?>属性可见性
php
<?php
class BankAccount {
public $accountNumber; // 可从任何地方访问
protected $balance; // 可从此类和子类访问
private $pin; // 仅可从此类访问
public function __construct($accountNumber, $initialBalance, $pin) {
$this->accountNumber = $accountNumber;
$this->balance = $initialBalance;
$this->pin = $pin;
}
public function getBalance() {
return $this->balance;
}
public function deposit($amount) {
if ($amount > 0) {
$this->balance += $amount;
return true;
}
return false;
}
public function withdraw($amount, $enteredPin) {
if ($this->validatePin($enteredPin) && $amount > 0 && $amount <= $this->balance) {
$this->balance -= $amount;
return true;
}
return false;
}
private function validatePin($enteredPin) {
return $this->pin === $enteredPin;
}
protected function calculateInterest($rate) {
return $this->balance * $rate;
}
}
$account = new BankAccount("12345", 1000, "1234");
echo $account->accountNumber; // 正常(public)
echo $account->getBalance(); // 正常(public 方法)
// 这些会导致错误:
// echo $account->balance; // 错误(protected)
// echo $account->pin; // 错误(private)
// $account->validatePin("1234"); // 错误(private 方法)
?>静态属性和方法
php
<?php
class Counter {
private static $count = 0;
public static $instances = [];
public $id;
public function __construct() {
self::$count++;
$this->id = self::$count;
self::$instances[] = $this;
}
public static function getCount() {
return self::$count;
}
public static function resetCount() {
self::$count = 0;
self::$instances = [];
}
public function getId() {
return $this->id;
}
}
// 使用静态方法和属性
echo Counter::getCount(); // 0
$counter1 = new Counter();
$counter2 = new Counter();
$counter3 = new Counter();
echo Counter::getCount(); // 3
echo $counter2->getId(); // 2
print_r(Counter::$instances); // Array of Counter objects
Counter::resetCount();
echo Counter::getCount(); // 0
?>魔术方法
php
<?php
class MagicExample {
private $data = [];
// 构造函数和析构函数
public function __construct($initialData = []) {
$this->data = $initialData;
echo "对象已创建\n";
}
public function __destruct() {
echo "对象已销毁\n";
}
// 属性访问
public function __get($name) {
return $this->data[$name] ?? null;
}
public function __set($name, $value) {
$this->data[$name] = $value;
}
public function __isset($name) {
return isset($this->data[$name]);
}
public function __unset($name) {
unset($this->data[$name]);
}
// 方法调用
public function __call($method, $args) {
echo "调用方法 '$method',参数:" . implode(', ', $args) . "\n";
}
public static function __callStatic($method, $args) {
echo "调用静态方法 '$method',参数:" . implode(', ', $args) . "\n";
}
// 字符串转换
public function __toString() {
return json_encode($this->data);
}
// 数组访问
public function __invoke($arg) {
echo "对象作为函数调用,参数:$arg\n";
}
}
$obj = new MagicExample(["name" => "张三"]);
// 属性访问
echo $obj->name; // "张三"(调用 __get)
$obj->age = 30; // 调用 __set
echo isset($obj->age); // true(调用 __isset)
// 方法调用
$obj->nonExistentMethod("arg1", "arg2"); // 调用 __call
// 字符串转换
echo $obj; // 调用 __toString,输出JSON
// 函数调用
$obj("hello"); // 调用 __invoke
?>面向对象编程概念
继承
php
<?php
// 基类
class Animal {
protected $name;
protected $species;
public function __construct($name, $species) {
$this->name = $name;
$this->species = $species;
}
public function getName() {
return $this->name;
}
public function getSpecies() {
return $this->species;
}
public function makeSound() {
return "一些通用动物声音";
}
public function sleep() {
return "{$this->name}在睡觉";
}
}
// 派生类
class Dog extends Animal {
private $breed;
public function __construct($name, $breed) {
parent::__construct($name, "犬科");
$this->breed = $breed;
}
public function makeSound() {
return "汪!汪!";
}
public function fetch() {
return "{$this->name}在捕球";
}
public function getBreed() {
return $this->breed;
}
}
class Cat extends Animal {
public function __construct($name) {
parent::__construct($name, "猫科");
}
public function makeSound() {
return "喘!";
}
public function purr() {
return "{$this->name}在咕咕叫";
}
}
// 使用
$dog = new Dog("小白", "金毛寻回犬");
$cat = new Cat("胡须");
echo $dog->getName(); // "小白"
echo $dog->makeSound(); // "汪!汪!"
echo $dog->fetch(); // "小白在捕球"
echo $dog->getBreed(); // "金毛寻回犬"
echo $cat->getName(); // "胡须"
echo $cat->makeSound(); // "喘!"
echo $cat->purr(); // "胡须在咕咕叫"
// 多态性
$animals = [$dog, $cat];
foreach ($animals as $animal) {
echo $animal->getName() . " 说:" . $animal->makeSound() . "\n";
}
?>抽象类和接口
php
<?php
// 抽象类
abstract class Shape {
protected $color;
public function __construct($color) {
$this->color = $color;
}
public function getColor() {
return $this->color;
}
// 抽象方法 - 必须由子类实现
abstract public function calculateArea();
abstract public function calculatePerimeter();
}
// 接口
interface Drawable {
public function draw();
}
interface Resizable {
public function resize($factor);
}
// 具体类
class Circle extends Shape implements Drawable, Resizable {
private $radius;
public function __construct($color, $radius) {
parent::__construct($color);
$this->radius = $radius;
}
public function calculateArea() {
return pi() * $this->radius * $this->radius;
}
public function calculatePerimeter() {
return 2 * pi() * $this->radius;
}
public function draw() {
return "绘制一个{$this->color}的圆,半径为{$this->radius}";
}
public function resize($factor) {
$this->radius *= $factor;
}
}
class Rectangle extends Shape implements Drawable {
private $width;
private $height;
public function __construct($color, $width, $height) {
parent::__construct($color);
$this->width = $width;
$this->height = $height;
}
public function calculateArea() {
return $this->width * $this->height;
}
public function calculatePerimeter() {
return 2 * ($this->width + $this->height);
}
public function draw() {
return "绘制一个{$this->color}的矩形({$this->width}x{$this->height})";
}
}
// 使用
$circle = new Circle("红色", 5);
$rectangle = new Rectangle("蓝色", 4, 6);
echo $circle->draw(); // "绘制一个红色的圆,半径为5"
echo "面积:" . $circle->calculateArea(); // 面积:78.54
$circle->resize(2);
echo "新面积:" . $circle->calculateArea(); // 新面积:314.16
// 使用接口的多态性
$shapes = [$circle, $rectangle];
foreach ($shapes as $shape) {
if ($shape instanceof Drawable) {
echo $shape->draw() . "\n";
}
}
?>特征
php
<?php
// 特征 - 可重用的代码块
trait Timestampable {
private $createdAt;
private $updatedAt;
public function setCreatedAt($timestamp = null) {
$this->createdAt = $timestamp ?: date('Y-m-d H:i:s');
}
public function setUpdatedAt($timestamp = null) {
$this->updatedAt = $timestamp ?: date('Y-m-d H:i:s');
}
public function getCreatedAt() {
return $this->createdAt;
}
public function getUpdatedAt() {
return $this->updatedAt;
}
}
trait Validatable {
private $errors = [];
public function addError($field, $message) {
$this->errors[$field][] = $message;
}
public function getErrors() {
return $this->errors;
}
public function hasErrors() {
return !empty($this->errors);
}
public function clearErrors() {
$this->errors = [];
}
}
// 使用特征
class User {
use Timestampable, Validatable;
private $name;
private $email;
public function __construct($name, $email) {
$this->name = $name;
$this->email = $email;
$this->setCreatedAt();
$this->validate();
}
private function validate() {
if (empty($this->name)) {
$this->addError('name', '姓名是必需的');
}
if (!filter_var($this->email, FILTER_VALIDATE_EMAIL)) {
$this->addError('email', '邮箱格式无效');
}
}
public function getName() {
return $this->name;
}
public function getEmail() {
return $this->email;
}
public function setName($name) {
$this->name = $name;
$this->setUpdatedAt();
$this->validate();
}
}
$user = new User("张三", "zhangsan@example.com");
echo "创建时间:" . $user->getCreatedAt();
echo "是否有错误:" . ($user->hasErrors() ? '是' : '否');
$user->setName("");
if ($user->hasErrors()) {
print_r($user->getErrors());
}
?>处理复杂数据结构
嵌套数组和对象
php
<?php
// 复杂嵌套结构
$company = [
"name" => "科技公司",
"founded" => 2010,
"departments" => [
"engineering" => [
"manager" => "张经理",
"employees" => [
["name" => "李开发", "role" => "高级开发工程师", "salary" => 90000],
["name" => "王设计", "role" => "初级开发工程师", "salary" => 60000],
["name" => "赵运维", "role" => "DevOps工程师", "salary" => 85000]
]
],
"marketing" => [
"manager" => "刘营销",
"employees" => [
["name" => "陈经理", "role" => "营销经理", "salary" => 75000],
["name" => "孙创作", "role" => "内容创作者", "salary" => 55000]
]
]
]
];
// 访问嵌套数据
echo $company["name"]; // "科技公司"
echo $company["departments"]["engineering"]["manager"]; // "张经理"
echo $company["departments"]["engineering"]["employees"][0]["name"]; // "李开发"
// 处理嵌套数据
function calculateDepartmentPayroll($department) {
$total = 0;
foreach ($department["employees"] as $employee) {
$total += $employee["salary"];
}
return $total;
}
function getCompanyStats($company) {
$stats = [
"total_employees" => 0,
"total_payroll" => 0,
"departments" => []
];
foreach ($company["departments"] as $deptName => $department) {
$employeeCount = count($department["employees"]);
$payroll = calculateDepartmentPayroll($department);
$stats["departments"][$deptName] = [
"manager" => $department["manager"],
"employee_count" => $employeeCount,
"payroll" => $payroll
];
$stats["total_employees"] += $employeeCount;
$stats["total_payroll"] += $payroll;
}
return $stats;
}
$stats = getCompanyStats($company);
print_r($stats);
?>数组和对象的相互转换
php
<?php
// 数组到对象的转换
$array = [
"name" => "张三",
"age" => 30,
"address" => [
"street" => "主干道123号",
"city" => "北京"
]
];
// 简单转换(浅层)
$obj = (object) $array;
echo $obj->name; // "张三"
echo $obj->address["street"]; // "主干道123号"(仍然是数组)
// 深度转换函数
function arrayToObject($array) {
if (is_array($array)) {
$obj = new stdClass();
foreach ($array as $key => $value) {
$obj->$key = arrayToObject($value);
}
return $obj;
}
return $array;
}
$deepObj = arrayToObject($array);
echo $deepObj->name; // "张三"
echo $deepObj->address->street; // "主干道123号"(现在是对象属性)
// 对象到数组的转换
function objectToArray($obj) {
if (is_object($obj)) {
$array = [];
foreach (get_object_vars($obj) as $key => $value) {
$array[$key] = objectToArray($value);
}
return $array;
}
return $obj;
}
$backToArray = objectToArray($deepObj);
print_r($backToArray);
// JSON转换(处理嵌套结构)
$jsonString = json_encode($array);
$objFromJson = json_decode($jsonString); // 对象
$arrayFromJson = json_decode($jsonString, true); // 数组
?>数据操作模式
php
<?php
// 数据管理的仓库模式
class UserRepository {
private $users = [];
public function add($user) {
$this->users[] = $user;
}
public function findById($id) {
foreach ($this->users as $user) {
if ($user['id'] === $id) {
return $user;
}
}
return null;
}
public function findByEmail($email) {
return array_filter($this->users, function($user) use ($email) {
return $user['email'] === $email;
});
}
public function update($id, $data) {
foreach ($this->users as &$user) {
if ($user['id'] === $id) {
$user = array_merge($user, $data);
return true;
}
}
return false;
}
public function delete($id) {
foreach ($this->users as $index => $user) {
if ($user['id'] === $id) {
unset($this->users[$index]);
$this->users = array_values($this->users); // Reindex
return true;
}
}
return false;
}
public function getAll() {
return $this->users;
}
public function filter($callback) {
return array_filter($this->users, $callback);
}
public function map($callback) {
return array_map($callback, $this->users);
}
}
// Usage
$repo = new UserRepository();
$repo->add(['id' => 1, 'name' => '张三', 'email' => 'zhangsan@example.com', 'active' => true]);
$repo->add(['id' => 2, 'name' => '李四', 'email' => 'lisi@example.com', 'active' => false]);
$repo->add(['id' => 3, 'name' => '王五', 'email' => 'wangwu@example.com', 'active' => true]);
// 查找操作
$user = $repo->findById(2);
echo "找到用户:" . $user['name'];
$activeUsers = $repo->filter(function($user) {
return $user['active'];
});
echo "活跃用户数:" . count($activeUsers);
// 转换数据
$userNames = $repo->map(function($user) {
return $user['name'];
});
print_r($userNames); // ['张三', '李四', '王五']
// 更新和删除
$repo->update(2, ['active' => true]);
$repo->delete(3);
print_r($repo->getAll());
?>下一步
现在您已经了解了数组和对象,让我们在API和接口中探索API和接口。
实践练习
- 使用数组和对象创建一个购物车系统
- 构建一个具有CRUD操作的简单数据库系统
- 为不同类型的车辆实现一个类层次结构
- 使用数组函数创建一个数据处理管道
- 使用嵌套数组构建一个配置管理系统
理解数组和对象是构建复杂PHP应用程序的基础!