加入收藏 | 设为首页 | 会员中心 | 我要投稿 莱芜站长网 (https://www.0634zz.com/)- 云连接、建站、智能边缘云、设备管理、大数据!
当前位置: 首页 > 编程开发 > PHP > 正文

php反序列化之魔术方法超详细讲解

发布时间:2023-02-16 12:38:12 所属栏目:PHP 来源:互联网
导读:序列化其实就是将数据转化成一种可逆的数据结构,自然,逆向的过程就叫做反序列化。php将数据序列化和反序列化会用到两个函数:serialize 将对象格式化成有序的字符串、unserialize 将字符串还原成原来的对象 php魔术方法 在php类保留方法中以 __两个下划线
  序列化其实就是将数据转化成一种可逆的数据结构,自然,逆向的过程就叫做反序列化。php将数据序列化和反序列化会用到两个函数:serialize 将对象格式化成有序的字符串、unserialize 将字符串还原成原来的对象
  php魔术方法
  在php类保留方法中以 “__”两个下划线开头的函数称为魔术方法,我的理解为php类设计中自定义好的函数。 
  常见的魔术方法有: 
  __construct(),类的构造函数
  __destruct(),类的析构函数
  __call(),在对象中调用一个不可访问方法时调用
  __callStatic(),用静态方式中调用一个不可访问方法时调用
  __get(),获得一个类的成员变量时调用
  __set(),设置一个类的成员变量时调用
  __isset(),当对不可访问属性调用isset()或empty()时调用
  __unset(),当对不可访问属性调用unset()时被调用
  __sleep(),执行serialize()时,先会调用这个函数
  __wakeup(),执行unserialize()时,先会调用这个函数
  __toString(),类被当成字符串时的回应方法
  __invoke(),调用函数的方式调用一个对象时的回应方法
  __set_state(),调用var_export()导出类时,此静态方法会被调用
  __clone(),当对象复制完成时调用
  __autoload(),尝试加载未定义的类
  __debugInfo(),打印所需调试信息
   __construct()与__destruct()
  __construct() 构造函数与 __destruct() 析构函数,与其他的语言如java,c#,一样,构造函数就是在对象实例化的时候先执行初始化的方法。
 
  __construct()构造函数只有在new 一个对象的时候会触发,在serialize 序列化和unserialize反序列化中都不会触发

  <?php
  class demo1{
      private $k1;
      public function __construct()
      {
          echo("构造函数被调用"."<br>");
      }
      public  function f1(){
          echo("f1 函数被调用");
      }
  }
  echo("0000"."<br>");
  $f=new demo1();
  echo("1111"."<br>");
  $a=serialize($f);
  echo("2222"."<br>");
  unserialize($a);
  ?>
  输出结果
  __destruct() 析构函数则在对象销毁和serialize 反序列化的情况下会被触发。如下
 
  <?php
  class demo1{
      private $k1;
      public function __destruct()
      {
          echo("析构函数被调用"."<br>");
      }
  }
  $f=new demo1();
  echo("0000"."<br>");
  $a=serialize($f);
  echo("1111"."<br>");
  unset($f);
  echo("2222"."<br>");
  unserialize($a);
  ?>
  输出结果 
  __call
  __call 魔术方法的作用是当前对象调用一个不存在的方法时,就会被触发
  <?php
  class demo1{
      private $k1;
      public  function f1(){
          echo("f1 函数被调用");
      }
        //当调用不存在的方法时,方法名作为参数传到$name 变量,方法名的输入参数传到arguments参数列表中
      public function __call($name, $arguments)
      {
          // TODO: Implement __call() method.
          echo($name."---".$arguments[0]);
      }
  }
  $f=new demo1();
  $f->f2("123");//调用不存在的方法f2()
  ?>
  输出结果
  __get
  __get() 魔术方法是当访问一个对象不存在的变量时就会被触发
  <?php
  class demo1{
      private $k1;
      public  function f1(){
          echo("f1 函数被调用");
      }
      public function __get($name)//不存在的变量k会以参数传到$name
      {
          echo($name);
      }
  }
  $f=new demo1();
  $f->k;//不存在的变量k
  ?>
  输出结果
   __set
  __set() 魔术方法是当给一个对象不存在的变量赋值时就会被触发

  <?php
  header("Content-Type:text/html;charset=utf-8");
  highlight_file(__FILE__);
  class demo1{
      private $k1;
      public  function f1(){
          echo("f1 函数被调用");
      }
      public function __set($name, $value)
      {
          echo($name."---".$value);
      }
  }
  $f=new demo1();
  $f->k=123; //给不存在的成员变量赋值
  ?>
  输出结果

  __isset
  当对不可访问属性调用isset()或empty()时会触发,例如访问类的私有属性,类不存在的成员属性

  <?php
  header("Content-Type:text/html;charset=utf-8");
  highlight_file(__FILE__);
  class demo1{
      private $k1;
      public  function f1(){
          echo("f1 函数被调用");
      }
      public function __isset($name)
      {
         echo($name);
      }
  }
  $f=new demo1();
  $f2=unserialize(serialize($f));//反序列化
  isset($f2->k1);//使用isset方法判断私有成员属性k1
  empty($f2->k1);//使用empty方法判断私有成员属性k1
  ?>
  输出结果 
  __unset
  当尝试使用unset() 销毁函数去销毁一个不可访问的成员属性时会触发,不可访问(包括私有成员属性,不存在的成员属性)
 <?php
  header("Content-Type:text/html;charset=utf-8");
  highlight_file(__FILE__);
  class demo1{
      private $k1;
      public  function f1(){
          echo("f1 函数被调用");
      }
      public function __unset($name)
      {
          echo($name);
      }
  }
  $f=new demo1();
  $f2=unserialize(serialize($f));//反序列化
  unset($f2->k1);//使用unset销毁私有成员属性k1
  unset($f2->faaa);//使用unset销毁不存在的成员属性faaa
  ?>
  输出结果
  __sleep
  当对象被serialize 序列化时触发调用__sleep

  <?php
  header("Content-Type:text/html;charset=utf-8");
  highlight_file(__FILE__);
  class demo1{
      private $k1;
      public  function f1(){
          echo("f1 函数被调用");
      }
      public function __sleep()
      {
          echo("在被序列化时被调用");
      }
  }
  $f=new demo1();
  echo("00000"."</br>");

(编辑:莱芜站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读