PHP的魔法方法__set, __get

php的魔法方法__set()与__get()

Tags: PHP

我们先来看看官方的文档如何定义他们的:

public void __set(string $name, mixed $value);

public mixed __get(string $name);

在给不可访问的属性赋值时,__set()会被调用。

读取不可访问的属性的值时,__get()会被调用。

在实际的应用中,经常需要将一些属性设置为私有的属性,不能为外部随便的更改,这个时候要更改不可见的属性的时候可以通过:

  1. 创建一个专门用于设置与读取值得setter,getter。
  2. 使用php的魔法方法__set(), __get()便可以方便的设置与读取属性。

有代码才有真相嘛:

<?php

/** setget.php **/

/**
* 测试__set()和__get()的作用于用法
*/
class Person {

        private $name;
        private $age = 20;

        // 故意设置为public
        public $sex = 'girl';
        
        function __construct() {
        }

        public function __set($name, $value) {
                echo 'setting ' . $name . ' to ' . $value . '<br />';
                $this->$name = $value;
        }

        public function __get($name) {
                echo 'getting ' . $name . ' ';
                return isset($this->$name) ? $this->$name : null;
        }
}

echo '<pre>';

$person = new Person();

$person->name = 'tingyugetc';
echo $person->name . '<br />';

$person->sex = 'boy';
echo $person->sex . '<br />';

$person->age = 21;
echo $person->age . '<br />';

$person->city = '南京';
echo $person->city . '<br />';

print_r($person);

echo 'unset<br />';

unset($person->city);

//不可以对不可见属性直接调用unset,需要重载__unset()才可以
//PHP Fatal error:  Cannot access private property Person::$name in setget.php on line 47
// unset($person->name);

print_r($person);

/**
* 测试不使用__set(),__get()时访问不可见的属性
*/
class Student {
        
        private $name;
        public $core;

        function __construct() {
        
        }

}

$student = new Student();

// 不可以直接访问不可见属性
//  PHP Fatal error:  Cannot access private property Student::$name in setget.php on line 66
// $student->name = 'tingyugetc';
// echo $student->name . '<br />';

$student->core = 100;
echo $student->core . '<br />';

print_r($student);

?>

以上代码的输出结果为:

        此处可见对于private属性的访问调用了__set,__get
setting name to tingyugetc
getting name tingyugetc
        此处可见对于public属性的访问没有调用
boy
setting age to 21
getting age 21
        此处可见对于类中没有定义的属性在set的时候会调用__set()
        然而在读取的时候并不调用__get
        对象新创建的属性默认为public
setting city to 南京
南京
Person Object
(
    [name:Person:private] => tingyugetc
    [age:Person:private] => 21
    [sex] => boy
    [city] => 南京
)
unset
Person Object
(
    [name:Person:private] => tingyugetc
    [age:Person:private] => 21
    [sex] => boy
)
100
Student Object
(
    [name:Student:private] => 
    [core] => 100
)