0

0

php魔术方法是什么

青灯夜游

青灯夜游

发布时间:2023-01-04 18:32:17

|

4477人浏览过

|

来源于php中文网

原创

PHP中以双下划线“__”开始命名的内置方法被称作魔术方法,包括“__construct()”、“__set()”、“__get()”、“__isset()”、“__unset()”、“__sleep()”、“__wakeup()”、“__call()”、“__invoke()”等;其中“__construct()”是类的构造方法,是对象创建完成后第一个被对象自动调用的方法。

php魔术方法是什么

本教程操作环境:windows7系统、PHP8版、DELL G3电脑

php中的魔术方法

在PHP中,以双下划线(__)开始命名的方法被称作PHP中的魔术方法,它们在PHP中充当很重要的角色。魔术方法包括:

方法名 描述
__construct() 类的构造函数
__destruct() 类的析构函数
__call($funName, $arguments) 当调用一个未定义或不可达方法时, __call() 方法将被调用。
__callStatic($funName, $arguments) 当调用一个未定义或不可达的静态方法时, __callStatic() 方法将被调用。
__get($propertyName) 当获取一个类的成员变量时, __get() 方法将被调用。
__set($property, $value) 当赋值一个类的成员变量时, __set() 方法将被调用。
__isset($content)  当调用 isset() 或 empty() 对一个未定义或不可达的成员赋值时, __isset() 方法将被调用。
__unset($content) 当调用 reset() 对一个未定义或不可达的成员更新时, __unset() 方法将被调用。
__sleep() 当执行序列化 serialize() 时,__sleep() 方法将首先被调用。
__wakeup() 当执行反序列化 deserialization() 时, __wakeup() 方法将首先被调用。
__toString() 当使用 echo 方法直接输出显示对象时,__toString() 方法首先被调用。
__invoke() 使用调用函数(function)访问一个对象时, __invoke() 方法将首先被调用。
__set_state($an_array) 当调用 var_export() 方法时,__set_state() 方法将被调用。
__clone() 当对象被复制赋值时,__clone() 方法将被调用。
__autoload($className) 试图载入一个未定义的类时调用。
__debugInfo() 输出 debug 信息。

本文将使用一些实例展示 PHP 魔术方法的运用。

立即学习PHP免费学习笔记(深入)”;

1.__construct()

当创建对象时,PHP 类的构造方法是第一个被调用的方法。每个类都有构造方法。若你没在类中明确声明定义它,将会有一个默认的无参类构造方法存在,虽然它不会在类中定义出现。

1) 构造方法的运用

类的构造方法通常用于执行一些初始化任务,诸如当创建对象时,为成员初始化赋值。

2) 类中构造方法的声明格式

function __constrct([parameter list]){

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

}

注意: 在多数类中仅可以声明一个构造方法。因为, PHP 不支持构造方法重载。

下面是个完整的例子:

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

使用一个参数 "Jams" 调用创建 $Person2 对象。

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

使用3个参数调用创建 $Person3 对象。

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

__destruct()

析构函数与构造函数相反。

析构函数允许你在销毁对象之前执行一些操作,例如关闭文件,清空结果集等等。

析构函数是 PHP 5 引入的新功能。

析构函数的声明与构造函数类似,以两个下划线开头,名称固定为 __destruct()

析构函数的声明

function __destruct()
{
    //method body
}

析构函数不能带参数。

析构函数的使用

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

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

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() 方法将被调用。

示例

";
    }     

    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!!
\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() 。下面举个例子:

";
    }

    public static function __callStatic($funName, $arguments)
    {
        echo "The static method you called:" . $funName . "(parameter:" ;  // 打印出未定义的方法名。
        print_r($arguments); // 打印出未定义方法的参数列表。
        echo ")does not exist!
\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 方法解决该问题。该方法可以获取从对象外部获取私有属性的值。举例如下

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 . "
"; // 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 . "
"; // 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()方法,并且传递的参数是设置的属性名称和值。

下面是演示代码:

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()方法。下面是一个例子:

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.
"; echo isset($this->$content); } } $person = new Person("John", 25); // Initially assigned. echo isset($person->sex),"
"; echo isset($person->name),"
"; echo isset($person->age),"
";

代码运行结果如下:

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()方法。下面是一个例子:

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.
"; echo isset($this->$content); } } $person = new Person("John", 25); // Initially assigned. unset($person->sex),"
"; unset($person->name),"
"; unset($person->age),"
";

代码的运行结果如下:

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()。如果存在,将首先调用该方法,然后执行序列化操作。

随缘网络php企业网站管理系统2.0
随缘网络php企业网站管理系统2.0

随缘网络PHP企业网站管理系统V2.0正式发布,该企业网站管理系统采用PHP+MYSQL编写,界面色调风格延续之前1.0版管理系统简洁浅蓝色风格,稍有所变动。变更分类树形目录方式采用jquery库,产品,文章三级无限分类。希望大家能够喜欢。系统中难免有些小问题,希望大家在使用中有什么问题可到本站论坛提出,我们将总结各问题后给予修正并升级。本站再次声明对于免费版系列系统本站不提供QQ电话等技术咨询服

下载

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

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

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.
"; $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 '
';

代码运行结果如下:

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()方法通常用于反序列化操作,例如重建数据库连接或执行其他初始化操作。

下面是相关实例:

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.
"; $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.
"; $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级别上引发致命错误。而且您也不能在__toString()方法中抛出异常。

下面是相关的实例:

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

那么,如果在类中未定义__toString()方法怎么办?让我们尝试一下。

name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

}

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

运行代码结果如下:

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及更高版本中有效。

下面是相关实例:

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()方法:

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()方法的另一种情况:

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()方法,该方法可用于修改属性的值(如有必要)。

下面是相关的示例:

name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }

    public function __clone()
    {
        echo __METHOD__."your are cloning the object.
"; } } $person = new Person('John'); // Initially assigned. $person2 = clone $person; var_dump('persion1:'); var_dump($person); echo '
'; 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 方法或打印出这个对象的所有属性。

举例说明:

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速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

1930

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1263

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1169

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

948

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1400

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1229

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1439

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1303

2023.11.13

桌面文件位置介绍
桌面文件位置介绍

本专题整合了桌面文件相关教程,阅读专题下面的文章了解更多内容。

0

2025.12.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 8.1万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 6.9万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号