>  기사  >  백엔드 개발  >  PHP 매직 메소드 란 무엇입니까?

PHP 매직 메소드 란 무엇입니까?

青灯夜游
青灯夜游원래의
2023-01-04 18:32:174219검색

PHP에서 이중 밑줄 "__"로 시작하는 내장 메서드는 "__construct()", "__set()", "__get()", "__isset()", "__unset( )" ", "__sleep()", "__wakeup()", "__call()", "__invoke()" 등 그 중 "__construct()"는 클래스의 생성 메소드이며 첫 번째 객체입니다. 객체가 생성된 후 자동으로 호출되는 메서드입니다.

PHP 매직 메소드 란 무엇입니까?

이 튜토리얼의 운영 환경: windows7 시스템, PHP8 버전, DELL G3 컴퓨터

php의 Magic 메소드

PHP에서 이중 밑줄(__)로 시작하는 메소드는 다음과 같습니다. PHP에서 매직 메소드라고 불리는 이 메소드는 PHP에서 매우 중요한 역할을 합니다. 매직 메서드에는 다음이 포함됩니다.

메서드 이름 Description
__construct() 클래스 생성자
__destruct() 클래스 소멸자
__call($ funName, $ 인수) 정의되지 않았거나 연결할 수 없는 메서드가 호출되면 __call() 메서드가 호출됩니다.
__callStatic($funName, $arguments) 정의되지 않았거나 연결할 수 없는 정적 메서드가 호출되면 __callStatic() 메서드가 호출됩니다.
__get($propertyName) 클래스의 멤버 변수를 가져올 때 __get() 메서드가 호출됩니다.
__set($property, $value) 클래스의 멤버 변수를 할당할 때 __set() 메서드가 호출됩니다.
__isset($content) 정의되지 않았거나 연결할 수 없는 멤버에 값을 할당하기 위해 isset() 또는 empty()를 호출하면 __isset() 메서드가 호출됩니다.
__unset($content) 정의되지 않았거나 연결할 수 없는 멤버를 업데이트하기 위해 재설정()을 호출하면 __unset() 메서드가 호출됩니다.
__sleep() serialize()가 실행되면 __sleep() 메서드가 먼저 호출됩니다.
__wakeup() deserialization()이 수행되면 __wakeup() 메서드가 먼저 호출됩니다.
__toString() echo 메서드를 사용하여 표시 객체를 직접 출력하는 경우 __toString() 메서드가 먼저 호출됩니다.
__invoke() 함수를 사용하여 객체에 접근하면 __invoke() 메서드가 먼저 호출됩니다.
__set_state($an_array) var_export() 메서드가 호출되면 __set_state() 메서드가 호출됩니다.
__clone() 객체를 복사하고 할당하면 __clone() 메서드가 호출됩니다.
__autoload($className) 정의되지 않은 클래스를 로드하려고 할 때 호출됩니다.
__debugInfo() 디버그 정보를 출력합니다.

이 기사에서는 몇 가지 예를 사용하여 PHP 매직 메소드의 사용을 보여줍니다.

1.__construct()

객체를 생성할 때 PHP 클래스의 생성자 메서드가 가장 먼저 호출됩니다. 모든 클래스에는 생성자 메서드가 있습니다. 클래스에서 명시적으로 정의하지 않으면 인수가 없는 기본 클래스 생성자가 생성되지만 클래스에서 정의되지는 않습니다.

1) 생성자 메서드 적용

클래스의 생성자 메서드는 일반적으로 객체 생성 시 멤버에 값을 초기화하고 할당하는 등의 일부 초기화 작업을 수행하는 데 사용됩니다.

2) 클래스의 생성자 메서드 선언 형식

function __constrct([parameter list]){

    方法具体实现 //通常为成员变量初始赋值。

}

참고: 대부분의 클래스에서는 하나의 생성자만 선언할 수 있습니다. 왜냐하면 PHP는 생성자 오버로딩을 지원하지 않기 때문입니다.

전체 예는 다음과 같습니다.

