Rumah pembangunan bahagian belakang tutorial php php框架中的动态实例化对象详解

php框架中的动态实例化对象详解

Jun 26, 2017 pm 02:09 PM
php dinamik Contoh objek bingkai

在框架开发,模块化开发等场合,我们可能有一种需求,那就是在PHP运行时动态实例化对象。

什么是动态实例化对象呢?我们先来看一下PHP有一种变量函数(可变函数)的概念,例如如下代码:

function foo() {
    echo 'This is the foo function';
}
$bar = 'foo';
$bar();
Salin selepas log masuk

运行上述代码将会输出“This is the foo function”。具体请参考PHP手册:可变函数。当然,如果需要动态调用的话,那么就使用call_user_func或call_user_func_array函数。这两个函数的用法不是本文的重点,不懂的同学请查阅其它资料。回到本文的话题上:什么是动态实例化对象?本人认为动态实例化对象,即是:需要实例化的对象是在程序运行时(run-time)动态决定(由变量决定)需要实例化什么样的对象,而不是直接写死在代码里。

通过上述例子我们已经知道了如何在运行时动态调用一个函数了,在现在面向对向如此流行的今天,在一些代码中,我们需要去动态去实例化一个类,该怎么做呢?

情况一:类的构造函数没有参数或参数的个数是确定的

如果类的构造函数没有参数或者我们要实例化的类根本没有构造函数,似乎简单一点,可以照上面的例子改一个嘛,嗯,照葫芦画瓢,谁不会:

代码示例:(构造函数没有参数)

class FOO {
    private $a, $b;
    public function construct() {
        $this->a = 1;
        $this->b = 2;
    }
    public function test() {
        echo &#39;This is the method test of class FOO<br />&#39;;
        echo &#39;$this->a=&#39;, $this->a, &#39;, $this->b=&#39;, $this->b;
    }
}
$bar = &#39;FOO&#39;;
$foo = new $bar();
$foo->test();
Salin selepas log masuk

运行一下,就看到了输出了如下结果:

This is the method test of class FOO
$this->a=1, $this->b=2
Salin selepas log masuk

嗯,我们要传参的话,那么就这样吧:

class FOO {
    private $a, $b;
    public function construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }
    public function test() {
        echo &#39;This is the method test of class FOO<br />&#39;;
        echo &#39;$this->a=&#39;, $this->a, &#39;, $this->b=&#39;, $this->b;
    }
}
$bar = &#39;FOO&#39;;
$foo = new $bar(&#39;test&#39;, 5);
$foo->test();
Salin selepas log masuk

一样可以得到类似的结果:

This is the method test of class FOO
$this->a=test, $this->b=5
Salin selepas log masuk

很理想嘛。

情况二:类的构造函数的参数个数不确定

这种情况就要麻烦很多了,但是如果要写得比较通用的话,就不得不考虑这种情况了。例如,我们有如下两个类

class FOO {
    public function test() {
        echo &#39;This is the method test of class FOO&#39;;
    }
}
class BAR {
    private $a, $b;
    public function construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }
    public function test() {
        echo &#39;This is the method test of class BAR<br />&#39;;
        echo &#39;$this->a=&#39;, $this->a, &#39;, $this->b=&#39;, $this->b;
    }
}
Salin selepas log masuk

我们想要一个通用的方式来实例化这两个类。我们注意到FOO类是没有写构造函数的,或者是可以认为FOO类的构造函数的参数个数为零;而BAR类的构造函数却有参数。还好,PHP5已经足够强大了,引入了反射的概念,具体请参考PHP手册:反射,虽然手册上也没有什么可参考的:)。还好,命名写得不错,从类名和方法名上面已经可以看出大概的端倪,不需要太多的文字。

那么好吧,就让我们用PHP5的反射来着手这个事情:

(还在用PHP4的同学请不要走开,如果你拥有一个没有反射的PHP版本或者是你为了兼容也好还是不想升级也好,反正不想用反射的,下面有解决方案)

