Heim >php教程 >php手册 >php魔术方法属性重载方法 - 南十字

php魔术方法属性重载方法 - 南十字

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOriginal
2016-05-20 13:19:421065Durchsuche

php有一类很神奇的方法,这些方法是保留方法,通常不会在外部被显式调用,他们使用双下划线(__)开头,他们被称为魔术方法(Magic Methods)。php官方也不建议定义其他双下划线开头的方法。

这次介绍属性重载方法:get/set/isset/unset

<span style="color: #0000ff;">public</span> void __set ( <span style="color: #0000ff;">string</span> <span style="color: #800080;">$name</span> , <span style="color: #0000ff;">mixed</span> <span style="color: #800080;">$value</span><span style="color: #000000;"> )

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">mixed</span> __get ( <span style="color: #0000ff;">string</span> <span style="color: #800080;">$name</span><span style="color: #000000;"> )

</span><span style="color: #0000ff;">public</span> bool __isset ( <span style="color: #0000ff;">string</span> <span style="color: #800080;">$name</span><span style="color: #000000;"> )

</span><span style="color: #0000ff;">public</span> void __unset ( <span style="color: #0000ff;">string</span> <span style="color: #800080;">$name</span> )

这些方法触发的时机,都是在访问不可访问的属性的时候。

如以下:

