php类的魔术方法的含义及应用场景
php类的魔术方法
php类的魔术方法基本上是成对出现的,最常用的就是构造方法__construct()
,对应的还有析构方法destruct()
。除此之外还有:
__get,__set
__set当给不可访问或不存在属性赋值时被调用
__get读取不可访问或不存在属性时被调用__isset,__unset
__isset对不可访问或不存在的属性调用isset()或empty()时被调用
__unset对不可访问或不存在的属性进行unset时被调用__call,__callStatic
__call调用不可访问或不存在的方法时被调用
__callStatic调用不可访问或不存在的静态方法时被调用__sleep,__wakeup
__sleep当使用serialize时被调用,当你不需要保存大对象的所有数据时很有用
__wakeup当使用unserialize时被调用,可用于做些对象的初始化操作__clone
进行对象clone时被调用,用来调整对象的克隆行为
__toString
当一个类被转换成字符串时被调用
__invoke
当以函数方式调用对象时被调用
__set_state
当调用var_export()导出类时,此静态方法被调用。用__set_state的返回值做为var_export的返回值。
__debuginfo
当调用var_dump()打印对象时被调用(当你不想打印所有属性)
__get,__set
的应用场景
用过框架的人往往不会陌生,我们可以直接给模型类对象的属性赋值,不管该属性是否存在,好像很神奇。
在模型类中,几乎所有的属性我们都定义为protected
,只有方法会定义成public
。究竟怎么赋值呢?
很简单,在模型内维护一个受保护的$data
属性,值为数组。
当使用$modelnstanse->foo = 'bar';
的方式赋值时或使用$foo = $modelnstanse->foo;
取值时,会经过__get / __set
方法处理,操作的是$data
属性。
__call,__callStatic
的应用场景
还是举框架的例子。thinkphp6有个门面模式,比如Cache::set('name','value');
可以进行写入操作(看起来很方便),这是怎么实现的呢?
创建一个Facade
基类,再创建一个类继承该基类,重写getFacadeClass()
方法返回我们要实现门面模式的那个类的类名。
最核心的就是在基类中的__callStatic()
方法。当我们调用一个不存在的静态方法,会触发该方法执行。根据getFacadeClass()
的返回值来生成一个对象,然后执行指定的方法。
虽然thinkphp使用了Container容器来make,但是基本的逻辑和上面无差别。
__toString
应用场景
当我们将一个类以字符串的形式使用,会报致命错误:Fatal error: Uncaught Error: Object of class Foo could not be converted to string
,在类中实现该方法,就会使用其返回值。
虽然将类直接作为字符串使用的场景比较少,但是也不是没有。比如我们开发模型类想使其输出html格式的分页,就可以使用该函数实现。