<?php
    class Person
    {                                                                     
            public $name;       
            public $age;       
            public $sex;       

        /**
         * 明确定义含参的构造方法
         */                                                                                       
        public function __construct($name="", $sex="Male", $age=22)
        {     
            $this->name = $name;
            $this->sex = $sex;
            $this->age = $age;
        }

        /**
         * say 方法定义
         */
        public function say()
        {
            echo "Name:" . $this->name . ",Sex:" . $this->sex . ",Age:" . $this->age;
        }   

    }

매개변수 없이 $Person1 개체를 만듭니다.

$Person1 = new Person();
echo $Person1->say(); //显示:Name:,Sex:Male,Age:22

$Person2 개체를 생성하려면 "Jams" 매개변수 하나로 호출하세요.

$Person2 = new Person("Jams");
echo $Person2->say(); // 显示: Name: Jams, Sex: Male, Age: 22

$Person3 객체를 생성하기 위해 3개의 매개변수로 호출됩니다.

$Person3 = new Person ("Jack", "Male", 25);
echo $Person3->say(); // 显示:Name: Jack, Sex: Male, Age: 25

__destruct()

Destructor는 생성자의 반대입니다.

Destructor를 사용하면 객체를 파괴하기 전에 파일 닫기, 결과 집합 지우기 등과 같은 일부 작업을 수행할 수 있습니다.

Destructor는 PHP 5에 도입된 새로운 기능입니다.

소멸자의 선언은 생성자와 유사하며 두 개의 밑줄로 시작하고 이름은 __destruct()로 고정됩니다. __destruct()

析构函数的声明

function __destruct()
{
    //method body
}

析构函数不能带参数。

析构函数的使用

析构函数在类中一般不常见。它是类的可选部分,通常用于在类销毁之前完成一些清理任务。

这是使用析构函数的示例:

<?php
class Person{     

    public $name;         
    public $age;         
    public $sex;         

    public function __construct($name="", $sex="Male", $age=22)
    {   
        $this->name = $name;
        $this->sex  = $sex;
        $this->age  = $age;
    }

    /**
     * say method
     */
    public function say()
    {
        echo "Name:".$this->name.",Sex:".$this->sex.",Age:".$this->age;
    }   

    /**
     * declare a destructor method
     */
    public function __destruct()
    {
            echo "Well, my name is ".$this->name;
    }
}

$Person = new Person("John");
unset($Person); //destroy the object of $Person created above

输出结果

Well, my name is John

__call()

该方法接受两个参数。第一个参数为未定义的方法名称,第二个参数则为传入方法的参数构成的数组

使用

function __call(string $function_name, array $arguments)
{
    // method body
}

在程序中调用未定义方法时, __call() 方法将被调用。

示例

<?php
class Person
{                             
    function say()
    {
           echo "Hello, world!<br>";
    }     

    function __call($funName, $arguments)
    {
          echo "The function you called:" . $funName . "(parameter:" ;  // Print the method's name that is not existed.
          print_r($arguments); // Print the parameter list of the method that is not existed.
          echo ")does not exist!!<br>\n";                   
    }                                         
}
$Person = new Person();           
$Person->run("teacher"); // If the method which is not existed is called within the object, then the __call() method will be called automatically.
$Person->eat("John", "apple");             
$Person->say();

显示结果

The function you called: run (parameter: Array([0] => teacher)) does not exist!
The function you called: eat (parameter: Array([0] => John[1] => apple)) does not exist!
Hello world!

4. __callStatic()

当在程序中调用未定义的静态方法,__callStatic() 方法将会被自动调用。

__callStatic() 的用法类似于 __call() 。下面举个例子:

<?php
class Person
{
    function say()
    {
        echo "Hello, world!<br>";
    }

    public static function __callStatic($funName, $arguments)
    {
        echo "The static method you called:" . $funName . "(parameter:" ;  // 打印出未定义的方法名。
        print_r($arguments); // 打印出未定义方法的参数列表。
        echo ")does not exist!<br>\n";
    }
}
$Person = new Person();
$Person::run("teacher"); // 如果此项目内不存在的方法被调用了,那么 __callStatic() 方法将被自动调用。
$Person::eat("John", "apple");
$Person->say();

