Jadual Kandungan
本节讲解的内容
前言
对象的克隆
对象的遍历
对象的序列化和反序列化
PHP内置标准类
Traits的使用
类与对象相关函数
PHP反射机制
反射实现TP控制器调度
总结
Rumah pembangunan bahagian belakang tutorial php PHP基础教程十三之反射、对象序列化

PHP基础教程十三之反射、对象序列化

Mar 01, 2017 am 10:12 AM

本节讲解的内容

  • 对象的克隆

  • 对象的遍历

  • 对象的序列化和反序列化

  • 内置标准类的使用

  • traits的使用

  • 类和对象的相关函数

  • PHP反射机制

前言

PHP的面向对象是一个重要的知识点,它的思想贯穿着我们开发的整个流程。在面向对象中还有一些知识点是需要我们去了解的,对象克隆的特点以及对象的遍历,对象的序列化和反序列化,如果你想写一个PHP的框架,那么你对PHP的反射也是要掌握的。

对象的克隆

当我们创建一个对象后,就会在内存中分配一个空间,对象名指向这个空间,前面我们讲过对象的赋值,当一个对象把里面的数据修改了,另一个对象的数据也会跟着变化,因为赋值是相当于把对象标识符赋值了一份,而克隆并不是这样的。

<?php

class Person{
    public $name;
    public $age;
    public $sex;
    public function __construct($name,$age,$sex){
        $this -> name = $name;
        $this -> age = $age;
        $this -> sex = $sex;
    }

    public function getName(){
        return $this -> name;
    }

    public function getAge(){
        return $this -> age;
    }

    public function getSex(){
        return $this -> sex;
    }
}

