In PHP-Klassen Eventhandler verwenden wie in Delphi
Diese Anleitung richtet sich an Programmierer welche sich sowohl in Borland Delphi als auch in PHP auskennen. Ich erläutere in einem einfachen Beispiel die Verwendung von Eventhandlern (Ereignissen) in PHP-Klassen.
Hallo zusammen!
Als langjähriger Delphi-Programmierer habe ich in PHP immer eines sehr vermisst: Den Komfort von Eventhandlern (auch bekannt als Ereignisse). Die Delphi-Dokumentation definiert Ereignisse einfach als Methodenzeiger welche wiederum als Eigenschaftsvariablen einer Klasse angegeben werden. Zwar kennt PHP Callback-Funktionen doch ist deren Handhabung mit call_user_func innerhalb einer Klasse umständlich, der Zugriff auf Funktionen außerhalb der Klassendeklaration IMHO unmöglich.
PHP kennt im Gegensatz zu Delphi keine Methodenzeiger. Man kann sich aber eine andere nützliche Eigenschaft des PHP-Interpreters zu Nutze machen. PHP behandelt Funktionsnamen wie Strings und kann Stringvariablen als Funktionsaufrufe nutzen.
Da es für diesen speziellen Anwendungsfall natürlich keinen Objektinspektor wie in Delphi gibt ähnelt die weitere Vorgehensweise stark der Entwicklung von visuellen Komponenten in Delphi sowie deren Test durch Erzeugung zur Laufzeit.
Ich habe dazu folgenden Beispielcode entwickelt. Er orientiert sich stark an den Delphi-Konventionen:
Einige Erläuterungen zum Quelltext:
Zeile 7: Hier wird eine Klassen-Membervariable OnStart als public deklariert. Diese nimmt später den Namen der Eventhandler-Routine als String auf.
Zeile 10: Hier wird eine Klassenmethode als public deklariert. Darin können z.B. Schleifen durchlaufen werden wobei innerhalb der Schleife z.B. der Eventhandler mit dem aktuellen Schleifenzählerstand aufgerufen wird.
Zeile 14: Hier wird der Inhalt der Klassen-Membervariable OnStart in eine lokale Variable der Klassenmethode kopiert. Funktionsaufrufe aus Stringvariablen heraus funktionieren nur mit lokalen Variablen.
Zeile 18: Mittels function_exists wird überprüft, ob der angegebene Funktionsname als Funktion exisitiert und im Codebaum erreichbar ist. Dies kann man entfernt mit dem Aufruf von if Assigned(OnStart) in Delphi vergleichen.
Zeile 19: Hier wird nun der Eventhandler aufgerufen. Ich habe hier beispielhaft nur eine numerische Konstante als Parameter mitgegeben. Dies kann natürlich jede Art von Variable sein.
Zeile 26: Hier wird eine einfache Funktion als Eventhandler deklariert. Ihre Parameterliste muss natürlich mit der kompatibel sein welche innerhalb der Klasse beim Eventhandler-Aufruf verwendet wird.
Zeile 27: Der Inhalt des Eventhandler-Parameters wird beispielhaft per echo ausgegeben.
Zeile 34: Der Membervariablen OnStart unserer Klasse wird nun der Name unserer Eventhandler-Funktion übergeben. Um mich der Delphi-Syntax etwas anzunähern habe ich mir die Eigenart von PHP zunutze gemacht, nicht in einfache oder doppelte Anführungszeichen gesetzte Zeichenfolgen als String zu behandeln. Allerdings erzeugt dies einen PHP-Hinweis dass dies keine definierte Konstante ist - mir ging es um Ähnlichkeit zur Delphi-Syntax. Besser man schreibt oder
Zeile 37: Schließlich und endlich wird nun die Klassenmethode Start() aufgerufen welche unser Konstrukt in Gang setzt.
Jetzt könnte man das Ganze noch ein wenig auf die Spitze treiben in dem man dem Eventhandler ein Handle auf die Klasseninstanz mitgibt. Dies entpricht dann den in Delphi bekannten Sender-Variablen. Dadurch kann man mehreren Klasseninstanzen den selben Eventhandler zuweisen. Die einzelnen Klasseninstanzen lassen sich anschließend innerhalb des Eventhandlers über die Sender-Variable identifizieren. Hier ein entsprechend modifiziertes Codebeispiel:
Ich hoffe, mein kleines PHP-Delphi-Crossover findet ein paar Anwender. Schließlich sind beide Programmiersprachen sehr komfortabel. Warum sollen sie dann nicht voneinander profitieren.
Grüssle
Cody
Hallo zusammen!
Als langjähriger Delphi-Programmierer habe ich in PHP immer eines sehr vermisst: Den Komfort von Eventhandlern (auch bekannt als Ereignisse). Die Delphi-Dokumentation definiert Ereignisse einfach als Methodenzeiger welche wiederum als Eigenschaftsvariablen einer Klasse angegeben werden. Zwar kennt PHP Callback-Funktionen doch ist deren Handhabung mit call_user_func innerhalb einer Klasse umständlich, der Zugriff auf Funktionen außerhalb der Klassendeklaration IMHO unmöglich.
PHP kennt im Gegensatz zu Delphi keine Methodenzeiger. Man kann sich aber eine andere nützliche Eigenschaft des PHP-Interpreters zu Nutze machen. PHP behandelt Funktionsnamen wie Strings und kann Stringvariablen als Funktionsaufrufe nutzen.
Da es für diesen speziellen Anwendungsfall natürlich keinen Objektinspektor wie in Delphi gibt ähnelt die weitere Vorgehensweise stark der Entwicklung von visuellen Komponenten in Delphi sowie deren Test durch Erzeugung zur Laufzeit.
Ich habe dazu folgenden Beispielcode entwickelt. Er orientiert sich stark an den Delphi-Konventionen:
<?php
/* Eine neue Klasse deklarieren */
class TObject {
/* Sichtbare Klassenvariable welche den Eventhandler aufnimmt */
public $OnStart;
/* Eine neue Klassenmethode deklarieren */
public function Start() {
/* Die Klassenvariable mit dem Eventhandler in eine lokale Variable
kopieren */
$func = $this->OnStart;
/* Den Eventhandler aufrufen und ihm einen Parameter übergeben
(beispielsweise einen Fortschrittszähler) */
if(function_exists($func)) {
$func(1234);
}
}
}
/* Die Funktion des Eventhandlers definieren */
function ObjectStart($number) {
echo $number;
}
/* Oben deklarierte Klasse instantiieren */
$obj = new TObject;
/* Eventhandler der Klasseninstanz zuweisen */
$obj->OnStart = ObjectStart;
/* Klassenmethode aufrufen welche ihrerseits den Eventhandler aufruft */
$obj->Start();
?>
Zeile 7: Hier wird eine Klassen-Membervariable OnStart als public deklariert. Diese nimmt später den Namen der Eventhandler-Routine als String auf.
Zeile 10: Hier wird eine Klassenmethode als public deklariert. Darin können z.B. Schleifen durchlaufen werden wobei innerhalb der Schleife z.B. der Eventhandler mit dem aktuellen Schleifenzählerstand aufgerufen wird.
Zeile 14: Hier wird der Inhalt der Klassen-Membervariable OnStart in eine lokale Variable der Klassenmethode kopiert. Funktionsaufrufe aus Stringvariablen heraus funktionieren nur mit lokalen Variablen.
Zeile 18: Mittels function_exists wird überprüft, ob der angegebene Funktionsname als Funktion exisitiert und im Codebaum erreichbar ist. Dies kann man entfernt mit dem Aufruf von if Assigned(OnStart) in Delphi vergleichen.
Zeile 19: Hier wird nun der Eventhandler aufgerufen. Ich habe hier beispielhaft nur eine numerische Konstante als Parameter mitgegeben. Dies kann natürlich jede Art von Variable sein.
Zeile 26: Hier wird eine einfache Funktion als Eventhandler deklariert. Ihre Parameterliste muss natürlich mit der kompatibel sein welche innerhalb der Klasse beim Eventhandler-Aufruf verwendet wird.
Zeile 27: Der Inhalt des Eventhandler-Parameters wird beispielhaft per echo ausgegeben.
Zeile 34: Der Membervariablen OnStart unserer Klasse wird nun der Name unserer Eventhandler-Funktion übergeben. Um mich der Delphi-Syntax etwas anzunähern habe ich mir die Eigenart von PHP zunutze gemacht, nicht in einfache oder doppelte Anführungszeichen gesetzte Zeichenfolgen als String zu behandeln. Allerdings erzeugt dies einen PHP-Hinweis dass dies keine definierte Konstante ist - mir ging es um Ähnlichkeit zur Delphi-Syntax. Besser man schreibt
$obj->OnStart = 'ObjectStart';
$obj->OnStart = "ObjectStart"';
Zeile 37: Schließlich und endlich wird nun die Klassenmethode Start() aufgerufen welche unser Konstrukt in Gang setzt.
Jetzt könnte man das Ganze noch ein wenig auf die Spitze treiben in dem man dem Eventhandler ein Handle auf die Klasseninstanz mitgibt. Dies entpricht dann den in Delphi bekannten Sender-Variablen. Dadurch kann man mehreren Klasseninstanzen den selben Eventhandler zuweisen. Die einzelnen Klasseninstanzen lassen sich anschließend innerhalb des Eventhandlers über die Sender-Variable identifizieren. Hier ein entsprechend modifiziertes Codebeispiel:
<?php
class TObject {
public $Name;
public $OnStart;
public function __construct() {
$this->Name = 'Object1';
}
public function Start() {
$func = $this->OnStart;
if(function_exists($func)) {
/* Den Eventhandler mit einem Handle auf die aktuelle Klasseninstanz
und einem Zählparameter aufrufen */
$func($this, 1234);
}
}
}
function ObjectStart($sender, $number) {
echo $number;
echo '<br />';
/* Hier wird über das Handle der Klasseninstanz auf eine Membervariable
zugegriffen. Genausogut könnte man auf Klassenmethoden zugreifen */
echo $sender->Name;
}
$obj = new TObject;
$obj->OnStart = ObjectStart;
$obj->Start();
?>
Grüssle
Cody
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 146483
Url: https://administrator.de/tutorial/in-php-klassen-eventhandler-verwenden-wie-in-delphi-146483.html
Ausgedruckt am: 26.12.2024 um 11:12 Uhr
2 Kommentare
Neuester Kommentar
PHP behandelt Funktionsnamen wie Strings und kann Stringvariablen als Funktionsaufrufe nutzen.
Und das kommt davon wenn man PHP programmiert ohne mal die Fehleranzeige einzuschalten...
<?php
error_reporting(E_ALL|E_STRICT);
ini_set('display_erros','On');
function keks() {
echo "Hallo";
}
$call = keks;
$call();
?>
PHP Notice: Use of undefined constant keks - assumed 'keks' in /private/var/folders/rk/rkpxTSHLGeKxWDx3wCuQbk+++TI/-Tmp-/untitled_1b9..php on line 10
PHP Stack trace:
PHP 1. {main}() /private/var/folders/rk/rkpxTSHLGeKxWDx3wCuQbk+++TI/-Tmp-/untitled_1b9..php:0
Hallo
PHP Stack trace:
PHP 1. {main}() /private/var/folders/rk/rkpxTSHLGeKxWDx3wCuQbk+++TI/-Tmp-/untitled_1b9..php:0
Hallo
Wenn schon, dann gib bitte auch einen String an und nicht eine Konstante!
Das ist eine Unart, die manche PHP-Programmier-Anfänger entwickeln und dafür sollten Sie gleich im Hinterhof an die Wand gestellt werden...
Zudem kann 5.3 Closures, weshalb man dann ohnehin folgendes schreibt:
<?php
$call = function() {
echo "Hallo";
};
$call();
?>