执行结果如下:

The static method you called: run (parameter: Array([0] => teacher)) does not exist!
The static method you called: eat (parameter: Array([0] => John[1] => apple)) does not exist!
Hello world!

__get()

当你尝试在外部访问对象的私有属性时,应用程序将抛出异常并结束运行。我们可以使用 __get 方法解决该问题。该方法可以获取从对象外部获取私有属性的值。举例如下

<?php
class Person
{
    private $name;
    private $age;

    function __construct($name="", $age=1)
    {
        $this->name = $name;
        $this->age = $age;
    }

    public function __get($propertyName)
    {   
        if ($propertyName == "age") {
            if ($this->age > 30) {
                return $this->age - 10;
            } else {
                return $this->$propertyName;
            }
        } else {
            return $this->$propertyName;
        }
    }
}
$Person = new Person("John", 60);   // Instantiate the object with the Person class and assign initial values to the properties with the constructor.
echo "Name:" . $Person->name . "<br>";   // When the private property is accessed, the __get() method will be called automatically,so we can get the property value indirectly.
echo "Age:" . $Person->age . "<br>";    // The __get() method is called automatically,and it returns different values according to the object itself.

结果显示如下

Name: John
Age: 50

6. __set()

set($property,$value)方法用于设置类的私有属性。分配了未定义的属性后,将触发set()方法,并且传递的参数是设置的属性名称和值。

下面是演示代码:

<?php
class Person
{
    private $name;
    private $age;

    public function __construct($name="",  $age=25)
    {
        $this->name = $name;
        $this->age  = $age;
    }

    public function __set($property, $value) {
        if ($property=="age")
        {
            if ($value > 150 || $value < 0) {
                return;
            }
        }
        $this->$property = $value;
    }

    public function say(){
        echo "My name is ".$this->name.",I'm ".$this->age." years old";
    }
}

$Person=new Person("John", 25); //请注意,类初始化并为“name”和“age”分配初始值。
$Person->name = "Lili";     // "name" 属性值被成功修改。如果没有__set()方法,程序将报错。
$Person->age = 16; // "age"属性修改成功。
$Person->age = 160; //160是无效值,因此修改失败。
$Person->say();  //输出:My name is Lili, I'm 16 years old。

代码运行结果:

My name is Lili, I'm 16 years old

7. __isset()

在使用__isset()方法之前,让我先解释一下isset()方法的用法。isset()方法主要用于确定是否设置了此变量。

如果在对象外部使用isset()方法,则有两种情况:

  1. 如果该参数是公共属性,则可以使用isset()方法确定是否设置了该属性。
  2. 如果参数是私有属性,则isset()方法将不起作用。

那么对于私有属性,有什么办法知道它是否被设置了吗?当然,只要在类中定义__isset()方法,就可以在类外部使用isset()方法来确定是否设置了私有属性。

当在未定义或不可访问的属性上调用isset()或empty()时,将调用__isset()方法。下面是一个例子:

<?php
class Person
{
    public $sex;
    private $name;
    private $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    /**
     * @param $content
     *
     * @return bool
     */
    public function __isset($content) {
        echo "The {$content} property is private,the __isset() method is called automatically.<br>";
        echo  isset($this->$content);
    }
}

$person = new Person("John", 25); // Initially assigned.
echo isset($person->sex),"<br>";
echo isset($person->name),"<br>";
echo isset($person->age),"<br>";

代码运行结果如下:

1
The name property is private,the __isset() method is called automatically.
1
The age property is private,the __isset() method is called automatically.
1

8. __unset()

isset()方法类似,当在未定义或不可访问的属性上调用unset()方法时,将调用unset()方法。下面是一个例子:

<?php
class Person
{
    public $sex;
    private $name;
    private $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    /**
     * @param $content
     *
     * @return bool
     */
    public function __unset($content) {
        echo "It is called automatically when we use the unset() method outside the class.<br>";
        echo  isset($this->$content);
    }
}