$a = new Person(&#39;宋江&#39;,&#39;45&#39;,&#39;男&#39;);
echo &#39;<pre class="brush:php;toolbar:false">&#39;;

$b = clone $a;
$b -> name = &#39;武松&#39;;
var_dump($a);
var_dump($b);
Salin selepas log masuk

结果

对象克隆的语法:

$新对象 = clone $就对象;
Salin selepas log masuk

从上面的结果中可以看出来,一个对象的数据变化,并不会影响到另外一个对象的数据。对象克隆会生成一个全新的对象。可以理解如下:

在PHP的魔术方法中有一个魔术方法和PHP的克隆有关的__clone(),在复制完成时,如果在类里面定义了魔术方法__clone()方法,则新创建也就是复制生成的对象会调用这个__clone()方法,在这个方法中如果有需要可以对属性做一些变动。

如果不想一个对象进行克隆可以在内部把魔术方法__clone()方法定义成私有的,这时如果在进行克隆,会提示

Call to private Peoson::__clone() from context &#39;&#39;
Salin selepas log masuk

对象的遍历

在PHP中对象也是可以遍历的,对象的遍历可以理解成把某个对象的属性和值,遍历显示出来。遍历使用到foreach这个循环体。基本语法:

foreach(对象名 as $key => $val){
    //$key是属性名,$val是属性值
}
Salin selepas log masuk

<?php

    class Person{
    public $name;
    public $age;
    private $sex;
    public function __construct($name,$age,$sex){
        $this -> name = $name;
        $this -> age = $age;
        $this -> sex = $sex;
    }
}

$person = new Person(&#39;孙悟空&#39;,256,&#39;男&#39;);

foreach ($person as $key => $value) {
    echo $key . &#39; = &#39; . $value . &#39;<br>&#39;;
}
.......结果........
name = 孙悟空
age = 256
Salin selepas log masuk

对象的遍历只能把属性的修饰符是public的遍历出来,protected和private不能再类外访问,所以在类外进行对象的遍历,用这两个修饰符修饰的属性是取不出来的,就像上面代码的sex属性一样。

对象的序列化和反序列化

在PHP中当程序执行完一个文件,就会自动的释放内存,我们在文件中创建的对象,变量等,都会消失,如果我们在一个文件创建了一个对象,在另外一个对象中想要使用这个对象,就可以使用到对象的序列化(serialize())和反序列化(unserialize())。

对象的序列化和反序列化可以理解成把对象转换成字符串保存在一个文件中,在用到对象时把文件进行反序列化得到对象,对象是不能直接保存在文件中的。

示意图:

a.php文件,创建一个对象并保存:

<?php

    class Person{
    public $name;
    public $age;
    private $sex;
    public function __construct($name,$age,$sex){
        $this -> name = $name;
        $this -> age = $age;
        $this -> sex = $sex;
    }
}

$person = new Person(&#39;孙悟空&#39;,256,&#39;男&#39;);
//使用file_put_contents()函数把将一个字符串写入文件 
file_put_contents(&#39;D:person.txt&#39;, serialize($person));
Salin selepas log masuk

上面的代码file_put_contents()函数是把一个字符串写入到一个文件中。
上面的代码执行完可以看到在D盘有一个person.txt文件,里面是一个转换成字符串的对象。

b.php文件,使用到a.php文件中的对象person

<?php

    class Person{
        public $name;
        public $age;
        private $sex;
        public function __construct($name,$age,$sex){
            $this -> name = $name;
            $this -> age = $age;
            $this -> sex = $sex;
        }
    }
    //通过file_get_contents这个方法把一个文件读取到字符串。
    $str = file_get_contents(&#39;D:person.txt&#39;);
    //进行反序列化。
    $person = unserialize($str);
    echo &#39;<pre class="brush:php;toolbar:false">&#39;;
    var_dump($person);
    ......结果......
    object(Person)#1 (3) {
      ["name"]=>
      string(9) "孙悟空"
      ["age"]=>
      int(256)
      ["sex":"Person":private]=>
      string(3) "男"
    }
Salin selepas log masuk

在b.php中通过file_get_contents()这个方法把一个文件读取到字符串,然后通过unserialize()反序列化,但是这样反序列化得到的对象不是person对象,所以在文件中把person类的声明粘贴复制过来,自动转换成person对象。

对象的序列化和反序列化可以让多个文件共享一个对象。

PHP内置标准类

有时我们希望把一些数据,以对象的属性的方式存储,同时我们又不想定义一个类,可以考虑使用PHP内置标准类 stdClass,这是用系统提供的一个虚拟的类,并不需要我们定义就可以直接使用。

<?php

    $person = new StdClass();
    $person -> name = &#39;孙悟空&#39;;
    $person -> age = 524;
    $person -> sex = &#39;男&#39;;
    echo &#39;<pre class="brush:php;toolbar:false">&#39;;
    var_dump($person);
    ......结果......
    object(stdClass)#1 (3) {
      ["name"]=>
      string(9) "孙悟空"
      ["age"]=>
      int(524)
      ["sex"]=>
      string(3) "男"
    }
Salin selepas log masuk

在上面代码中我们可以看出来,并没有定义stdClass这个类就能使用。

Traits的使用

Traits 是一种为类似 PHP 的单继承语言而准备的代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用方法集。可以理解为在traits中定义一段代码块,可以在不同的类中使用。

图解:

traits使用语法:

trait 自定义名称{
    //额外定义的代码
}
在类中使用格式
use 自定义的名称;
Salin selepas log masuk

代码:

<?php
    //使用trait,自定义名称
    trait my_code{
        public function minus($num1,$num2){
            return $num1 - $num2;
        }
    }

    class A{
        public function plus($num1,$num2){
            return $num1 + $num2;
        }
    }

    class B extends A{
        //使用trait定义的代码块
        use my_code;
    }

    class C extends A{
        use my_code;
    }

    class D extends A{

    }

    $b = new B();
    $c = new C();
    $d = new D();
    echo $b -> plus(1,2);
    echo &#39;<br>&#39;;
    echo $b -> minus(2,1);
    echo &#39;<br>&#39;;

    echo $d -> plus(1,2);
    echo &#39;<br>&#39;;
    echo $d -> minus(2,1);
    ......结果......
    3
    1
    3
    Fatal error: Call to undefined method D::minus() in D:\mywamp\Apache24\htdocs\zendstudio\yunsuanfu\staits.php on line 36
Salin selepas log masuk

在上面代码中类D没有使用trait代码,所以在使用minus方法时,出现错误。

当我们在trait中写的函数和父类的函数一样时,以trait代码为准,即trait代码的优先级高于继承的类。

类与对象相关函数

在PHP中系统提供了一系列的函数来判断类和对象的。从帮助文档中可以看到好多函数:

在这里我们只对里面的几个函数进行了解。

<?php

    class Person{
        public $name;
        public $age;
        private $sex;
        public function __construct($name,$age,$sex){
            $this -> name = $name;
            $this -> age = $age;
            $this -> sex = $sex;
        }

        public function showInfo(){
            echo &#39;名字是:&#39; . $this -> name . &#39;,年龄是:&#39; . $this -> age . &#39;,性别是:&#39; . $this -> sex . &#39;<br>&#39;; 
        }
    }

    //判断是否创建了对象,没有创建返回true,创建返回false。
    if(class_exists(&#39;Person&#39;)){
        $person = new Person(&#39;唐僧&#39;,25,&#39;男&#39;);
        //返回对象的类名
        echo &#39;类名是: &#39; . get_class($person) . &#39;<br>&#39;;
        //判断方法是否存在。
        if(method_exists($person, &#39;showInfo&#39;)){
            $person -> showInfo();
        }else{
            echo &#39;该方法不存在&#39;;
        }
        //判断属性是否存在
        if(property_exists($person,&#39;name&#39;)){
            echo $person -> name;
        }else{
            echo &#39;属性不存在&#39;;
        }
    }else{
        echo &#39;类不存在&#39;;
    }
    ......结果......
    类名是: Person
    名字是:唐僧,年龄是:25,性别是:男
    唐僧
Salin selepas log masuk

使用类和对象函数,可以保证我们代码的完整性,对出错信息进行及时的捕获输出。

PHP反射机制

在很多编程语言中都有反射这种概念,反射简单理解就是通过类,获取里面的属性,方法,甚至注释也可以,不管属性和方法的访问修饰符是什么类型都可以获取到。

在PHP 5中具有完整的反射API,添加了对类、接口、函数、方法和扩展进行反向工程的能力。此外,反射 API 提供了方法来取出函数、类和方法中的文档注释。而我们在开发中一般是使用不到反射的,但是在某些情况下使用反射可以更好的处理问题,比如我们需要我们写框架底层,扩展功能,管理大量的未知类。

定义一个类,通过反射创建对象和调用里面的方法:

<?php

    class Dog{

        public $name;
        protected $age;
        private $food;

        public function __construct($name, $age, $food){

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

        public function cry($sound){

            echo &#39;<br> &#39; . $this->name . &#39; 叫声是.&#39; . $sound;
        }

    }

    //使用反射完成对象的创建和方法调用
    //1. 创建一个反射对象
    $reflect_obj = new ReflectionClass(&#39;Dog&#39;);

    //2. 通过反射对象创建Dog对象实例
    $dog = $reflect_obj->newInstance(&#39;大黄狗&#39;, 4, &#39;排骨&#39;);
    echo &#39;<pre class="brush:php;toolbar:false">&#39;;
    var_dump($dog);

    //3. 调用方法-使用代理方式.
    $reflect_method_cry = $reflect_obj->getMethod(&#39;cry&#39;);
    echo &#39;<pre class="brush:php;toolbar:false">&#39;;
    var_dump($reflect_method_cry);
    //4. 代理调用cry
    $reflect_method_cry->invoke($dog, &#39;汪汪&#39;);
Salin selepas log masuk

结果:


在上面代码中,我们通过new创建了一个反射的对象,在反射对象里面通过newInstance()方法得到类的对象。获取里面的方法可以使用反射对象的getMethod()方法,返回来的是一个方法对象ReflectionMethod类,通过里面的invoke()方法执行该方法。这里只是基本的介绍,可以查找帮助文档了解更多的反射对象和方法。

反射实现TP控制器调度

需求:

有一个类IndexAction,其中的方法和访问控制修饰符是不确定的,
1. 如果index 方法是public,可以执行 _before_index.
2. 如果存在_before_index 方法,并且是public的,执行该方法
3. 执行test方法
4. 再判断有没有_after_index方法,并且是public的,执行该方法
Salin selepas log masuk

代码:

<?php

    class IndexAction{
        public function index(){
            echo &#39;index<br>&#39;;
        }

        public function _before_index(){
            echo &#39;_before_index方法执行 <br>&#39;;
        }

        public function test($data){
            echo &#39;data : &#39;  . $data . &#39;<br>&#39;;
        }

        public  function _after_index(){
            echo &#39;_after_index方法执行<br>&#39;;
        }
    }

    if(class_exists(&#39;IndexAction&#39;)){
        //创建对象
        $reflectionClass = new ReflectionClass(&#39;IndexAction&#39;);
        //判断index是否存在
        if($reflectionClass -> hasMethod(&#39;index&#39;)){

            //获取index方法对象
            $reflec_index_method = $reflectionClass -> getMethod(&#39;index&#39;);
            //判断修饰符是否是public
            if($reflec_index_method -> isPublic()){
                //判断是否有_before_index方法
                if($reflectionClass -> hasMethod(&#39;_before_index&#39;)){
                    $reflec_before_method = $reflectionClass -> getMethod(&#39;_before_index&#39;);
                    //判断是否是public
                    if($reflec_before_method -> isPublic()){
                        $reflec_before_method -> invoke($reflectionClass -> newInstance());
                        //调用test()方法
                        $reflectionClass -> getMethod(&#39;test&#39;) -> invoke($reflectionClass -> newInstance(),&#39;这是test的数据&#39;);
                        //判断是否有_after_index方法
                        if($reflectionClass -> hasMethod(&#39;_after_index&#39;)){
                            $reflec_after_method = $reflectionClass -> getMethod(&#39;_after_index&#39;);
                            //判断是否是public
                            if($reflec_after_method -> isPublic()){
                                //执行_after_index方法
                                $reflec_after_method -> invoke($reflectionClass -> newInstance());

                            }else{
                                echo &#39;_after_index不是public修饰的&#39;;
                            }

                        }else{
                            echo &#39;没有_after_index方法&#39;;
                        }


                    }else{
                        echo &#39;_before_index修饰符不是public&#39;;
                    }

                }else{
                    echo &#39;没有_before_index方法&#39;;
                }


            }else{
                echo &#39;index方法不是public修饰&#39;;
            }


        }else{
            echo &#39;index方法不存在&#39;;
        }

    }else{
        echo &#39;类名不存在&#39;;
    }
    ......结果.......
    _before_index方法执行 
    data : 这是test的数据
    _after_index方法执行
Salin selepas log masuk

在上面的代码中可以看到我们不停地在判断类中有没有某个方法,是不是public修饰,然后执行,我们可以利用封装的思想,把一些共性的特征抽取出来写成一个函数。从而对我们的代码进行优化。

优化的代码:

<?php

    class IndexAction{
        public function index(){
            echo &#39;index<br>&#39;;
        }

        public function _before_index(){
            echo &#39;_before_index方法执行 <br>&#39;;
        }

        public function test($data){
            echo &#39;data : &#39;  . $data . &#39;<br>&#39;;
        }

        public  function _after_index(){
            echo &#39;_after_index方法执行<br>&#39;;
        }
    }

    if(class_exists(&#39;IndexAction&#39;)){
        $reflectionClass = new ReflectionClass(&#39;IndexAction&#39;);
        //创建IndexAction对象。
        $indexAction = $reflectionClass -> newInstance();

        execute($reflectionClass,$indexAction,&#39;index&#39;);
        execute($reflectionClass,$indexAction,&#39;_after_index&#39;);
        execute($reflectionClass,$indexAction,&#39;test&#39;,&#39;test使用的数据&#39;);
        execute($reflectionClass,$indexAction,&#39;_after_index&#39;);
    }else{
        echo &#39;没有IndexAction方法&#39;;
    }

    //封装的函数
    /**
     * [execute description]对反射的封装。
     * @param  [type]  $reflect_obj [description]反射对象
     * @param  [type]  $worker      [description]类对象
     * @param  [type]  $name        [description]方法的名字
     * @param  [type]  $canshu      [description]方法的参数
     * @return boolean              [description]
     */
    function execute($reflect_obj,$indexAction,$name,$param = &#39;&#39;){
        if($reflect_obj-> hasMethod($name)){
            $method = $reflect_obj->getMethod($name);
        if($method->isPublic()){
            $method->invoke($indexAction,$param); 
        }else{
            echo $name . &#39;不是public&#39;;
        }
        }else{
            echo $name . &#39;方法不存在&#39;;
        }
    }
    ......结果.....
    index
    _after_index方法执行
    data : test使用的数据
    _after_index方法执行
Salin selepas log masuk

可以看到进行功能的封装,可以简化我们的代码,同时代码看起来更加的清晰。

总结

PHP的面向对象的内容到这里算是讲完了,在开发中利用面向对象的思想进行开发是一定要掌握的技能。同时也要对面向对象进行深度的了解。

 以上就是PHP,反射、对象序列化的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Akan R.E.P.O. Ada Crossplay?
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Panduan Pemasangan dan Naik Taraf PHP 8.4 untuk Ubuntu dan Debian Panduan Pemasangan dan Naik Taraf PHP 8.4 untuk Ubuntu dan Debian Dec 24, 2024 pm 04:42 PM

PHP 8.4 membawa beberapa ciri baharu, peningkatan keselamatan dan peningkatan prestasi dengan jumlah penamatan dan penyingkiran ciri yang sihat. Panduan ini menerangkan cara memasang PHP 8.4 atau naik taraf kepada PHP 8.4 pada Ubuntu, Debian, atau terbitan mereka

Cara Menyediakan Kod Visual Studio (Kod VS) untuk Pembangunan PHP Cara Menyediakan Kod Visual Studio (Kod VS) untuk Pembangunan PHP Dec 20, 2024 am 11:31 AM

Kod Visual Studio, juga dikenali sebagai Kod VS, ialah editor kod sumber percuma — atau persekitaran pembangunan bersepadu (IDE) — tersedia untuk semua sistem pengendalian utama. Dengan koleksi sambungan yang besar untuk banyak bahasa pengaturcaraan, Kod VS boleh menjadi c

7 Fungsi PHP Saya Menyesal Saya Tidak Tahu Sebelum ini 7 Fungsi PHP Saya Menyesal Saya Tidak Tahu Sebelum ini Nov 13, 2024 am 09:42 AM

Jika anda seorang pembangun PHP yang berpengalaman, anda mungkin merasakan bahawa anda telah berada di sana dan telah melakukannya. Anda telah membangunkan sejumlah besar aplikasi, menyahpenyahpepijat berjuta-juta baris kod dan mengubah suai sekumpulan skrip untuk mencapai op

Bagaimana anda menghuraikan dan memproses HTML/XML dalam PHP? Bagaimana anda menghuraikan dan memproses HTML/XML dalam PHP? Feb 07, 2025 am 11:57 AM

Tutorial ini menunjukkan cara memproses dokumen XML dengan cekap menggunakan PHP. XML (bahasa markup extensible) adalah bahasa markup berasaskan teks yang serba boleh yang direka untuk pembacaan manusia dan parsing mesin. Ia biasanya digunakan untuk penyimpanan data

Jelaskan JSON Web Tokens (JWT) dan kes penggunaannya dalam PHP API. Jelaskan JSON Web Tokens (JWT) dan kes penggunaannya dalam PHP API. Apr 05, 2025 am 12:04 AM

JWT adalah standard terbuka berdasarkan JSON, yang digunakan untuk menghantar maklumat secara selamat antara pihak, terutamanya untuk pengesahan identiti dan pertukaran maklumat. 1. JWT terdiri daripada tiga bahagian: header, muatan dan tandatangan. 2. Prinsip kerja JWT termasuk tiga langkah: menjana JWT, mengesahkan JWT dan muatan parsing. 3. Apabila menggunakan JWT untuk pengesahan di PHP, JWT boleh dijana dan disahkan, dan peranan pengguna dan maklumat kebenaran boleh dimasukkan dalam penggunaan lanjutan. 4. Kesilapan umum termasuk kegagalan pengesahan tandatangan, tamat tempoh, dan muatan besar. Kemahiran penyahpepijatan termasuk menggunakan alat debugging dan pembalakan. 5. Pengoptimuman prestasi dan amalan terbaik termasuk menggunakan algoritma tandatangan yang sesuai, menetapkan tempoh kesahihan dengan munasabah,

Program PHP untuk mengira vokal dalam rentetan Program PHP untuk mengira vokal dalam rentetan Feb 07, 2025 pm 12:12 PM

Rentetan adalah urutan aksara, termasuk huruf, nombor, dan simbol. Tutorial ini akan mempelajari cara mengira bilangan vokal dalam rentetan yang diberikan dalam PHP menggunakan kaedah yang berbeza. Vokal dalam bahasa Inggeris adalah a, e, i, o, u, dan mereka boleh menjadi huruf besar atau huruf kecil. Apa itu vokal? Vokal adalah watak abjad yang mewakili sebutan tertentu. Terdapat lima vokal dalam bahasa Inggeris, termasuk huruf besar dan huruf kecil: a, e, i, o, u Contoh 1 Input: String = "TutorialSpoint" Output: 6 menjelaskan Vokal dalam rentetan "TutorialSpoint" adalah u, o, i, a, o, i. Terdapat 6 yuan sebanyak 6

Terangkan pengikatan statik lewat dalam php (statik: :). Terangkan pengikatan statik lewat dalam php (statik: :). Apr 03, 2025 am 12:04 AM

Mengikat statik (statik: :) Melaksanakan pengikatan statik lewat (LSB) dalam PHP, yang membolehkan kelas panggilan dirujuk dalam konteks statik dan bukannya menentukan kelas. 1) Proses parsing dilakukan pada masa runtime, 2) Cari kelas panggilan dalam hubungan warisan, 3) ia boleh membawa overhead prestasi.

Apakah kaedah Magic PHP (__construct, __destruct, __call, __get, __set, dll) dan menyediakan kes penggunaan? Apakah kaedah Magic PHP (__construct, __destruct, __call, __get, __set, dll) dan menyediakan kes penggunaan? Apr 03, 2025 am 12:03 AM

Apakah kaedah sihir PHP? Kaedah sihir PHP termasuk: 1. \ _ \ _ Membina, digunakan untuk memulakan objek; 2. \ _ \ _ Destruct, digunakan untuk membersihkan sumber; 3. \ _ \ _ Call, mengendalikan panggilan kaedah yang tidak wujud; 4. \ _ \ _ Mendapatkan, melaksanakan akses atribut dinamik; 5. \ _ \ _ Set, melaksanakan tetapan atribut dinamik. Kaedah ini secara automatik dipanggil dalam situasi tertentu, meningkatkan fleksibiliti dan kecekapan kod.

See all articles