魔术方法

魔术方法

总结

  1. __construct(),类的构造函数
  2. __destruct(),类的析构函数
  3. __call(),在对象中调用一个不可访问方法时调用
  4. __callStatic(),用静态方式中调用一个不可访问方法时调用
  5. __get(),获得一个类的成员变量时调用
  6. __set(),设置一个类的成员变量时调用
  7. __isset(),当对不可访问属性调用isset()或empty()时调用
  8. __unset(),当对不可访问属性调用unset()时被调用。
  9. __sleep(),执行serialize()时,先会调用这个函数
  10. __wakeup(),执行unserialize()时,先会调用这个函数
  11. __toString(),类被当成字符串时的回应方法
  12. __invoke(),用调用函数的方式去调用一个对象时的回应方法
  13. __set_state(),调用var_export()导出类时,此静态方法会被调用。
  14. __clone(),当对象复制完成时调用
  15. __autoload(),尝试加载未定义的类
  16. __debugInfo(),打印所需调试信息

1.__construct()

作用:用来执行一些有用的初始化任务,如对成员属性在创建对象时赋予初始值

格式

function __construct([参数列表]){
    方法体//通常用来对成员属性进行初始化赋值
}

创建对象 不带参数

$Person1 = new Person();
echo $Person1->say(); //输出:我叫:,性别:男,年龄:22

创建对象带一个参数

$Person2 = new Person("李华");
echo $Person2->say(); //输出:我叫:李华,性别:男,年龄:22

创建对象带三个参数

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

    //声明一个构造方法且带参数

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

    //say方法

    public function say(){
        echo "我叫:". $this->name . ",性别:" . $this->sex . ",年龄:" . $this->age;

    }
}
$Person1 = new Person("李华");
echo $Person1->say();

输出结果

我叫:李四,性别:男,年龄:25

2.__destruct()

作用:用来完成一些在对象销毁前的清理任务

格式

function __destruct(){
//方法体
}

注:不能带有任何参数

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

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

    public function say(){
        echo "我叫:" . $this->name . ",性别:" . $this->sex . ",年龄:" . $this->age;
    }

    //声明一个构造方法

    public function __destruct(){
        echo "我觉得我还可以再抢救一下,我的名字叫".$this->name;
    }
}
$Person = new Person("小美");
unset($Person);//销毁上面创建的对象$Person

输出结果

我觉得我还可以再抢救一下,我的名字叫小明

3.__call()

在对象中调用一个不可访问方法时调用

作用:为了避免当调用的方法不存在时产生错误,而意外的导致程序中止,可以使用 __call() 方法来避免。

该方法在调用的方法不存在时会自动调用,程序仍会继续执行下去。

用法:该方法有两个参数,第一个参数 $function_name 会自动接收不存在的方法名,第二个 $arguments 则以数组的方式接收不存在方法的多个参数

格式

function __call(string $function_name, array $arguments)
{
    // 方法体
}
<?php
class Person{
    function say(){
        echo "Hello world!";
    }
    //声明此方法用来处理调用对象中不存在的方法

    function __call($funName,$arguments){
        echo "你所调用的函数:".$funName . "(参数:";//输出调用不存在的方法名
        print_r($arguments);// 输出调用不存在的方法时的参数列表
        echo ")不存在!\n";// 结束换行
    }
}
$Person =new Person();
$Person->run("teacher");// 调用对象中不存在的方法,则自动调用了对象中的__call()方法
$Person->eat("小美","草莓");
$Person->say();

输出结果

你所调用的函数:run(参数:Array ( [0] => teacher ) )不存在!

你所调用的函数:eat(参数:Array ( [0] => 小明 [1] => 苹果 ) )不存在!

Hello, world!

4.__callStatic()

用静态方式中调用一个不可访问方法时调用

此方法与上面所说的 call() 功能除了 callStatic() 是未静态方法准备的之外,其它都是一样的。

<?php
class Person{
    function say(){
        echo "Hello world!";
    }
    public static function __callStatic($funName, $arguments)
    {
        echo "你所调用的静态方法:".$funName."(参数:";
        print_r($arguments);
        echo ")不存在!\n";
    }
}
$Person=new Person();
$Person::run("teacher");
$Person::eat("小明", "苹果");
$Person->say();

输出结果