$person = new Person("John", 25); // Initially assigned.
unset($person->sex),"<br>";
unset($person->name),"<br>";
unset($person->age),"<br>";

代码的运行结果如下:

It is called automatically when we use the unset() method outside the class.
1
It is called automatically when we use the unset() method outside the class.
1

9. __sleep()

serialize()方法将检查类中是否有魔术方法__sleep()。如果存在,将首先调用该方法,然后执行序列化操作。

__sleep()方法通常用于指定保存数据之前需要序列化的属性。如果有一些非常大的对象不需要全部保存,那么您会发现此功能非常有用。

有关详细信息,请参考以下代码:

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    /**
     * @return array
     */
    public function __sleep() {
        echo "It is called when the serialize() method is called outside the class.<br>";
        $this->name = base64_encode($this->name);
        return array('name', 'age'); // It must return a value of which the elements are the name of the properties returned.
    }
}

$person = new Person('John'); // Initially assigned.
echo serialize($person);
echo '<br/>';

代码运行结果如下:

It is called when the serialize() method is called outside the class.
O:6:"Person":2:{s:4:"name";s:8:"5bCP5piO";s:3:"age";i:25;}

10. __wakeup()

sleep()方法相比,wakeup()方法通常用于反序列化操作,例如重建数据库连接或执行其他初始化操作。

下面是相关实例:

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    /**
     * @return array
     */
    public function __sleep() {
        echo "It is called when the serialize() method is called outside the class.<br>";
        $this->name = base64_encode($this->name);
        return array('name', 'age'); // It must return a value of which the elements are the name of the properties returned.
    }

    /**
     * __wakeup
     */
    public function __wakeup() {
        echo "It is called when the unserialize() method is called outside the class.<br>";
        $this->name = 2;
        $this->sex = 'Male';
        // There is no need to return an array here.
    }
}

$person = new Person('John'); // Initially assigned.
var_dump(serialize($person));
var_dump(unserialize(serialize($person)));

代码运行结果如下:

It is called when the serialize() method is called outside the class.
string(58) "O:6:"Person":2:{s:4:"name";s:8:"5bCP5piO";s:3:"age";i:25;}"
It is called when the unserialize() method is called outside the class.
object(Person)#2 (3) { ["sex"]=> string(3) "Male" ["name"]=> int(2) ["age"]=> int(25) }

11. __toString()

使用echo方法直接打印对象时,将调用__toString()方法。

注意:此方法必须返回一个字符串,否则将在E_RECOVERABLE_ERROR

소멸자 선언

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    public function __toString()
    {
        return  'go go go';
    }
}

$person = new Person('John'); // Initially assigned.
echo $person;

소멸자는 매개변수를 사용할 수 없습니다.

소멸자 사용

소멸자는 일반적으로 클래스에서 일반적이지 않습니다. 이는 클래스의 선택적 부분이며 일반적으로 클래스가 삭제되기 전에 일부 정리 작업을 완료하는 데 사용됩니다.

이것은 소멸자를 사용하는 예입니다:

go go go
출력 결과🎜
<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

}

$person = new Person('John'); // Initially assigned.
echo $person;
🎜__call()🎜🎜이 메서드는 두 개의 매개 변수를 허용합니다. 첫 번째 매개변수는 정의되지 않은 메소드 이름, 두 번째 매개변수는 메소드에 전달되는 매개변수의 배열🎜

사용

