哈喽,各位自习室的小伙伴们👋!
作为后端入门绕不开的语言,PHP 从“面向过程”到“面向对象”的跨越,是很多新手的第一个“坎”——明明背会了类和对象的定义,一写代码就懵,分不清 `$this` 该怎么用,搞不懂 public/private 到底有啥区别。
今天的「基础自习室」,咱们不聊空洞的理论,只从实战角度拆解 PHP 类与对象的核心用法,结合可直接运行的代码示例,帮你夯实面向对象的技术地基,搞定那些入门易混点。
一、先搞懂:类与对象到底是什么?
新手最容易犯的错,是把“类”和“对象”混为一谈。咱们用一个通俗的比喻讲清楚:
简单说:类是“模板”,对象是模板实例化后的“具体产物”。
二、核心语法:从定义到使用(附易混点提醒)
先看最基础的代码结构,咱们以“用户(User)”为例,一步步写:
1. 定义类:封装属性和方法
<?php// 定义User类(类名首字母建议大写,规范)classUser{ // 1. 定义属性(成员变量) // 访问修饰符:public(公开)、private(私有)、protected(受保护) public $username; // 用户名(公开) private $password; // 密码(私有,只能类内部访问,易混点!) public $age; // 年龄(公开) // 2. 构造方法:实例化对象时自动执行,用于初始化属性 // 易混点:构造方法名必须是 __construct(两个下划线) public function __construct($username, $password, $age) { $this->username = $username; // $this 代表当前对象本身 $this->password = $password; $this->age = $age; } // 3. 定义方法(成员函数):封装对象的行为 // 获取用户名 public function getUsername() { return $this->username; } // 私有属性不能直接访问,需通过方法获取(封装的核心思想) public function getPassword() { // 实际开发中不会直接返回密码,这里仅作示例 return md5($this->password); // 简单加密 } // 修改年龄(加个简单的逻辑:年龄不能小于0) public function setAge($newAge) { if($newAge >= 0) { $this->age = $newAge; } else { echo "年龄不能为负数!"; } } // 显示用户信息 public function showInfo() { echo "用户名:{$this->username},年龄:{$this->age},加密密码:{$this->getPassword()}"; }}?>
2. 实例化对象:使用类创建具体实例
<?php// 引入上面的User类(如果在同一个文件可省略)// require_once 'User.php';// 实例化对象:new 类名(构造方法参数)$user1 = new User("张三", "123456", 25);$user2 = new User("李四", "654321", 30);// 访问对象的公开属性和方法echo $user1->getUsername(); // 输出:张三$user1->setAge(26); // 修改年龄为26$user1->showInfo(); // 输出:用户名:张三,年龄:26,加密密码:e10adc3949ba59abbe56e057f20f883e// 易混点提醒:不能直接访问私有属性!下面这行代码会报错// echo $user1->password; // Fatal error: Uncaught Error: Cannot access private property User::$password?>
3. 核心易混点拆解
这里整理了新手最容易踩的3个坑:
1. `$this` 的使用场景:只能在类的成员方法内部使用,代表“当前实例化的对象”,不能在类外部或静态方法中用;
2. 访问修饰符的区别:
- private:仅类内部能访问(最常用的封装手段,比如密码、手机号等敏感信息);
3. 构造方法不是必须的:但没有构造方法时,实例化对象需要手动给属性赋值,不如构造方法高效。
三、实战案例:用户管理小功能(完整可运行)
结合上面的知识点,咱们写一个完整的“用户管理”小案例,涵盖类的定义、对象实例化、方法调用、封装核心逻辑:
<?php/** * 用户类:封装用户的属性和行为 */classUserManager{ // 私有属性:存储用户列表 private $userList = []; /** * 添加用户 * @param string $username 用户名 * @param string $password 密码 * @param int $age 年龄 * @return bool 添加成功返回true */ public function addUser($username, $password, $age) { // 校验用户名是否已存在(简单逻辑) foreach($this->userList as $user) { if($user['username'] == $username) { echo "用户名 {$username} 已存在!\n"; return false; } } // 加密密码(实际开发用password_hash(),这里简化) $encryptPwd = md5($password); // 添加用户到列表 $this->userList[] = [ 'username' => $username, 'password' => $encryptPwd, 'age' => $age ]; echo "用户 {$username} 添加成功!\n"; return true; } /** * 获取所有用户信息 * @return array 用户列表 */ public function getAllUsers() { return $this->userList; } /** * 根据用户名删除用户 * @param string $username 用户名 * @return bool 删除成功返回true */ public function deleteUser($username) { foreach($this->userList as $key => $user) { if($user['username'] == $username) { unset($this->userList[$key]); echo "用户 {$username} 删除成功!\n"; return true; } } echo "用户名 {$username} 不存在!\n"; return false; }}// -------------- 测试代码 --------------// 实例化用户管理对象$userMgr = new UserManager();// 添加用户$userMgr->addUser("张三", "123456", 25); // 输出:用户 张三 添加成功!$userMgr->addUser("张三", "789012", 26); // 输出:用户名 张三 已存在!$userMgr->addUser("李四", "654321", 30); // 输出:用户 李四 添加成功!// 获取所有用户并打印echo "当前用户列表:\n";print_r($userMgr->getAllUsers());// 删除用户$userMgr->deleteUser("李四"); // 输出:用户 李四 删除成功!echo "删除后用户列表:\n";print_r($userMgr->getAllUsers());?>
运行结果(控制台):
用户 张三 添加成功!用户名 张三 已存在!用户 李四 添加成功!当前用户列表:Array( [0] => Array ( [username] => 张三 [password] => e10adc3949ba59abbe56e057f20f883e [age] => 25 ) [1] => Array ( [username] => 李四 [password] => 6512bd43d9caa6e02c990b0a82652dca [age] => 30 ))用户 李四 删除成功!删除后用户列表:Array( [0] => Array ( [username] => 张三 [password] => e10adc3949ba59abbe56e057f20f883e [age] => 25 ))
这个案例虽然简单,但覆盖了面向对象的核心思想——封装:把用户的“添加、删除、查询”逻辑封装在 `UserManager` 类中,外部只需要调用方法,无需关心内部实现,既保证了代码的安全性(比如密码加密),也让代码更易维护。
四、入门必避坑:3个高频错误
1. 直接访问私有属性:新手常忽略访问修饰符,直接在类外调用 `$user->password`,导致报错;
2. 构造方法名写错:把 `__construct` 写成 `construct`(少一个下划线),构造方法不会执行;
3. 静态/实例混淆:在非静态方法中用 `self::` 访问实例属性,或在静态方法中用 `$this`,都会报错(后续自习室会专门讲静态属性/方法)。
总结
1. 核心概念:类是“模板”,对象是模板实例化的“具体产物”,面向对象的核心是封装;
2. 关键语法:`$this` 代表当前对象,构造方法用于初始化属性,private 修饰符实现封装;
3. 实战思路:写类时先明确“属性(数据)”和“方法(行为)”,把敏感逻辑封装在类内部,外部只通过方法交互。
如果这篇内容帮你理清了类与对象的思路,别忘了点赞+收藏🌟!后续「程序员的自习室」还会拆解 PHP 面向对象的继承、多态、接口等核心知识点,帮你一步步吃透后端基础。
最后,留个小思考题:如果想给上面的 `UserManager` 加一个“根据用户名修改年龄”的功能,该怎么写?评论区聊聊你的思路~