你所调用的静态方法:run(参数:Array ( [0] => teacher ) )不存在!
你所调用的静态方法:eat(参数:Array ( [0] => 小明 [1] => 苹果 ) )不存在!
Hello, world!

5.__get()

获得一个类的成员变量时调用,解决private“不能访问某个私有属性”时调用

<?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("小美",61);
echo "姓名:".$Person->name;
echo "年龄:".$Person->age;

输出结果

姓名:小美年龄:51

6.__set()

__set( $property, $value )` 方法用来设置私有属性, 给一个未定义的属性赋值时,此方法会被触发,传递的参数是被设置的属性名和值

<?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 "我叫" . $this->name . ",今年" . $this->age . "岁了";
    }
}
$Person=new Person("小美",17);
$Person->name="小红";
$Person->age=15;
$Person->age=163;
$Person->say();

输出结果

我叫小红,今年15岁了

7.__isset()

当对不可访问的属性调用isset()或empty()时调用

isset)_函数是测定变量是否设定的函数,传入一个变量作为参数,如果传入的变脸存在就返回true,否则返回false

在一个对象外面使用isset()函数去测定对象里面的陈鸿源是否被设定分两种情况:

(1)对象里面成员是公有的->(√)

(2)私有属性成员->(X) 若是在类里面加上__isset()函数就可以了

即:当在类的外部使用isset()函数来测定对象里面的私有成员是否被设定时,就会自动调用类里面的__isset()函数

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

    public function __construct($name="",$age=18,$sex='男')
    {
        $this->name = $name;
        $this->age = $age;
        $this->sex = $sex;
    }
    public function __isset($content){
        echo "当在类外部使用isset()函数测定私有成员{$content}时,自动调用";
        echo isset($this->$content);
    }
}
$Person =new Person("小美",18);
echo isset($Person->sex);
echo isset($Person->name);
echo isset($Perosn->age);

输出结果

1当在类外部使用isset()函数测定私有成员name时,自动调用1

8.__unset()

unset()函数是删除指定的变量且回传true,参数为要删除的变量

(1)如果一个对象里面的成员属性是公有的,可以使用这个函数在对象外面删除对象的公有属性

(2) 如果对象的成员属性是私有的,这个函数就没有权限去删除

即 在对象里面加上unset函数 就可以在对象外面删除对象里面的私有成员属性,对象会自动调用unset()函数来删除对象内部的私有成员属性

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

    public function __construct($name="",$age=18,$sex='男')
    {
        $this->name = $name;
        $this->$age = $age;
        $this->sex = $sex;
    }
    public function __unset($content)
    {
        echo "当在类的外部使用unset()函数来删除私有成员时自动调用";
        echo isset($this->content);
    }
}
$Person =new Person("小美",18);
unset($Person->sex);
unset($Person->name);
unset($Person->age);

输出结果

当在类的外部使用unset()函数来删除私有成员时自动调用当在类的外部使用unset()函数来删除私有成员时自动调用

9.__sleep()

serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,则该方法会优先被调用,然后才执行序列化操作

此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组

如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误

__sleep()不能返回父类的私有成员的名字。这样做会产生一个 E_NOTICE 级别的错误。可以用 Serializable 接口来替代.
__sleep() 方法常用于提交未提交的数据,或类似的清理操作。同时,如果有一些很大的对象,但不需要全部保存,这个功能就很好用。
<?php
class Person{
    public $sex;
    public $name;
    public $age;

    public function __construct($name="",$age="",$sex='男'){
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }
    public function __sleep()
    {
        echo "当在类的外部使用serialize()时会调用这里的__sleep()方法";
        $this->name = base64_encode($this->name);
        return array('name','age');
    }
}
$Person = new Person('小美');
echo serialize($Person);

输出结果

当在类的外部使用serialize()时会调用这里的__sleep()方法O:6:"Person":2:{s:4:"name";s:8:"5bCP576O";s:3:"age";s:0:"";}

10.__wakeup()

unserialize()会检查是覅否存在一个wakeup()方法,如果存在则会优先调用wakeup方法,预先准备对象需要的资源。

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

    public function __construct($name="",$age=18,$sex='男'){
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }
    public function __sleep()
    {
        echo "当在类的外部使用serialize()时,会调用这里的__sleep()方法";
        $this->name = base64_encode($this->name);
        return array('name','age');
    }
    
    public function __wakeup(){
        echo "当前类外部使用unserialize()时会调用这里的__wakeup()方法";
        $this->name=2;
        $this->sex='男';
    }
}
$Person = new Person('小美');
var_dump(serialize($Person));
var_dump(unserialize(serialize($Person)));

输出结果

当在类的外部使用serialize()时,会调用这里的__sleep()方法string(58) "O:6:"Person":2:{s:4:"name";s:8:"5bCP576O";s:3:"age";i:18;}"
当在类的外部使用serialize()时,会调用这里的__sleep()方法当前类外部使用unserialize()时会调用这里的__wakeup()方法object(Person)#2 (3) {
  ["sex"]=>
  string(3) "男"
  ["name"]=>
  int(2)
  ["age"]=>
  int(18)
}

11.__toString()

一个类被当成字符串时的回应方法(次啊方法必须返回一个字符串否则报错)

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

    public function __construct($name = "", $age = 18, $sex = '男')
    {
        $this->name = $name;
        $this->age = $age;
        $this->sex = $sex;
    }
    public function __toString()
    {
        return 'go go go';
    }
}
$Person = new Person('小美');
echo $Person;

输出结果

go go go

12.__invoke()

当尝试调用函数的方式调用一个对象时,__invoke()方法会被自动调用

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

    public function __construct($name = "", $age = 18, $sex = '男')
    {
        $this->name = $name;
        $this->age = $age;
        $this->sex = $sex;
    }

    public function __invoke(){
        echo '这是一个对象';
    }
}
$Person = new Person('小美');
$Person();

输出:这是一个对象

若还执意调用 则会报错

13.__set_state()

作用:当调用var_export()导出类时,此方法被调用

参数:本方法的唯一参数时数组,其中包含array(’property‘ = >value,..)格式排列的类

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

    public function __construct($name = "", $age = 18, $sex = '男')
    {
        $this->name = $name;
        $this->age = $age;
        $this->sex = $sex;
    }

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

输出结果

object(Person)#1 (3) {
  ["sex"]=>
  string(3) "男"
  ["name"]=>
  string(6) "小米"
  ["age"]=>
  int(18)
}

14.__clone()

当对象复制完成时调用

对象复制可以通过 clone 关键字来完成(如果可能,这将调用对象的 clone() 方法)。对象中的 clone() 方法不能被直接调用。

语法:

$copy_of_object = clone $object;

当复制完成时,如果定义了 clone() 方法,则新创建的对象(复制生成的对象)中的 clone() 方法会被调用,可用于修改属性的值

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

    public function __construct($name = "", $age = 18, $sex = '男')
    {
        $this->name = $name;
        $this->age = $age;
        $this->sex = $sex;
    }

    public function __clone(){
       echo __METHOD__."你正在克隆对象";
    }
}
$Person = new Person('小美');
$Person2 = clone $Person;
var_dump('Persion1:');
var_dump($Person);

输出结果

Person::__clone你正在克隆对象string(9) "Persion1:"
object(Person)#1 (3) {
  ["sex"]=>
  string(3) "男"
  ["name"]=>
  string(6) "小美"
  ["age"]=>
  int(18)
}                                          //克隆成功

15.__sutoload()

尝试加载未定义的类

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

    public function __construct($name = "", $age = 18, $sex = '男')
    {
        $this->name = $name;
        $this->age = $age;
        $this->sex = $sex;
    }

    public function __autolaod( $className){
        $filePAth = "project/calss/{$className}.php";
        if (is_readable($filePAth)){
            require($filePAth);
        }
    }
}
if (条件A){
    $a = new A();
    $b = new B();
    $c = new C();
}else if (条件B){
    $a =newA();
    $b = new B();
}

第一次使用 类A,但是找不到时,会自动调用autoload方法,并将类名A作为参数传入,所以需要在autoload()中根据类名找到相应的文件,并包含进来。如果方法也找不到就会报错

16.__debugInfo

打印所需调试的信息

<?php
class C{
    private $prop;

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

    public function __debugInfo()
    {
        return [
            'propSquared' =>$this->prop **2,
        ];
    }
}
var_dump(new C(42));

输出结果

object(C)#1 (1) {
  ["propSquared"]=>
  int(1764)
}
posted @   Yolololololo  阅读(32)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示