Catchable fatal error: Object of class Person could not be converted to string in D:\phpStudy\WWW\test\index.php on line 18
🎜프로그램에서 정의되지 않은 메소드를 호출할 때 __call( ) 메소드가 호출됩니다. 🎜🎜Example🎜<pre class="brush:php;toolbar:false">&lt;?php class Person { public $sex; public $name; public $age; public function __construct($name=&quot;&quot;, $age=25, $sex=&amp;#39;Male&amp;#39;) { $this-&gt;name = $name;         $this-&gt;age  = $age;         $this-&gt;sex  = $sex;     }     public function __invoke() {         echo 'This is an object';     } } $person = new Person('John'); // Initially assigned. $person();</pre>🎜결과 표시🎜<pre class="brush:php;toolbar:false">This is an object</pre>🎜4.__callStatic()🎜🎜프로그램에서 정의되지 않은 정적 메서드를 호출하면 <code>__callStatic() 메서드가 자동으로 호출됩니다. 🎜🎜__callStatic()__call()과 유사하게 사용됩니다. 예를 들면 다음과 같습니다. 🎜
Fatal error: Function name must be a string in D:\phpStudy\WWW\test\index.php on line 18
🎜실행 결과는 다음과 같습니다. 🎜
<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

}

$person = new Person('John'); // Initially assigned.
var_export($person);
🎜__get()🎜🎜외부에서 개체의 개인 속성에 액세스하려고 하면 응용 프로그램에서 예외가 발생하고 작업이 종료됩니다. __get 메서드를 사용하여 이 문제를 해결할 수 있습니다. 이 메서드는 객체 외부에서 전용 속성 값을 얻을 수 있습니다. 예시는 다음과 같습니다🎜
Person::__set_state(array( 'sex' => 'Male', 'name' => 'John', 'age' => 25, ))
🎜결과는 다음과 같습니다🎜
<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    public static function __set_state($an_array)
    {
        $a = new Person();
        $a->name = $an_array['name'];
        return $a;
    }

}

$person = new Person('John'); // Initially assigned.
$person->name = 'Jams';
var_export($person);
🎜6. __set()🎜🎜set($property,$value) 메소드는 클래스의 개인 속성을 설정하는 데 사용됩니다. 정의되지 않은 속성이 할당되면set() 메서드가 트리거되고 전달된 매개변수는 설정된 속성 이름과 값입니다. 🎜🎜다음은 데모 코드입니다.🎜
Person::__set_state(array( 'sex' => 'Male', 'name' => 'Jams', 'age' => 25, ))
🎜코드 실행 결과:🎜
$copy_of_object = clone $object;
🎜7.__isset()🎜🎜__isset() 메서드를 사용하기 전에 먼저 isset() 메서드의 사용법을 설명하겠습니다. isset() 메소드는 주로 이 변수가 설정되었는지 확인하는 데 사용됩니다. 🎜🎜isset() 메소드가 객체 외부에서 사용되는 경우 두 가지 상황이 있습니다. 🎜
  1. 매개변수가 공용 속성인 경우 isset() 메소드를 사용하여 속성 설정 여부를 확인할 수 있습니다.
  2. 매개변수가 비공개 속성인 경우 isset() 메서드는 작동하지 않습니다.
🎜그럼 사유재산의 경우 설정되어 있는지 알 수 있는 방법이 있나요? 물론 __isset() 메서드가 클래스에 정의되어 있는 한 클래스 외부에서 isset() 메서드를 사용하여 전용 속성이 설정되어 있는지 확인할 수 있습니다. 🎜🎜 정의되지 않았거나 액세스할 수 없는 속성에 대해 isset() 또는 empty()가 호출되면 __isset() 메서드가 호출됩니다. 예를 들면 다음과 같습니다. 🎜
<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    public function __clone()
    {
        echo __METHOD__."your are cloning the object.<br>";
    }

}

$person = new Person('John'); // Initially assigned.
$person2 = clone $person;

var_dump('persion1:');
var_dump($person);
echo '<br>';
var_dump('persion2:');
var_dump($person2);
🎜 코드 실행 결과는 다음과 같습니다. 🎜
Person::__clone your are cloning the object.
string(9) "persion1:" object(Person)#1 (3) { ["sex"]=> string(3) "Male" ["name"]=> string(6) "John" ["age"]=> int(25) }
string(9) "persion2:" object(Person)#2 (3) { ["sex"]=> string(3) "Male" ["name"]=> string(6) "John" ["age"]=> int(25) }
🎜8. __unset()🎜🎜은 정의되지 않은 항목에서 unset() 메서드를 호출할 때와 유사합니다. 액세스할 수 없는 속성인 경우unset() 메서드가 호출됩니다. 예는 다음과 같습니다. 🎜
/**
 * file non_autoload.php
 */