$class = new ReflectionClass(&#39;FOO&#39;);
$foo = $class->newInstance(); //或者是$foo = $class->newInstanceArgs();
$foo->test();
Salin selepas log masuk

看到什么了没有?接着来:

$class = new ReflectionClass(&#39;BAR&#39;);
$bar = $class->newInstanceArgs(array(55, 65));
$bar->test();
Salin selepas log masuk

OK,似乎可以了,那么就整理一下吧,来个通用函数,我们想这么设计,此函数的第一个函数是要实例化的类名,从第二个参数开始就是要实例化类的构造函数的参数,有几个就写几个上去,没有就不写。要想实现参数个数可变的函数,我们有两种方法:

第一种是类似于:

function foo($arg1, $arg2 = 123, $arg3 = &#39;test&#39;, $arg4 = null, ....... ) {
    //some code;
}
Salin selepas log masuk

的办法,这种方法有两个缺点,第一个是你如果需要传100个参数难道就写100个参数吗?第二个是你还要在程序里判断哪个参数是不是null,或是其它默认值。(题外话:这种写法的参数默认值必须放在最后,你不能将没有默认值的参数插在有默认值的中间或前面,否则你调用的时候也必须显式地写上有默认值参数的值)

另一种实现参数数量可变的方法是在函数里用PHP的内置函数func_get_args(猛击这里看手册)取得传给函数的参数。类似的函数有func_get_num和func_get_arg,算了,我懒,你们自己找手册看吧。

那么,用这个函数似乎要方便很多,我们根据想象的函数参数的排列,代码应该是这个样子的:

function newInstance() {
    $arguments = func_get_args();
    $className = array_shift($arguments);
    $class = new ReflectionClass($className);
    return $class->newInstanceArgs($arguments);
}
Salin selepas log masuk

OK,让我们来看一下效果:

$foo = newInstance(&#39;FOO&#39;);
$foo->test();
//输出结果:
//This is the method test of class FOO
$bar = newInstance(&#39;BAR&#39;, 3, 5);
$bar->test();
//输出结果:
//This is the method test of class BAR
//$this->a=3, $this->b=5
Salin selepas log masuk

短短四行代码,效果相当完美啊。那么,如果应用到类里面,我们可以利用这种思想,直接写成魔术方法,可以让我们的类更酷哦!

class INSTANCE {
    function call($className, $arguments) {
        $class = new ReflectionClass($className);
        return $class->newInstanceArgs($arguments);
    }
}
$inst = new INSTANCE();
$foo = $inst->foo();
$foo->test();
//输出结果:
//This is the method test of class FOO
$bar = $inst->bar(&#39;arg1&#39;, &#39;arg2&#39;);
$bar->test();
//输出结果:
//This is the method test of class BAR
//$this->a=3, $this->b=5
Salin selepas log masuk

咔咔,爽吧。

接下来讨论一下不使用反射类的情况。例如PHP4中就没有反射,而一些老项目就是运行在PHP4上面的。或者是要保证项目对未知环境的兼容性,Whatever,来关心一下怎么动态传参吧。PHP中动态传参的函数只有一个:call_user_func_array(轻击此处查看手册)。这是一个动态调用函数的函数,作用是可以将函数的参数以数组的形式传递给要调用的函数。好吧,我自己也被自己绕晕了,直接来看实例:

function foo($a, $b) {
    echo &#39;$a=&#39;, $a, &#39;<br />&#39;;
    echo &#39;$b=&#39;, $b;
}
call_user_func_array(&#39;foo&#39;, array(1, &#39;string&#39;));
//本例输出结果:
//$a=1
//$b=string
Salin selepas log masuk

那么,要实现用这种方法来动态实例化对象并传参,呃……,只有曲线救国了,我们得先写一个函数,让这个函数来实例化对象,而这个函数的参数就原原本本地传给要实例化对象的类的构造函数就好了。打住!那这个函数得有几个参数啊?怎么实现传递不同个数的参数呢?嘿嘿,我一声冷笑,你忘了PHP里提供一个创建匿名函数的函数吗?(又开始绕起来了……)create_function(手册在此),照着手册里面的例子直接画就可以了,我也懒得打字了,直接看下面的代码,注释我写清楚点大家都明白了:

function newInst() {
    //取得所有参数
    $arguments = func_get_args();
    //弹出第一个参数,这是类名,剩下的都是要传给实例化类的构造函数的参数了
    $className = array_shift($arguments);
    //给所有的参数键值加个前缀
    $keys = array_keys($arguments);
    array_walk($keys, create_function(&#39;&$value, $key, $prefix&#39;, &#39;$value = $prefix . $value;&#39;), &#39;$arg_&#39;);
    //动态构造实例化类的函数,主要是动态构造参数的个数
    $paramStr = implode(&#39;, &#39;,$keys);
    $newClass=create_function($paramStr, "return new {$className}({$paramStr});");
    //实例化对象并返回
    return call_user_func_array($newClass, $arguments);
}
Salin selepas log masuk

好了,至于效果是什么,就麻烦各位看官自己动动手,运行一下看看,是不是自己期望的结果。

Atas ialah kandungan terperinci php框架中的动态实例化对象详解. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

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)
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Arahan sembang dan cara menggunakannya
4 minggu 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