__get、__set、__isset、__unset
本课属于 Coddy PHP 学习旅程的“面向对象编程”单元。第 46 课,共 91 课。
PHP 提供了 4 个拦截属性访问的魔术方法:__get()、__set()、__isset() 和 __unset()。当你尝试访问不存在或无法访问的属性时,就会触发这些方法。
读取不可访问的属性时会调用 __get() 方法,而 __set() 用于处理对这类属性的写入。这样你就可以创建动态属性,或在访问属性时添加逻辑:
<?php
class DynamicObject {
private array $data = [];
public function __get(string $name): mixed {
return $this->data[$name] ?? null;
}
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
}
$obj = new DynamicObject();
$obj->title = "Hello";
$obj->count = 42;
echo $obj->title . " - " . $obj->count;
输出:
Hello - 42__isset() 方法会由 isset() 或 empty() 触发,而 __unset() 会响应 unset() 函数:
<?php
class DynamicObject {
private array $data = [];
public function __set(string $name, mixed $value): void {
$this->data[$name] = $value;
}
public function __isset(string $name): bool {
return isset($this->data[$name]);
}
public function __unset(string $name): void {
unset($this->data[$name]);
}
}
$obj = new DynamicObject();
$obj->name = "Test";
echo isset($obj->name) ? "exists" : "missing";
输出:
exists这些方法常用于创建灵活的数据容器、实现懒加载,或构建行为类似数组的对象,同时保持面向对象的结构。
挑战
简单让我们构建一个灵活的配置管理器,使用魔术方法动态存储设置。你的类会拦截属性访问,以管理配置值、检查设置是否存在,并在需要时删除设置:整个过程无需显式定义每个属性。
你将把代码分成两个文件:
Config.php:创建一个Config类,使用私有数组在内部存储配置值。实现全部四个属性魔术方法:__get($name):返回给定键对应的值;如果键不存在,则返回"undefined"__set($name, $value):将值存储在给定键下__isset($name):返回配置中是否存在该键__unset($name):从配置中删除该键
count()方法,返回已存储设置的数量。main.php:引入 Config 文件。你会收到 3 个输入:一个设置名称、一个设置值,以及第二个设置名称。创建一个Config实例,并执行以下操作:- 将第一个设置设为给定值
- 使用
isset()输出第一个设置是否存在:输出"exists"或"missing" - 输出第一个设置的值
- 输出当前设置数量
- 使用
unset()删除第一个设置 - 输出第一个设置现在是否存在:输出
"exists"或"missing" - 输出第二个设置的值(该设置从未被设置)
每项输出都应单独占一行。借助魔术方法,你可以使用自然的属性语法与 Config 对象交互,例如 $config->theme = "dark" 和 isset($config->theme),即使没有定义任何实际属性也可以。
亲手试试
<?php
require_once 'Config.php';
// 读取输入
$settingName1 = trim(fgets(STDIN));
$settingValue = trim(fgets(STDIN));
$settingName2 = trim(fgets(STDIN));
// TODO:创建一个 Config 实例
// TODO:将第一个设置设为给定值
// TODO:输出第一个设置是否存在("exists" 或 "missing")
// TODO:输出第一个设置的值
// TODO:输出当前设置的数量
// TODO:使用 unset() 移除第一个设置
// TODO:输出第一个设置现在是否存在("exists" 或 "missing")
// TODO:输出第二个设置的值(该设置从未被设置过)
?>这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
8魔术方法
魔术方法简介__toString 和 __debugInfo__get、__set、__isset、__unset__call 和 __callStatic__clone 和对象克隆__serialize 和 __unserialize回顾:自定义集合自己练习: PHP 在线编译器