require_once('project/class/A.php');
require_once('project/class/B.php');
require_once('project/class/C.php');
.
.
.

if (ConditionA) {
    $a = new A();
    $b = new B();
    $c = new C();
    // …
} else if (ConditionB) {
    $a = newA();
    $b = new B();
    // …
}
🎜코드 실행 결과는 다음과 같습니다. 🎜
/**
 * file autoload_demo.php
 */
function  __autoload($className) {
    $filePath = “project/class/{$className}.php”;
    if (is_readable($filePath)) {
        require($filePath);
    }
}

if (ConditionA) {
    $a = new A();
    $b = new B();
    $c = new C();
    // …
} else if (ConditionB) {
    $a = newA();
    $b = new B();
    // …
}
🎜9. __sleep()🎜🎜serialize() 메서드는 클래스에 매직 메서드 __sleep()이 있는지 확인합니다. 존재하는 경우 이 메서드가 먼저 호출된 다음 직렬화 작업이 수행됩니다. 🎜🎜__sleep() 메서드는 일반적으로 데이터를 저장하기 전에 직렬화해야 하는 속성을 지정하는 데 사용됩니다. 모두 저장할 필요가 없는 매우 큰 개체가 있는 경우 이 기능이 유용할 수 있습니다. 🎜🎜자세한 내용은 다음 코드를 참고하세요. 🎜
<?php
class C {
    private $prop;

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

    /**
     * @return array
     */
    public function __debugInfo() {
        return [
            'propSquared' => $this->prop ** 2,
        ];
    }
}

var_dump(new C(42));
🎜코드 실행 결과는 다음과 같습니다. 🎜
object(C)#1 (1) { ["propSquared"]=> int(1764) }
🎜10.__wakeup()🎜🎜sleep() 메소드와 비교하면 wakeup () 메소드는 일반적으로 데이터베이스 연결 재설정 또는 기타 초기화 작업 수행과 같은 역직렬화 작업에 사용됩니다. 🎜🎜다음은 관련 예입니다.🎜rrreee🎜코드 실행 결과는 다음과 같습니다.🎜rrreee🎜11.__toString()🎜🎜echo 메서드를 사용하여 객체를 직접 인쇄하는 경우 __toString() 메서드가 호출됩니다. 🎜🎜참고: 이 메서드는 문자열을 반환해야 합니다. 그렇지 않으면 E_RECOVERABLE_ERROR 수준에서 치명적인 오류가 발생합니다. 그리고 __toString() 메서드에서도 예외를 던질 수 없습니다. 🎜🎜다음은 관련 예시입니다.🎜rrreee🎜코드를 실행한 결과는 다음과 같습니다.🎜rrreee🎜그럼, 클래스에 __toString() 메서드가 정의되어 있지 않다면 어떻게 될까요? 한번 시험해 봅시다. 🎜rrreee🎜코드를 실행한 결과는 다음과 같습니다🎜
Catchable fatal error: Object of class Person could not be converted to string in D:\phpStudy\WWW\test\index.php on line 18

显然,它在页面上报告了一个致命错误,PHP语法不支持这样的写法。

12. __invoke()

当您尝试以调用函数的方式调用对象时,__ invoke()方法将被自动调用。

注意:此功能仅在PHP 5.3.0及更高版本中有效。

下面是相关实例:

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    public function __invoke() {
        echo 'This is an object';
    }

}

$person = new Person('John'); // Initially assigned.
$person();

运行代码结果如下:

This is an object

如果坚持使用对象作为方法(但未定义__invoke()方法),则将得到以下结果:

Fatal error: Function name must be a string in D:\phpStudy\WWW\test\index.php on line 18

13.__set_state()

从PHP 5.1.0开始,在调用var_export()导出类代码时会自动调用__set_state()方法。

__set_state()方法的参数是一个包含所有属性值的数组,其格式为array('property'=> value,...)

在以下示例中,我们没有定义__set_state()方法:

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

}

$person = new Person('John'); // Initially assigned.
var_export($person);

执行代码结果如下:

Person::__set_state(array( 'sex' => 'Male', 'name' => 'John', 'age' => 25, ))

显然,对象的属性已打印。

现在让我们看看定义__set_state()方法的另一种情况:

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    public static function __set_state($an_array)
    {
        $a = new Person();
        $a->name = $an_array['name'];
        return $a;
    }

}

$person = new Person('John'); // Initially assigned.
$person->name = 'Jams';
var_export($person);

执行代码结果如下:

Person::__set_state(array( 'sex' => 'Male', 'name' => 'Jams', 'age' => 25, ))

14. __clone()

在PHP中,我们可以使用clone关键字通过以下语法克隆对象:

$copy_of_object = clone $object;

但是,使用clone关键字只是一个浅拷贝,因为所有引用的属性仍将指向原始变量。

如果在对象中定义了clone()方法,则将在复制生成的对象中调用clone()方法,该方法可用于修改属性的值(如有必要)。

下面是相关的示例:

<?php
class Person
{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",  $age=25, $sex=&#39;Male&#39;)
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    public function __clone()
    {
        echo __METHOD__."your are cloning the object.<br>";
    }

}

$person = new Person('John'); // Initially assigned.
$person2 = clone $person;

var_dump('persion1:');
var_dump($person);
echo '<br>';
var_dump('persion2:');
var_dump($person2);

运行代码结果如下:

Person::__clone your are cloning the object.
string(9) "persion1:" object(Person)#1 (3) { ["sex"]=> string(3) "Male" ["name"]=> string(6) "John" ["age"]=> int(25) }
string(9) "persion2:" object(Person)#2 (3) { ["sex"]=> string(3) "Male" ["name"]=> string(6) "John" ["age"]=> int(25) }

15.__autoload()

__autoload()方法可以尝试加载未定义的类。

过去,如果要在程序文件中创建100个对象,则必须使用include()或require()来包含100个类文件,或者必须在同一类文件中定义100个类。 例如以下:

/**
 * file non_autoload.php
 */

require_once('project/class/A.php');
require_once('project/class/B.php');
require_once('project/class/C.php');
.
.
.

if (ConditionA) {
    $a = new A();
    $b = new B();
    $c = new C();
    // …
} else if (ConditionB) {
    $a = newA();
    $b = new B();
    // …
}

那么,如果我们使用__autoload()方法呢?

/**
 * file autoload_demo.php
 */
function  __autoload($className) {
    $filePath = “project/class/{$className}.php”;
    if (is_readable($filePath)) {
        require($filePath);
    }
}

if (ConditionA) {
    $a = new A();
    $b = new B();
    $c = new C();
    // …
} else if (ConditionB) {
    $a = newA();
    $b = new B();
    // …
}

当PHP引擎第一次使用类A时,如果未找到类A,则autoload方法将被自动调用,并且类名称“ A”将作为参数传递。因此,我们在autoload()方法中需要做的是根据类名找到相应的类文件,然后将其包含在内。如果找不到该文件,则php引擎将抛出异常。

16. __debugInfo()

当执行 var_dump() 方法时,__debugInfo() 方法会被自动调用。如果 __debugInfo() 方法未被定义,那么 var_dump 方法或打印出这个对象的所有属性。

举例说明:

<?php
class C {
    private $prop;

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

    /**
     * @return array
     */
    public function __debugInfo() {
        return [
            'propSquared' => $this->prop ** 2,
        ];
    }
}

var_dump(new C(42));

执行结果:

object(C)#1 (1) { ["propSquared"]=> int(1764) }

注意:__debugInfo() 方法应该在 PHP 5.6.0 及以上版本中使用。

总结

以上就是我所了解的 PHP 魔术方法,其中常用的包括 __set() 还有 __get()__autoload()。如果你还有其他疑问,可以从 PHP 官方网站获得更多帮助。

推荐学习:《PHP视频教程

위 내용은 PHP 매직 메소드 란 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.