在深入学习PHP面向对象编程之前,有必要先理解OOP的核心思想。面向对象编程是一种以“对象”为中心的编程范式——把现实世界中的事物抽象成代码中的对象,每个对象既有自己的数据(属性),也有自己能执行的操作(方法)。PHP从早期版本就开始支持面向对象编程,虽然4.x时代的OOP支持还比较薄弱,但从PHP 5开始,类的定义、继承、访问控制等特性已经趋于成熟,如今的PHP 8更是引入了联合类型、枚举、只读属性等现在化特性。
下面我们围绕PHP中类的定义和对象创建,把基本概念、语法细节和实际运用讲清楚。
一、OOP核心术语速览
在动手写代码之前,先了解一些面向对象编程中反复出现的基础术语,有助于后续内容的理解:
| 术语 | 说明 |
|---|---|
| 类(Class) | 用户自定义的数据类型,把变量和函数组合在一起形成统一的逻辑单元 |
| 对象(Object) | 根据类创建出来的具体实例,每个对象拥有类所定义的属性和方法 |
| 成员变量(Member Variable) | 定义在类内部的变量,也叫属性,用于存储对象的数据 |
| 成员函数(Member Function) | 定义在类内部的函数,也叫方法,用于操作对象的数据或执行相关逻辑 |
| 继承(Inheritance) | 子类从父类那里获得属性和方法的能力,是代码复用的重要手段 |
| 父类(Parent Class) | 被继承的基类,也叫超类或基类 |
| 子类(Child Class) | 继承父类的派生类,可以新增或重写父类的属性和方法 |
| 多态(Polymorphism) | 同一个方法名在不同类中可以有不同的行为表现 |
| 重载(Overloading) | PHP中的重载指通过魔术方法动态处理不可访问的属性或方法调用 |
| 数据抽象(Data Abstraction) | 对外暴露操作接口,隐藏内部实现细节 |
| 封装(Encapsulation) | 把数据和操作数据的方法捆绑在一起,控制外部访问权限 |
| 构造函数(Constructor) | 对象创建时自动调用的特殊方法,用于初始化 |
| 析构函数(Destructor) | 对象被销毁时自动调用的特殊方法,用于清理资源 |
二、PHP中定义类的语法
PHP用class关键字来声明一个类,后面跟类名和一对花括号,类体里可以定义属性和方法。
基本语法
<?php
class 类名 {
// 属性声明
var $属性名;
var $属性名 = "默认值";
// 方法声明
function 方法名($参数1, $参数2) {
// 方法体
}
}
?>
var是PHP中较早期的属性声明方式,效果等同于public。在现在的PHP版本里,更推荐直接用public、protected、private这些明确的访问修饰符,代码意图更清晰。
三、创建对象并调用成员方法
类定义好之后只是模板,要真正使用它,需要用new关键字创建对象实例。对象创建后,通过箭头运算符->来访问对象的属性和方法。
示例:汽车类的完整使用流程
<?php
// 定义汽车类
class Car {
// 成员变量(属性)
public $brand;
public $color;
// 设置品牌
function setBrand($brand) {
$this->brand = $brand;
}
// 获取品牌
function getBrand() {
return $this->brand;
}
// 设置颜色
function setColor($color) {
$this->color = $color;
}
// 获取颜色
function getColor() {
return $this->color;
}
}
// 创建三个汽车对象
$car1 = new Car();
$car2 = new Car();
$car3 = new Car();
// 为每辆车设置品牌和颜色
$car1->setBrand("比亚迪");
$car1->setColor("白色");
$car2->setBrand("蔚来");
$car2->setColor("蓝色");
$car3->setBrand("小鹏");
$car3->setColor("灰色");
// 输出每辆车的信息
echo $car1->getBrand() . " → " . $car1->getColor() . "<br>";
echo $car2->getBrand() . " → " . $car2->getColor() . "<br>";
echo $car3->getBrand() . " → " . $car3->getColor();
?>
输出结果
比亚迪 → 白色
蔚来 → 蓝色
小鹏 → 灰色
这个例子展示了面向对象编程的一个基本优势:同一份类代码,创建了三个互不干扰的对象实例,每个对象有各自的属性值。$this关键字在方法内部指向当前调用该方法的那个具体对象——在$car1->setBrand("比亚迪")执行时,$this指的就是$car1。
个人经验分享:初学OOP时容易被$this的写法绊住,总觉得多打了一个$符号。实际上可以这样理解:$this代表的是“当前这个对象整体”,而$this->brand表示“这个对象的brand属性”。如果方法里直接写$brand而不加$this->,PHP会把它当作方法内部的局部变量,和对象的属性毫无关系——这是很多新手调试半天才发现的细节。
四、$this关键字的两种典型用法
$this只能用在类的成员方法内部,指向调用该方法的对象实例。常见的使用方式有两种:
方式一:通过setter方法设置属性值
<?php
class Employee {
public $name;
public $position;
function setName($name) {
$this->name = $name; // $this->name 是对象属性,$name 是传入的参数
}
function setPosition($position) {
$this->position = $position;
}
}
$emp = new Employee();
$emp->setName("张伟");
$emp->setPosition("后端开发工程师");
echo "姓名:" . $emp->name . "<br>";
echo "职位:" . $emp->position;
?>
输出结果
姓名:张伟
职位:后端开发工程师
通过专门的方法来设置属性值,这是封装思想的一种体现——如果需要增加校验逻辑(比如姓名不能为空),只需要修改setName()方法内部,所有调用处都能自动生效。
方式二:直接从外部给public属性赋值
<?php
class Employee {
public $name;
public $position;
}
$emp1 = new Employee();
$emp1->name = "李娜";
$emp1->position = "产品经理";
$emp2 = new Employee();
$emp2->name = "王强";
$emp2->position = "UI设计师";
echo $emp1->name . " - " . $emp1->position . "<br>";
echo $emp2->name . " - " . $emp2->position;
?>
输出结果
李娜 - 产品经理
王强 - UI设计师
这种方式代码更简短,但属性必须是public才能从外部直接赋值。var声明在PHP中默认就是public的。
个人见解:两种方式各有适用场景。对于数据模型类的简单属性(如DTO、值对象),外部直接赋值写起来轻快;对于需要校验或涉及业务逻辑的属性,用setter方法封装更稳妥。实际项目中我一般会把核心业务对象的属性设为private或protected,只暴露必要的getter/setter,避免外部代码不小心把数据改乱。
五、完整实例:员工信息管理类
下面用一个员工信息管理的例子,把类的定义、对象创建、方法调用和$this的使用串联起来。
<?php
class Staff {
// 成员变量
public $name;
public $salary;
public $department;
// 设置姓名
function setName($name) {
$this->name = $name;
}
// 获取姓名
function getName() {
echo $this->name . "<br>";
}
// 设置薪资
function setSalary($salary) {
$this->salary = $salary;
}
// 获取薪资
function getSalary() {
echo $this->salary . "<br>";
}
// 设置部门
function setDepartment($dept) {
$this->department = $dept;
}
// 获取部门
function getDepartment() {
echo $this->department . "<br>";
}
}
// 创建员工对象
$staff1 = new Staff();
$staff2 = new Staff();
$staff3 = new Staff();
// 设置并输出员工1的信息
$staff1->setName("赵刚");
$staff1->setSalary("12000");
$staff1->setDepartment("技术部");
$staff1->getName();
$staff1->getSalary();
$staff1->getDepartment();
echo "<br>";
// 设置并输出员工2的信息
$staff2->setName("孙丽");
$staff2->setSalary("15000");
$staff2->setDepartment("市场部");
$staff2->getName();
$staff2->getSalary();
$staff2->getDepartment();
echo "<br>";
// 设置并输出员工3的信息
$staff3->setName("周杰");
$staff3->setSalary("9000");
$staff3->setDepartment("行政部");
$staff3->getName();
$staff3->getSalary();
$staff3->getDepartment();
?>
输出结果
赵刚
12000
技术部
孙丽
15000
市场部
周杰
9000
行政部
这个例子完整地演示了用类来管理结构化数据的基本模式。每个员工对象独立保存着自己的姓名、薪资和部门信息,相互之间不会串数据。如果后续需要对员工做扩展——比如增加入职日期、计算年薪、导出信息——直接在Staff类里加属性和方法就行,调用方不需要大规模改动。
本节课程知识要点
-
PHP用
class关键字定义类,类体内包含属性(变量)和方法(函数),是创建对象的模板。 -
使用
new关键字根据类创建对象实例,每个对象拥有独立的属性存储空间。 -
$this是类方法内部指向当前对象的引用,调用格式为$this->属性名或$this->方法名()。 -
访问修饰符
public、protected、private控制属性和方法的访问范围,推荐优先使用明确的修饰符替代var。 -
通过setter方法封装属性赋值的操作,可以在方法内部加入校验或业务逻辑,比直接从外部写属性更安全可控。
-
一个类可以创建多个对象实例,各实例之间的属性互不影响,这是面向对象编程管理数据的基本方式。
-
面向对象编程中涉及的继承、多态、封装、抽象等概念,都是以类和对象为基础衍生出来的高级特性。
掌握类的定义和对象的创建,是学习PHP面向对象编程的第一步。从简单的属性和方法组织,到$this的理解运用,再到合理的访问控制,这些都是后续学习继承、接口、Trait、命名空间等进阶内容的基础。把基础打扎实,面对更复杂的设计模式和框架源码时,理解起来会顺畅很多。