Rumah >pembangunan bahagian belakang >tutorial php >php的魔术方法__get(),__set(),__call(),__callStatic()以及static用法详解

php的魔术方法__get(),__set(),__call(),__callStatic()以及static用法详解

伊谢尔伦
伊谢尔伦asal
2017-07-03 11:43:443233semak imbas

php5之后实现了一些魔术方法还是比较有意思的,之前一直用面向过程的编程方法,对oop研究的比较少,最近在看oop的东西,还是比较有意思的。

魔术方法这些东西,感觉很大一部分就是为了偷懒用的,记得最早写php的时候,那时候做博客,用的是国外的一个叫lifetype的开源框架,那时候还是php4.3,但是那个框架里全部实现了对象,所有的数据都被封装到对象中。

于是当从db里select出来一堆东西之后,还要逐个循环封装成对象,每一个字段也要实现getField()和getField()方法,写起来还真有点麻烦,感觉就是在做重复性的工作。

那么get(),set(),call(),callStatic()这几个魔术方法的诞生,就完全解决了这个问题。

get()和set()是针对类中属性的而call()是针对方法的,callStatic() 是针对静态类的方法。

一、get()和set()魔术方法:

当实例化一个对象后,调用类中不存在或者没有权限访问的属性的时候,php会默认调用get()方法,这样做,不仅可以少些很多代码,让结构更清晰,而且也提供了一条外部访问类的私有成员的一种方法。

比如:

<?php
class testGet
{
  private $name = &#39;test&#39;;
}
$test = new testGet();
$test->name;

上面的代码,如果我们运行,会报一个错误:PHP Fatal error:  Cannot access private property testGet::$name in /Library/WebServer/Documents/workspace/learn/call/a.php on line 7

但是我们修改一下,通过get()方法就可以访问

<?php
class testGet
{
  private $name = &#39;test&#39;;

  function get($property) {
    if ( isset($this->$property) ) 
      return $this->$property;
    else
      return NULL;
  }
}
$test = new testGet();
echo $test->name . PHP_EOL;

代码改成这样之后我们再访问就没有问题。 

注意:如果把属性定义成是static的,那么通过get()访问也会报错。原因是static的成员,是属于类本身的,不因为实例化而改变,可以自己测试。

利用set()方法,可以禁止动态创建类属性,这样可以很好的避免给后来开发者,或者程序维护者带来不必要的麻烦。

funciton set($property) {

//$property接收的是属性的名字

}

是实话,oop这个东西的设计,会掺杂很多设计者自己的思想,如果没有文档,后来者去读代码还是很费劲的,当然和后来者的水平也有很大关系。

下面是一个get和set配合使用的例子:

<?php
class testGet
{
  private $name = &#39;test&#39;;

  function get($property) {
    if ( isset($this->$property) ) 
      return $this->$property;
    else
      return NULL;
  }
  
  public function set($property, $value) {
    if ( isset($this->$property) )
      $this->$property = $value;
    else
      return NULL;
  }
}
$test = new testGet();
$test->name = &#39;my test name&#39;;
echo $test->name . PHP_EOL;

function set($property, $value) {

//$property接收的属性的名字

//$value接收的是属性的值

}

二、call()和callStatic()方法:

当对象调用类中一个不存在或者没有权限访问的方法的时候,就会自动调用call()方法。

记得以前有个同事问我,tp框架中为什么有很多底层的方法没有,但是在上层还能调用,其实就是call()这个方法在起作用。

如果你不知道这个方法,那么肯定会很疑惑,而且问题也不好定位。

<?php
abstract class Obj 
{
        private $objData        = array();
        /** 
         * call魔术方法,如果对象请求的方法不存在或者没有权限访问的时候
         * 调用魔术方法
         */
        public function call($name, $args) {
            $field = preg_match(&#39;/^get(\w+)/&#39;, $name, $matches);
            if ( $field && $matches[1] )
                return $this->objData[strtolower($matches[1])];
            $field = preg_match(&#39;/^set(\w+)/&#39;, $name, $matches);
            if ( $field && $matches[1] ) { 
                return $this->objData[strtolower($matches[1])] = $args[0];
            }   
        }   
}
class User extends Obj
{
        
}
$user = new User();
$user->setName(&#39;test&#39;);
echo $user->getName();

User类什么都没干,但是通过继承类的call()方法,把所有的事都做了(getName和setName)。

function call($methodName, $args) {

//$methodName调用的方法名

//$args传递的参数数组

}

和call()对应的是callStatic()方法,是位静态类的静态方法服务的。

例子:

<?php
    abstract class Obj 
    {
        private static $objData        = array();
        /** 
         * call魔术方法,如果对象请求的方法不存在或者没有权限访问的时候
         * 调用魔术方法
         */
        public static function callStatic($name, $args) {
            $field = preg_match(&#39;/^get(\w+)/&#39;, $name, $matches);
            if ( $field && $matches[1] )
                return self::$objData[strtolower($matches[1])];
            $field = preg_match(&#39;/^set(\w+)/&#39;, $name, $matches);
            if ( $field && $matches[1] ) { 
                return self::$objData[strtolower($matches[1])] = $args[0];
            }   
        }   
    }
    class User extends Obj 
    {
    
    }
    User::setName(&#39;test&#39;);
    echo User::getName() . PHP_EOL;

三、延迟静态绑定:static这个对象

Atas ialah kandungan terperinci php的魔术方法__get(),__set(),__call(),__callStatic()以及static用法详解. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn