Können Sie eine Funktion wie diese deklarieren ...
function ihatefooexamples(){
return "boo-foo!";
};
Und dann etwas wie folgt neu deklarieren ...
if ($_GET['foolevel'] == 10){
function ihatefooexamples(){
return "really boo-foo";
};
};
Ist es möglich, eine Funktion auf diese Weise zu überschreiben?
Wie auch immer?
php
function
redeclaration
Mark Lalor
quelle
quelle
Antworten:
Bearbeiten
Es gibt eine Funktion namens override_function , die tatsächlich zur Rechnung passt. Da diese Funktion jedoch Teil der Advanced PHP Debugger- Erweiterung ist, ist es schwierig, ein Argument zu liefern,
override_function()
das für die Verwendung in der Produktion vorgesehen ist. Daher würde ich "Nein" sagen, es ist nicht möglich, eine Funktion mit der Absicht zu überschreiben, die der ursprüngliche Fragesteller im Sinn hatte.Ursprüngliche Antwort
Hier sollten Sie OOP nutzen, insbesondere Polymorphismus.
interface Fooable { public function ihatefooexamples(); } class Foo implements Fooable { public function ihatefooexamples() { return "boo-foo!"; } } class FooBar implements Fooable { public function ihatefooexamples() { return "really boo-foo"; } } $foo = new Foo(); if (10 == $_GET['foolevel']) { $foo = new FooBar(); } echo $foo->ihatefooexamples();
quelle
$foo = new Foo()
in einenelse
Block zu setzen, falls entweder der Konstruktor (a) teuer ist oder (b) Nebenwirkungen hat.Affen-Patch im Namespace php> = 5.3
Eine weniger ausweichende Methode als das Ändern des Interpreters ist das Affenfeld.
Das Patchen von Affen ist die Kunst, die eigentliche Implementierung durch ein ähnliches "Patch" zu ersetzen.
Ninja-Fähigkeiten
Bevor Sie wie ein PHP-Ninja Affen-Patches erstellen können, müssen Sie zunächst die PHP-Namespaces verstehen.
Seit PHP 5.3 haben wir Namespaces kennengelernt, die Sie auf den ersten Blick als äquivalent zu Java-Paketen bezeichnen könnten, aber es ist nicht ganz dasselbe. Namespaces in PHP sind eine Möglichkeit, den Bereich zu kapseln, indem eine Fokushierarchie erstellt wird, insbesondere für Funktionen und Konstanten. Wie dieses Thema, Rückgriff auf globale Funktionen , zu erklären versucht.
Wenn Sie beim Aufrufen einer Funktion keinen Namespace angeben , sucht PHP zuerst im aktuellen Namespace und bewegt sich dann in der Hierarchie nach unten, bis die erste in diesem vorangestellten Namespace deklarierte Funktion gefunden und ausgeführt wird. Wenn Sie in unserem Beispiel
print_r();
vonnamespace My\Awesome\Namespace;
PHP aus aufrufen , suchen Sie zuerst nach einer aufgerufenen FunktionMy\Awesome\Namespace\print_r();
undMy\Awesome\print_r();
dann,My\print_r();
bis die in PHP integrierte Funktion im globalen Namespace gefunden wird\print_r();
.Sie können a
function print_r($object) {}
im globalen Namespace nicht definieren, da dies zu einer Namenskollision führt, da bereits eine Funktion mit diesem Namen vorhanden ist.Erwarten Sie einen schwerwiegenden Fehler wie:
Fatal error: Cannot redeclare print_r()
Nichts hindert Sie jedoch daran, genau das im Rahmen eines Namespace zu tun.
Den Affen flicken
Angenommen, Sie haben ein Skript mit mehreren
print_r();
Aufrufen.Beispiel:
<?php print_r($some_object); // do some stuff print_r($another_object); // do some other stuff print_r($data_object); // do more stuff print_r($debug_object);
Aber Sie ändern später Ihre Meinung und möchten, dass die Ausgabe
<pre></pre>
stattdessen in Tags eingeschlossen wird. Ist dir schon mal was passiert?Bevor Sie loslegen und jeden Anruf ändern, sollten Sie
print_r();
stattdessen das Patchen von Affen in Betracht ziehen.Beispiel:
<?php namespace MyNamespace { function print_r($object) { echo "<pre>", \print_r($object, true), "</pre>"; } print_r($some_object); // do some stuff print_r($another_object); // do some other stuff print_r($data_object); // do more stuff print_r($debug_object); }
Ihr Skript wird jetzt
MyNamespace\print_r();
anstelle des globalen Skripts verwendet\print_r();
Funktioniert hervorragend zum Verspotten von Unit-Tests.
nJoy!
quelle
namespace SeparateInclude {}
Dann können Sie in der Hauptdatei wieder einen Namespacenamespace MainFile {}
erstellen und die neue Datei zum Erstellen eines Affen-Patchesfunction B()
erneut in die aufrufende Hauptdatei aufnehmen\SeparateInclude\B();
. Wenn SieB();
jetzt\MainFile\B();
die Hauptdatei aufrufen, wird aufgerufen, welche Aufrufe\SeparateInclude\B();
erfolgreich\B();
aus der großen / ursprünglichen Include-Datei vermieden werden.Schauen Sie sich an
override_function
, um die Funktionen zu überschreiben.Beispiel:
override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');
quelle
Die kurze Antwort lautet "Nein". Sie können eine Funktion nicht mehr überschreiben, wenn sie sich im PHP-Funktionsumfang befindet.
Sie können anonyme Funktionen wie diese am besten nutzen
$ihatefooexamples = function() { return "boo-foo!"; } //... unset($ihatefooexamples); $ihatefooexamples = function() { return "really boo-foo"; }
http://php.net/manual/en/functions.anonymous.php
quelle
unset
? Ich weiß, dass es nicht schlecht ist, nur neugierig (ich habe diesen speziellen Fall nicht ausprobiert) ...unset
Sie können keine Funktionen in PHP neu deklarieren. Sie können sie jedoch überschreiben. Überprüfen Sie die überschreibenden Funktionen sowie die Umbenennungsfunktionen , um die Funktion zu speichern, die Sie überschreiben, wenn Sie möchten.
Denken Sie also daran, dass Sie eine Funktion verlieren, wenn Sie sie überschreiben. Vielleicht möchten Sie es behalten, aber unter einem anderen Namen. Ich sage nur.
Wenn es sich um Funktionen in Klassen handelt, die Sie überschreiben möchten, müssen Sie lediglich eine Unterklasse erstellen und die Funktion in Ihrer Klasse neu deklarieren, ohne rename_function und override_function ausführen zu müssen.
Beispiel:
rename_function('mysql_connect', 'original_mysql_connect' ); override_function('mysql_connect', '$a,$b', 'echo "DOING MY FUNCTION INSTEAD"; return $a * $b;');
quelle
Ich würde alle Funktionen eines Falls in eine
include
Datei und die anderen in eine andere aufnehmeninclude
.Zum Beispiel
simple.inc
würde enthaltenfunction boofoo() { simple }
undreally.inc
würde enthaltenfunction boofoo() { really }
Es hilft bei der Lesbarkeit / Wartung Ihres Programms, da alle Funktionen der gleichen Art in der gleichen sind
inc
.Dann oben in Ihrem Hauptmodul
if ($_GET['foolevel'] == 10) { include "really.inc"; } else { include "simple.inc"; }
quelle
$iam = "really"
oder$iam = "simple"
oben in die Include-Dateien einfügen.Sie können die PECL-Erweiterung verwenden
runkit_function_redefine
- Ersetzen Sie eine Funktionsdefinition durch eine neue ImplementierungAber das ist meiner Meinung nach eine schlechte Praxis. Sie verwenden Funktionen, sehen sich jedoch das Designmuster des Dekorateurs an . Kann die Grundidee daraus ausleihen.
quelle
Nein, das wird ein Problem sein. PHP-Variablenfunktionen
quelle
Eine Lösung für den verwandten Fall, in dem Sie eine Include-Datei A haben, die Sie bearbeiten können und einige ihrer Funktionen in einer Include-Datei B (oder der Hauptdatei) überschreiben möchten:
Hauptdatei:
<?php $Override=true; // An argument used in A.php include ("A.php"); include ("B.php"); F1(); ?>
Datei A einschließen:
<?php if (!@$Override) { function F1 () {echo "This is F1() in A";} } ?>
Datei B einschließen:
<?php function F1 () {echo "This is F1() in B";} ?>
Wenn Sie zur Hauptdatei blättern, wird " Dies ist F1 () in B " angezeigt .
quelle
Abhängig von der Situation, in der Sie dies benötigen, können Sie möglicherweise anonyme Funktionen wie die folgenden verwenden:
$greet = function($name) { echo('Hello ' . $name); }; $greet('World');
... dann können Sie jederzeit eine neue Funktion für die angegebene Variable einstellen
quelle