__get和__set仅在访问未声明或已被unset()的属性时触发;__call/__callStatic分别仅拦截不存在的实例/静态方法调用;__toString仅在字符串隐式转换时执行,且必须返回字符串。
哪些操作会触发 __get 和 __set
__get 和 __set 只在访问**不可见(private/protected)或不存在的属性**时触发,且类中**没有显式定义该属性**或该属性被 unset() 过。直接访问 public 属性、已声明的 protected/private 属性,都不会触发。
常见误判点:
- 写成
$obj->prop = 123但$prop已在类中声明为public $prop→ 不触发__set - 用了
isset($obj->prop)→ 触发__isset,不是__get - 对 null 值属性赋值:
$obj->prop = null,若$prop已存在(哪怕值为 null),仍不触发__set
__call 和 __callStatic 的调用边界在哪
__call 仅当调用**不存在的实例方法**时触发;__callStatic 同理,只响应**不存在的静态方法调用**。二者互不干扰,也不能靠“加 static 关键字”让 __call 拦截静态调用。
必须注意:
立即学习“PHP免费学习笔记(深入)”;
-
self::missingMethod()在类内部调用 → 触发__callStatic(即使方法不存在) -
static::missingMethod()在子类中重写后调用父类未实现的方法 → 仍触发__callStatic,不是父类的__call - 如果方法存在但访问控制为 private,报
Fatal error: Uncaught Error: Call to private method,根本不会走到__call
修改魔术方法触发行为的唯一合法途径
PHP 不允许动态“关闭”或“重定向”魔术方法的触发逻辑。所谓“修改触发条件”,实际只有两种可操作方式: