• php魔术方法——属性重载方法


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

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

    public void __set ( string $name , mixed $value )
    
    public mixed __get ( string $name )
    
    public bool __isset ( string $name )
    
    public void __unset ( string $name )

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

    如以下:

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

    结果输出:

    ====================== DUMP START ====================
        a: 0
        b: 1
        c: 2
        d: 3
        Property 0: 0
    ====================== DUMP STOP =====================
    ------ isset : a ------
    Cls::__isset is called! ["a"]
    false
    ------ isset : b ------
    Cls::__isset is called! ["b"]
    false
    ------ isset : c ------
    true
    ------ isset : d ------
    true
    ------ isset : e ------
    Cls::__isset is called! ["e"]
    false
    ------ isset : f ------
    Cls::__isset is called! ["f"]
    false
    ====================== DUMP START ====================
        a: 0
        b: 1
        c: 2
        d: 3
        Property 0: 0
    ====================== DUMP STOP =====================
    ------ get : a ------
    Cls::__get is called! ["a"]
    null
    ------ get : b ------
    Cls::__get is called! ["b"]
    null
    ------ get : c ------
    2
    ------ get : d ------
    3
    ------ get : e ------
    Cls::__get is called! ["e"]
    null
    ------ get : f ------
    Cls::__get is called! ["f"]
    null
    ====================== DUMP START ====================
        a: 0
        b: 1
        c: 2
        d: 3
        Property 0: 0
    ====================== DUMP STOP =====================
    ------ set : a ------
    Cls::__set is called! ["a","a-val"]
    "a-val"
    ------ set : b ------
    Cls::__set is called! ["b","b-val"]
    "b-val"
    ------ set : c ------
    "c-val"
    ------ set : d ------
    "d-val"
    ------ set : e ------
    Cls::__set is called! ["e","e-val"]
    "e-val"
    ------ set : f ------
    Cls::__set is called! ["f","f-val"]
    "f-val"
    ====================== DUMP START ====================
        a: 0
        b: 1
        c: c-val
        d: d-val
        Property 0: 0
        Property a: a-val
        Property b: b-val
        Property e: e-val
        Property f: f-val
    ====================== DUMP STOP =====================
    ------ isset : a ------
    Cls::__isset is called! ["a"]
    true
    ------ isset : b ------
    Cls::__isset is called! ["b"]
    true
    ------ isset : c ------
    true
    ------ isset : d ------
    true
    ------ isset : e ------
    Cls::__isset is called! ["e"]
    true
    ------ isset : f ------
    Cls::__isset is called! ["f"]
    true
    ====================== DUMP START ====================
        a: 0
        b: 1
        c: c-val
        d: d-val
        Property 0: 0
        Property a: a-val
        Property b: b-val
        Property e: e-val
        Property f: f-val
    ====================== DUMP STOP =====================
    ------ unset : a ------
    Cls::__unset is called! ["a"]
    ------ unset : b ------
    Cls::__unset is called! ["b"]
    ------ unset : c ------
    ------ unset : d ------
    ------ unset : e ------
    Cls::__unset is called! ["e"]
    ------ unset : f ------
    Cls::__unset is called! ["f"]
    ====================== DUMP START ====================
    Cls::__get is called! ["c"]
    Cls::__get is called! ["d"]
        a: 0
        b: 1
        c: 
        d: 
        Property 0: 0
    ====================== DUMP STOP =====================
    ------ isset : a ------
    Cls::__isset is called! ["a"]
    false
    ------ isset : b ------
    Cls::__isset is called! ["b"]
    false
    ------ isset : c ------
    Cls::__isset is called! ["c"]
    false
    ------ isset : d ------
    Cls::__isset is called! ["d"]
    false
    ------ isset : e ------
    Cls::__isset is called! ["e"]
    false
    ------ isset : f ------
    Cls::__isset is called! ["f"]
    false
    ====================== DUMP START ====================
    Cls::__get is called! ["c"]
    Cls::__get is called! ["d"]
        a: 0
        b: 1
        c: 
        d: 
        Property 0: 0
    ====================== DUMP STOP =====================

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

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

    $tmp = $obj->$char = $char . "-val"

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

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

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

  • 相关阅读:
    情态动词
    形容词
    时态
    介词和介词短语
    句子成分
    被动语态
    C# Task使用CancellationTokenSource取消任务
    EntityFramework Core 迁移忽略主外键关系
    获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包
    .NET使用StackExchange.Redis
  • 原文地址:https://www.cnblogs.com/365star/p/5235524.html
Copyright © 2020-2023  润新知