Fallanalyse der dynamischen Instanziierung von Objekten durch PHP und der Übergabe von Parametern an den Konstruktor

黄舟
Freigeben: 2023-03-12 10:16:02
Original
2404 Leute haben es durchsucht

Bei der Framework-Entwicklung, der modularen Entwicklung usw. müssen wir möglicherweise Objekte dynamisch instanziieren, während PHP ausgeführt wird.

Was ist ein dynamisches Instanziierungsobjekt? Werfen wir zunächst einen Blick auf das Konzept einer Variablenfunktion (Variablenfunktion) in PHP. Zum Beispiel der folgende Code:

function foo() {
    echo 'This is the foo function';
}
$bar = 'foo';
$bar();
Nach dem Login kopieren

Beim Ausführen des obigen Codes wird „Dies ist“ ausgegeben die foo-Funktion" . Einzelheiten finden Sie im PHP-Handbuch: Variablenfunktionen. Wenn Sie dynamisch aufrufen müssen, verwenden Sie natürlich die Funktion call_user_func oder call_user_func_array. Die Verwendung dieser beiden Funktionen steht nicht im Mittelpunkt dieses Artikels. Wenn Sie dies nicht verstehen, lesen Sie bitte andere Informationen. Zurück zum Thema dieses Artikels: Was ist ein dynamisch instanziiertes Objekt? Ich glaube, dass die dynamische Instanziierung von Objekten bedeutet, dass die Objekte, die instanziiert werden müssen, während der Laufzeit des Programms dynamisch bestimmt (durch Variablen bestimmt) werden (durch Variablen bestimmt) und nicht direkt im Code fest codiert sind.

Anhand der obigen Beispiele wissen wir bereits, wie man eine Funktion zur Laufzeit dynamisch aufruft. Wenn die Objektorientierung heute so beliebt ist, müssen wir in einigen Codes eine Klasse dynamisch instanziieren zu tun?

Situation 1: Der Konstruktor der Klasse hat keine Parameter oder die Anzahl der Parameter ist bestimmt

Wenn der Konstruktor der Klasse keine Parameter oder die gewünschte Klasse hat Zum Instanziieren gibt es überhaupt keine Parameter. Ohne einen Konstruktor scheint es etwas einfacher zu sein. Sie können es gemäß dem obigen Beispiel ändern. Wer kann das nicht?

Codebeispiel. (Der Konstruktor hat keine Parameter)

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();
Nach dem Login kopieren

Führen Sie ihn aus und Sie werden die folgende Ausgabe sehen:

This is the method test of class FOO
$this->a=1, $this->b=2
Nach dem Login kopieren

Nun, wenn wir Parameter übergeben wollen, dann machen wir Folgendes:

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();
Nach dem Login kopieren

Sie können ähnliche Ergebnisse erzielen:

This is the method test of class FOO
$this->a=test, $this->b=5
Nach dem Login kopieren

Ideal.

Fall 2: KlassenkonstruktionDie Anzahl der Funktionsparameter ist ungewiss

Diese Situation wird viel problematischer sein, aber wenn Sie es universeller schreiben möchten, dann einfach Diese Situation muss berücksichtigt werden. Zum Beispiel haben wir die folgenden zwei Klassen

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;
    }
}
Nach dem Login kopieren

und wir wollen eine gemeinsame Möglichkeit, diese beiden Klassen zu instanziieren. Wir haben festgestellt, dass die FOO-Klasse keinen Konstruktor hat, oder es kann davon ausgegangen werden, dass die Anzahl der Parameter des Konstruktors der FOO-Klasse Null ist, während der Konstruktor der BAR-Klasse Parameter hat. Glücklicherweise ist PHP5 leistungsstark genug und führt das Konzept der Reflektion ein. Weitere Informationen finden Sie im PHP-Handbuch: Reflection, obwohl es im Handbuch nichts zu lesen gibt :). Glücklicherweise ist die Benennung gut geschrieben. Anhand des Klassennamens und des Methodennamens können Sie sich bereits eine ungefähre Vorstellung machen, sodass Sie nicht zu viele Wörter benötigen.

Nun, lasst uns PHP5-Reflexion verwenden, um diese Angelegenheit zu beginnen:

(Studenten, die immer noch PHP4 verwenden, gehen bitte nicht weg. Wenn Sie eine PHP-Version ohne Reflexion haben oder Liegt das daran? Aus Kompatibilitätsgründen oder weil Sie kein Upgrade durchführen möchten, möchten Sie Reflection nicht verwenden. Unten finden Sie eine Lösung.

$class = new ReflectionClass(&#39;FOO&#39;);
$foo = $class->newInstance(); //或者是$foo = $class->newInstanceArgs();
$foo->test();
Nach dem Login kopieren

Haben Sie etwas gesehen? Als nächstes:

$class = new ReflectionClass(&#39;BAR&#39;);
$bar = $class->newInstanceArgs(array(55, 65));
$bar->test();
Nach dem Login kopieren

OK, es scheint in Ordnung zu sein, also lassen Sie uns eine allgemeine Funktion entwickeln. Wir möchten sie so entwerfen. Die erste Funktion dieser Funktion ist der Name der Klasse Von Der zweite Parameter beginnt mit den Parametern des Konstruktors der zu instanziierenden Klasse. Wenn es mehrere gibt, notieren Sie sie. Um eine Funktion mit einer variablen Anzahl von Parametern zu implementieren, haben wir zwei Methoden:

Die erste ist eine Methode ähnlich wie:

function foo($arg1, $arg2 = 123, $arg3 = &#39;test&#39;, $arg4 = null, ....... ) {
    //some code;
}
Nach dem Login kopieren

Diese Methode hat zwei Nachteile: Die erste ist Wenn Sie 100 Parameter übergeben müssen, sollten Sie dann einfach 100 Parameter schreiben? Zweitens müssen Sie bestimmen, welcher Parameter im Programm null oder ein anderer Standardwert ist. (Exkurs: Der Standardwert des Parameters muss bei dieser Schreibweise am Ende stehen. Sie können einen Parameter ohne Standardwert nicht in der Mitte oder vor einem Parameter mit Standardwert einfügen. Andernfalls müssen Sie dies auch explizit tun Schreiben Sie den Parameter mit einem Standardwert, wenn Sie ihn aufrufen.)

Eine andere Möglichkeit, eine variable Anzahl von Parametern zu implementieren, ist die Verwendung der in PHP integrierten Funktion func_get_args (klicken Sie hier, um die zu lesen Handbuch), um die an die Funktion übergebenen Parameter in der Funktion zu erhalten. Ähnliche Funktionen umfassen func_get_num und func_get_arg. Vergiss es, ich bin faul. Du kannst das Handbuch finden und es selbst lesen.

Dann scheint es viel bequemer zu sein, diese Funktion zu verwenden. Basierend auf unserer vorgestellten Anordnung der Funktionsparameter sollte der Code so aussehen:

function newInstance() {
    $arguments = func_get_args();
    $className = array_shift($arguments);
    $class = new ReflectionClass($className);
    return $class->newInstanceArgs($arguments);
}
Nach dem Login kopieren
OK, nehmen wir Schauen Sie sich den Effekt an:

$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
Nach dem Login kopieren
Nur ​​vier Zeilen Code, der Effekt ist ziemlich perfekt. Wenn wir diese Idee dann auf eine Klasse anwenden, können wir sie direkt als

Magische Methode schreiben, was unsere Klasse cooler machen kann!

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
Nach dem Login kopieren

Klick, cool.

接下来讨论一下不使用反射类的情况。例如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
Nach dem Login kopieren

那么,要实现用这种方法来动态实例化对象并传参,呃……,只有曲线救国了,我们得先写一个函数,让这个函数来实例化对象,而这个函数的参数就原原本本地传给要实例化对象的类的构造函数就好了。打住!那这个函数得有几个参数啊?怎么实现传递不同个数的参数呢?嘿嘿,我一声冷笑,你忘了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);
}
Nach dem Login kopieren

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

如果改写成类里面的魔术方法,哼哼,威力嘛,你懂的!然后呢,我还是懒了,如果要写成魔术方法的话,相信这么easy的事情你很轻松就办到了。就当一个作业吧。另,本文的代码都是本人运行过的,但是,写文章的时候没有使用复制/粘贴功能,所以,你最好是也不要复制粘贴。如果从本文中的代码copy下来运行出错的话,还烦请各位自己debug一下,编程不就是要自己写么。

本来这个话题到这里就应该可以结束了,但是想到我在想到这个办法之前用的方法(好绕……),本着重在交流的态度,一起放出来。我例两个关键函数吧:extract和eval。只是我个人觉得用eval函数比较山寨,能不用最好不用。于是又想出了上面的办法,哈哈,编程最重要的是思想,不是吗?好,又是一道作业题了,大家可以试试用这两个函数(当然也会用到别的函数)来实现带不定数量的参数动态实例化对象的函数。

Das obige ist der detaillierte Inhalt vonFallanalyse der dynamischen Instanziierung von Objekten durch PHP und der Übergabe von Parametern an den Konstruktor. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
php
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!