设为首页 收藏本站
查看: 747|回复: 0

[经验分享] php的魔术方法(转)

[复制链接]

尚未签到

发表于 2017-3-25 08:48:50 | 显示全部楼层 |阅读模式
从php5以后的版本,类就可以使用魔术方法了。php规定以两个下划线(__)开头的方法都保留为魔术方法,所以建议大家函数名最好不用__开头,除非是为了重载已有的魔术方法。

目前php已有的魔术方法有__construct,__destruct,__call,__get,__set,__isset,__unset,__sleep,__wakeup,__toString,__set_state 和 __clone。

__construct和__destruct是类的构造函数和析构函数,这个大家经常会用到,相信大家都很熟悉,这里就不多说了。

__sleep和__wakeup是序列化类的时候调用的。当序列化对象时,php将试图在序列动作之前调用该对象的成员函数__sleep(),当使用unserialize() 恢复对象时, 将调用__wakeup()。


__toString是对象被转为string时调用的,例如

view plaincopy to clipboardprint?
01.<?php   
02.class Str   
03.{   
04.    private $str;   
05.  
06.    public function __construct($str) {   
07.        $this->str = $str;   
08.    }   
09.  
10.    public function __toString() {   
11.        return $this->str;   
12.    }   
13.}   
14.  
15.$class = new Str('Hello');   
16.echo $class; // 这里对象被转为了string,所以调用了__toString   
17.?>  
<?php
class Str
{
    private $str;

    public function __construct($str) {
        $this->str = $str;
    }

    public function __toString() {
        return $this->str;
    }
}

$class = new Str('Hello');
echo $class; // 这里对象被转为了string,所以调用了__toString
?>
上例将输出 Hello

__set_state是当用var_export()来导出类的时候调用的,这个魔术函数只有一个参数,这个参数是一个数组,用来指定export的时候得到的属性。一般很少用到。

__call, __get和__set 这三个魔术方法是最常用的,当调用类中不存在的方法时就会调用__call,而__get和__set则是访问和设置类不存在的成员变量时调用的。
这三个的函数原型如下:

view plaincopy to clipboardprint?
01.mixed __call(string $name, array $arguments)   
02.void __set(string $name, mixed $value)   
03.mixed __get(string $name)  
mixed __call(string $name, array $arguments)
void __set(string $name, mixed $value)
mixed __get(string $name)
__call的例子:

view plaincopy to clipboardprint?
01.<?php   
02.class Caller   
03.{   
04.    public function __call($method, $args)   
05.    {   
06.        echo "Method $method called:\n";   
07.        print_r($args);   
08.    }   
09.}   
10.  
11.$foo = new Caller();   
12.$foo->test(1, 2);   
13.?>  
<?php
class Caller
{
    public function __call($method, $args)
    {
        echo "Method $method called:\n";
        print_r($args);
    }
}

$foo = new Caller();
$foo->test(1, 2);
?>
上例将输出:
Method test called:
Array
(
    [0] => 1
    [1] => 2
)

__get 和 __set 的例子:

view plaincopy to clipboardprint?
01.<?php   
02.class a   
03.{   
04.    public $c = 0;   
05.    public $arr = array();   
06.      
07.    public function __set($k, $v)   
08.    {   
09.        echo $k . "\n";           
10.        echo $v . "\n";   
11.           
12.        $this->arr[$k] = $v;   
13.    }   
14.      
15.    public function __get($k)   
16.    {   
17.        echo "The value of $k is " . $this->arr[$k];   
18.    }   
19.}   
20.$a = new a;   
21.$a->b = 1; // 成员变量b不存在,所以会调用__set   
22.$a->c = 2; // 成员变量c是存在的,所以不调用__set,无任何输出   
23.$d = $a->b; // 成员变量b不存在,所以会调用__get   
24.?>  
<?php
class a
{
    public $c = 0;
    public $arr = array();
   
    public function __set($k, $v)
    {
        echo $k . "\n";        
        echo $v . "\n";
        
        $this->arr[$k] = $v;
    }
   
    public function __get($k)
    {
        echo "The value of $k is " . $this->arr[$k];
    }
}
$a = new a;
$a->b = 1; // 成员变量b不存在,所以会调用__set
$a->c = 2; // 成员变量c是存在的,所以不调用__set,无任何输出
$d = $a->b; // 成员变量b不存在,所以会调用__get
?>
上例将输出:
b
1
The value of b is 1

__isset和__unset这两个与__get和__set其实原理是差不多的,他们的原型如下:

view plaincopy to clipboardprint?
01.bool __isset(string $name)   
02.void __unset(string $name)  
bool __isset(string $name)
void __unset(string $name)
举个例子:

view plaincopy to clipboardprint?
01.<?php   
02.class a   
03.{      
04.    public $c = 3;   
05.    public $arr = array('a' => 1, 'b' => 2);   
06.      
07.    public function __isset($k)   
08.    {   
09.        return isset($this->arr[$k]);   
10.    }   
11.      
12.    public function __unset($k)   
13.    {   
14.        unset($this->arr[$k]);   
15.    }   
16.}   
17.$a = new a;   
18.  
19.var_dump(isset($a->a)); // 成员变量a不存在,所以调用__isset,返回true   
20.var_dump(isset($a->c)); // 成员变量c是存在的,没有调用__isset,同样返回true   
21.unset($a->b); // 成员变量b不存在,调用__unset   
22.var_dump($a);   
23.?>  
<?php
class a
{   
    public $c = 3;
    public $arr = array('a' => 1, 'b' => 2);
   
    public function __isset($k)
    {
        return isset($this->arr[$k]);
    }
   
    public function __unset($k)
    {
        unset($this->arr[$k]);
    }
}
$a = new a;

var_dump(isset($a->a)); // 成员变量a不存在,所以调用__isset,返回true
var_dump(isset($a->c)); // 成员变量c是存在的,没有调用__isset,同样返回true
unset($a->b); // 成员变量b不存在,调用__unset
var_dump($a);
?>
上例将输出:
bool(true)
bool(true)
object(a)#1 (2) {
["c"]=>
int(3)
["arr"]=>
array(1) {
    ["a"]=>
    int(1)
}
}

类复制(clone)的时候,如果有定义__clone这个魔术方法就会调用它。
举例如下:

view plaincopy to clipboardprint?
01.<?php   
02.class a   
03.{      
04.    public function __clone()   
05.    {   
06.        echo "object cloned\n";   
07.    }   
08.}   
09.$a = new a;   
10.  
11.$b = $a; // $b只是$a的引用,不是克隆,所以不调用__clone,没任何输出。   
12.$c = clone $a; // 调用了__clone,将输出 object cloned   
13.?>

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-354979-1-1.html 上篇帖子: php 封装JavaScript类 下篇帖子: extjs php 动态分页整理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表