<span style="color: #008080;"> 1</span> <span style="color: #000000;">php
</span><span style="color: #008080;"> 2</span> 
<span style="color: #008080;"> 3</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Cls{
</span><span style="color: #008080;"> 4</span> 
<span style="color: #008080;"> 5</span>     <span style="color: #0000ff;">private</span> <span style="color: #800080;">$a</span> = 0<span style="color: #000000;">;
</span><span style="color: #008080;"> 6</span>     <span style="color: #0000ff;">protected</span> <span style="color: #800080;">$b</span> = 1<span style="color: #000000;">;
</span><span style="color: #008080;"> 7</span>     <span style="color: #0000ff;">public</span> <span style="color: #800080;">$c</span> = 2<span style="color: #000000;">;
</span><span style="color: #008080;"> 8</span>     <span style="color: #0000ff;">var</span> <span style="color: #800080;">$d</span> = 3<span style="color: #000000;">;
</span><span style="color: #008080;"> 9</span> 
<span style="color: #008080;">10</span>     <span style="color: #0000ff;">private</span> <span style="color: #800080;">$_properties</span> = <span style="color: #0000ff;">array</span>(0<span style="color: #000000;">);
</span><span style="color: #008080;">11</span> 
<span style="color: #008080;">12</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> __set(<span style="color: #800080;">$name</span>, <span style="color: #800080;">$value</span><span style="color: #000000;">){
</span><span style="color: #008080;">13</span>         <span style="color: #0000ff;">echo</span> <span style="color: #ff00ff;">__METHOD__</span> . ' is called! ' . json_encode(<span style="color: #008080;">func_get_args</span>()) . "\n"<span style="color: #000000;">;
</span><span style="color: #008080;">14</span>         <span style="color: #0000ff;">return</span> <span style="color: #800080;">$this</span>->_properties[<span style="color: #800080;">$name</span>] = <span style="color: #800080;">$value</span><span style="color: #000000;">;
</span><span style="color: #008080;">15</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">16</span> 
<span style="color: #008080;">17</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> __get(<span style="color: #800080;">$name</span><span style="color: #000000;">){
</span><span style="color: #008080;">18</span>         <span style="color: #0000ff;">echo</span> <span style="color: #ff00ff;">__METHOD__</span> . ' is called! ' . json_encode(<span style="color: #008080;">func_get_args</span>()) . "\n"<span style="color: #000000;">;
</span><span style="color: #008080;">19</span>         <span style="color: #0000ff;">return</span> <span style="color: #800080;">$this</span>->_properties[<span style="color: #800080;">$name</span><span style="color: #000000;">];
</span><span style="color: #008080;">20</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">21</span> 
<span style="color: #008080;">22</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> __isset(<span style="color: #800080;">$name</span><span style="color: #000000;">){
</span><span style="color: #008080;">23</span>         <span style="color: #0000ff;">echo</span> <span style="color: #ff00ff;">__METHOD__</span> . ' is called! ' . json_encode(<span style="color: #008080;">func_get_args</span>()) . "\n"<span style="color: #000000;">;
</span><span style="color: #008080;">24</span>         <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$this</span>->_properties[<span style="color: #800080;">$name</span><span style="color: #000000;">]);
</span><span style="color: #008080;">25</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">26</span> 
<span style="color: #008080;">27</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> __unset(<span style="color: #800080;">$name</span><span style="color: #000000;">){
</span><span style="color: #008080;">28</span>         <span style="color: #0000ff;">echo</span> <span style="color: #ff00ff;">__METHOD__</span> . ' is called! ' . json_encode(<span style="color: #008080;">func_get_args</span>()) . "\n"<span style="color: #000000;">;
</span><span style="color: #008080;">29</span>         <span style="color: #0000ff;">unset</span>(<span style="color: #800080;">$this</span>->_properties[<span style="color: #800080;">$name</span><span style="color: #000000;">]);
</span><span style="color: #008080;">30</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">31</span> 
<span style="color: #008080;">32</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> dump(){
</span><span style="color: #008080;">33</span>         <span style="color: #0000ff;">echo</span> "====================== DUMP START ====================\n"<span style="color: #000000;">;
</span><span style="color: #008080;">34</span>         <span style="color: #0000ff;">echo</span> STR
<span style="color: #008080;">35</span>     a: <span style="color: #800080;">$this</span>-><span style="color: #000000;">a
</span><span style="color: #008080;">36</span>     b: <span style="color: #800080;">$this</span>-><span style="color: #000000;">b
</span><span style="color: #008080;">37</span>     c: <span style="color: #800080;">$this</span>-><span style="color: #000000;">c
</span><span style="color: #008080;">38</span>     d: <span style="color: #800080;">$this</span>-><span style="color: #000000;">d\n
</span><span style="color: #008080;">39</span> <span style="color: #000000;">STR;
</span><span style="color: #008080;">40</span>         <span style="color: #0000ff;">foreach</span>(<span style="color: #800080;">$this</span>->_properties <span style="color: #0000ff;">as</span> <span style="color: #800080;">$k</span> => <span style="color: #800080;">$v</span><span style="color: #000000;">){
</span><span style="color: #008080;">41</span>             <span style="color: #0000ff;">echo</span> STR
<span style="color: #008080;">42</span>     Property <span style="color: #800080;">$k</span>: <span style="color: #800080;">$v</span><span style="color: #000000;">\n
</span><span style="color: #008080;">43</span> <span style="color: #000000;">STR;
</span><span style="color: #008080;">44</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">45</span>     
<span style="color: #008080;">46</span>         <span style="color: #0000ff;">echo</span> "====================== DUMP STOP =====================\n"<span style="color: #000000;">;
</span><span style="color: #008080;">47</span>         
<span style="color: #008080;">48</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">49</span> <span style="color: #000000;">}
</span><span style="color: #008080;">50</span> <span style="color: #800080;">$string</span> = 'abcdef'<span style="color: #000000;">;
</span><span style="color: #008080;">51</span> <span style="color: #800080;">$obj</span> = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Cls();
</span><span style="color: #008080;">52</span> 
<span style="color: #008080;">53</span> <span style="color: #800080;">$list</span> = <span style="color: #0000ff;">array</span>('isset', 'get', 'set', 'isset', 'unset', 'isset'<span style="color: #000000;">);
</span><span style="color: #008080;">54</span> <span style="color: #800080;">$obj</span>-><span style="color: #000000;">dump();
</span><span style="color: #008080;">55</span> <span style="color: #0000ff;">foreach</span>(<span style="color: #800080;">$list</span> <span style="color: #0000ff;">as</span> <span style="color: #800080;">$method</span><span style="color: #000000;">){
</span><span style="color: #008080;">56</span>     <span style="color: #0000ff;">for</span>(<span style="color: #800080;">$i</span> = 0 ; <span style="color: #800080;">$i</span> strlen(<span style="color: #800080;">$string</span>) ; <span style="color: #800080;">$i</span> ++<span style="color: #000000;">){
</span><span style="color: #008080;">57</span>         <span style="color: #800080;">$char</span> = <span style="color: #800080;">$string</span>{<span style="color: #800080;">$i</span><span style="color: #000000;">};
</span><span style="color: #008080;">58</span>         <span style="color: #0000ff;">echo</span> "------ <span style="color: #800080;">$method</span> : <span style="color: #800080;">$char</span> ------\n"<span style="color: #000000;">;
</span><span style="color: #008080;">59</span>         <span style="color: #0000ff;">switch</span>(<span style="color: #800080;">$method</span><span style="color: #000000;">){
</span><span style="color: #008080;">60</span>             <span style="color: #0000ff;">case</span> 'isset':
<span style="color: #008080;">61</span>                 <span style="color: #0000ff;">echo</span> json_encode(<span style="color: #800080;">$tmp</span> = <span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$obj</span>-><span style="color: #800080;">$char</span>)) . "\n"<span style="color: #000000;">;
</span><span style="color: #008080;">62</span>                 <span style="color: #0000ff;">break</span><span style="color: #000000;">;
</span><span style="color: #008080;">63</span>             <span style="color: #0000ff;">case</span> 'get':
<span style="color: #008080;">64</span>                 <span style="color: #0000ff;">echo</span> json_encode(<span style="color: #800080;">$tmp</span> = <span style="color: #800080;">$obj</span>-><span style="color: #800080;">$char</span>) . "\n"<span style="color: #000000;">;
</span><span style="color: #008080;">65</span>                 <span style="color: #0000ff;">break</span><span style="color: #000000;">;
</span><span style="color: #008080;">66</span>             <span style="color: #0000ff;">case</span> 'set':
<span style="color: #008080;">67</span>                 <span style="color: #0000ff;">echo</span> json_encode(<span style="color: #800080;">$tmp</span> = <span style="color: #800080;">$obj</span>-><span style="color: #800080;">$char</span> = <span style="color: #800080;">$char</span> . "-val") . "\n"<span style="color: #000000;">;
</span><span style="color: #008080;">68</span>                 <span style="color: #0000ff;">break</span><span style="color: #000000;">;
</span><span style="color: #008080;">69</span>             <span style="color: #0000ff;">case</span> 'unset':
<span style="color: #008080;">70</span>                 <span style="color: #0000ff;">unset</span>(<span style="color: #800080;">$obj</span>-><span style="color: #800080;">$char</span><span style="color: #000000;">);
</span><span style="color: #008080;">71</span>                 <span style="color: #0000ff;">break</span><span style="color: #000000;">;
</span><span style="color: #008080;">72</span>             <span style="color: #0000ff;">default</span>:
<span style="color: #008080;">73</span>                 <span style="color: #0000ff;">break</span><span style="color: #000000;">;
</span><span style="color: #008080;">74</span> <span style="color: #000000;">        }
</span><span style="color: #008080;">75</span> <span style="color: #000000;">    }
</span><span style="color: #008080;">76</span>     <span style="color: #800080;">$obj</span>-><span style="color: #000000;">dump();
</span><span style="color: #008080;">77</span> }

结果输出:

====================== DUMP START ====================<span style="color: #000000;">
    a</span>: 0<span style="color: #000000;">
    b</span>: 1<span style="color: #000000;">
    c</span>: 2<span style="color: #000000;">
    d</span>: 3<span style="color: #000000;">
    Property </span>0: 0
====================== DUMP STOP =====================
------ <span style="color: #0000ff;">isset</span> : a ------<span style="color: #000000;">
Cls</span>::__isset is called! ["a"<span style="color: #000000;">]
</span><span style="color: #0000ff;">false</span>
------ <span style="color: #0000ff;">isset</span> : b ------<span style="color: #000000;">
Cls</span>::__isset is called! ["b"<span style="color: #000000;">]
</span><span style="color: #0000ff;">false</span>
------ <span style="color: #0000ff;">isset</span> : c ------
<span style="color: #0000ff;">true</span>
------ <span style="color: #0000ff;">isset</span> : d ------
<span style="color: #0000ff;">true</span>
------ <span style="color: #0000ff;">isset</span> : e ------<span style="color: #000000;">
Cls</span>::__isset is called! ["e"<span style="color: #000000;">]
</span><span style="color: #0000ff;">false</span>
------ <span style="color: #0000ff;">isset</span> : f ------<span style="color: #000000;">
Cls</span>::__isset is called! ["f"<span style="color: #000000;">]
</span><span style="color: #0000ff;">false</span>
====================== DUMP START ====================<span style="color: #000000;">
    a</span>: 0<span style="color: #000000;">
    b</span>: 1<span style="color: #000000;">
    c</span>: 2<span style="color: #000000;">
    d</span>: 3<span style="color: #000000;">
    Property </span>0: 0
====================== DUMP STOP =====================
------ get : a ------<span style="color: #000000;">
Cls</span>::__get is called! ["a"<span style="color: #000000;">]
</span><span style="color: #0000ff;">null</span>
------ get : b ------<span style="color: #000000;">
Cls</span>::__get is called! ["b"<span style="color: #000000;">]
</span><span style="color: #0000ff;">null</span>
------ get : c ------
2
------ get : d ------
3
------ get : e ------<span style="color: #000000;">
Cls</span>::__get is called! ["e"<span style="color: #000000;">]
</span><span style="color: #0000ff;">null</span>
------ get : f ------<span style="color: #000000;">
Cls</span>::__get is called! ["f"<span style="color: #000000;">]
</span><span style="color: #0000ff;">null</span>
====================== DUMP START ====================<span style="color: #000000;">
    a</span>: 0<span style="color: #000000;">
    b</span>: 1<span style="color: #000000;">
    c</span>: 2<span style="color: #000000;">
    d</span>: 3<span style="color: #000000;">
    Property </span>0: 0
====================== DUMP STOP =====================
------ set : a ------<span style="color: #000000;">
Cls</span>::__set is called! ["a","a-val"<span style="color: #000000;">]
</span>"a-val"
------ set : b ------<span style="color: #000000;">
Cls</span>::__set is called! ["b","b-val"<span style="color: #000000;">]
</span>"b-val"
------ set : c ------
"c-val"
------ set : d ------
"d-val"
------ set : e ------<span style="color: #000000;">
Cls</span>::__set is called! ["e","e-val"<span style="color: #000000;">]
</span>"e-val"
------ set : f ------<span style="color: #000000;">
Cls</span>::__set is called! ["f","f-val"<span style="color: #000000;">]
</span>"f-val"
====================== DUMP START ====================<span style="color: #000000;">
    a</span>: 0<span style="color: #000000;">
    b</span>: 1<span style="color: #000000;">
    c</span>: c-<span style="color: #000000;">val
    d</span>: d-<span style="color: #000000;">val
    Property </span>0: 0<span style="color: #000000;">
    Property a</span>: a-<span style="color: #000000;">val
    Property b</span>: b-<span style="color: #000000;">val
    Property e</span>: e-<span style="color: #000000;">val
    Property f</span>: f-<span style="color: #000000;">val
</span>====================== DUMP STOP =====================
------ <span style="color: #0000ff;">isset</span> : a ------<span style="color: #000000;">
Cls</span>::__isset is called! ["a"<span style="color: #000000;">]
</span><span style="color: #0000ff;">true</span>
------ <span style="color: #0000ff;">isset</span> : b ------<span style="color: #000000;">
Cls</span>::__isset is called! ["b"<span style="color: #000000;">]
</span><span style="color: #0000ff;">true</span>
------ <span style="color: #0000ff;">isset</span> : c ------
<span style="color: #0000ff;">true</span>
------ <span style="color: #0000ff;">isset</span> : d ------
<span style="color: #0000ff;">true</span>
------ <span style="color: #0000ff;">isset</span> : e ------<span style="color: #000000;">
Cls</span>::__isset is called! ["e"<span style="color: #000000;">]
</span><span style="color: #0000ff;">true</span>
------ <span style="color: #0000ff;">isset</span> : f ------<span style="color: #000000;">
Cls</span>::__isset is called! ["f"<span style="color: #000000;">]
</span><span style="color: #0000ff;">true</span>
====================== DUMP START ====================<span style="color: #000000;">
    a</span>: 0<span style="color: #000000;">
    b</span>: 1<span style="color: #000000;">
    c</span>: c-<span style="color: #000000;">val
    d</span>: d-<span style="color: #000000;">val
    Property </span>0: 0<span style="color: #000000;">
    Property a</span>: a-<span style="color: #000000;">val
    Property b</span>: b-<span style="color: #000000;">val
    Property e</span>: e-<span style="color: #000000;">val
    Property f</span>: f-<span style="color: #000000;">val
</span>====================== DUMP STOP =====================
------ <span style="color: #0000ff;">unset</span> : a ------<span style="color: #000000;">
Cls</span>::__unset is called! ["a"<span style="color: #000000;">]
</span>------ <span style="color: #0000ff;">unset</span> : b ------<span style="color: #000000;">
Cls</span>::__unset is called! ["b"<span style="color: #000000;">]
</span>------ <span style="color: #0000ff;">unset</span> : c ------
------ <span style="color: #0000ff;">unset</span> : d ------
------ <span style="color: #0000ff;">unset</span> : e ------<span style="color: #000000;">
Cls</span>::__unset is called! ["e"<span style="color: #000000;">]
</span>------ <span style="color: #0000ff;">unset</span> : f ------<span style="color: #000000;">
Cls</span>::__unset is called! ["f"<span style="color: #000000;">]
</span>====================== DUMP START ====================<span style="color: #000000;">
Cls</span>::__get is called! ["c"<span style="color: #000000;">]
Cls</span>::__get is called! ["d"<span style="color: #000000;">]
    a</span>: 0<span style="color: #000000;">
    b</span>: 1<span style="color: #000000;">
    c</span>:<span style="color: #000000;"> 
    d</span>:<span style="color: #000000;"> 
    Property </span>0: 0
====================== DUMP STOP =====================
------ <span style="color: #0000ff;">isset</span> : a ------<span style="color: #000000;">
Cls</span>::__isset is called! ["a"<span style="color: #000000;">]
</span><span style="color: #0000ff;">false</span>
------ <span style="color: #0000ff;">isset</span> : b ------<span style="color: #000000;">
Cls</span>::__isset is called! ["b"<span style="color: #000000;">]
</span><span style="color: #0000ff;">false</span>
------ <span style="color: #0000ff;">isset</span> : c ------<span style="color: #000000;">
Cls</span>::__isset is called! ["c"<span style="color: #000000;">]
</span><span style="color: #0000ff;">false</span>
------ <span style="color: #0000ff;">isset</span> : d ------<span style="color: #000000;">
Cls</span>::__isset is called! ["d"<span style="color: #000000;">]
</span><span style="color: #0000ff;">false</span>
------ <span style="color: #0000ff;">isset</span> : e ------<span style="color: #000000;">
Cls</span>::__isset is called! ["e"<span style="color: #000000;">]
</span><span style="color: #0000ff;">false</span>
------ <span style="color: #0000ff;">isset</span> : f ------<span style="color: #000000;">
Cls</span>::__isset is called! ["f"<span style="color: #000000;">]
</span><span style="color: #0000ff;">false</span>
====================== DUMP START ====================<span style="color: #000000;">
Cls</span>::__get is called! ["c"<span style="color: #000000;">]
Cls</span>::__get is called! ["d"<span style="color: #000000;">]
    a</span>: 0<span style="color: #000000;">
    b</span>: 1<span style="color: #000000;">
    c</span>:<span style="color: #000000;"> 
    d</span>:<span style="color: #000000;"> 
    Property </span>0: 0
====================== DUMP STOP =====================

特别强调,当这个属性不存在(基于当前访问权限)的时候,才会触发这些方法。因此严重建议使用确定的键值进行get/set处理,特别是对应的键值不要有访问权限问题,如上例中的a和b,会导致在类内部、类外部、子类内处理的方式不同,开发时产生不可预知的返回值,极易产生bug。

empty方法不能调用属性重载方法。

<span style="color: #800080;">$tmp</span> = <span style="color: #800080;">$obj</span>-><span style="color: #800080;">$char</span> = <span style="color: #800080;">$char</span> . "-val"

此例中,__set自身的返回值将被忽略,同样__get也不会被调用。

此外:属性重载方法必须声明为public,同时参数不能使用引用传递,静态属性不能通过这些方法重载,这些方法也不能被声明为static。

当然,使用魔术方法的时候,也会对反射系统造成影响。

 

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn