Sie können ein Observer-Muster verwenden. Ein einfacher funktionaler Weg, um dies zu erreichen:
<?php
/** Plugin system **/
$listeners = array();
/* Create an entry point for plugins */
function hook() {
global $listeners;
$num_args = func_num_args();
$args = func_get_args();
if($num_args < 2)
trigger_error("Insufficient arguments", E_USER_ERROR);
// Hook name should always be first argument
$hook_name = array_shift($args);
if(!isset($listeners[$hook_name]))
return; // No plugins have registered this hook
foreach($listeners[$hook_name] as $func) {
$args = $func($args);
}
return $args;
}
/* Attach a function to a hook */
function add_listener($hook, $function_name) {
global $listeners;
$listeners[$hook][] = $function_name;
}
/////////////////////////
/** Sample Plugin **/
add_listener('a_b', 'my_plugin_func1');
add_listener('str', 'my_plugin_func2');
function my_plugin_func1($args) {
return array(4, 5);
}
function my_plugin_func2($args) {
return str_replace('sample', 'CRAZY', $args[0]);
}
/////////////////////////
/** Sample Application **/
$a = 1;
$b = 2;
list($a, $b) = hook('a_b', $a, $b);
$str = "This is my sample application\n";
$str .= "$a + $b = ".($a+$b)."\n";
$str .= "$a * $b = ".($a*$b)."\n";
$str = hook('str', $str);
echo $str;
?>
Ausgabe:
This is my CRAZY application
4 + 5 = 9
4 * 5 = 20
Anmerkungen:
Für diesen Beispielquellcode müssen Sie alle Plugins vor dem eigentlichen Quellcode deklarieren, der erweiterbar sein soll. Ich habe ein Beispiel beigefügt, wie einzelne oder mehrere Werte behandelt werden, die an das Plugin übergeben werden. Der schwierigste Teil davon ist das Schreiben der eigentlichen Dokumentation, in der aufgeführt ist, welche Argumente an jeden Hook übergeben werden.
Dies ist nur eine Methode, um ein Plugin-System in PHP zu erstellen. Es gibt bessere Alternativen. Ich empfehle Ihnen, die WordPress-Dokumentation zu lesen, um weitere Informationen zu erhalten.
Mediator Pattern
. Echte Beobachter sind reine Benachrichtigungen, es gibt keine Nachrichtenübermittlung oder bedingte Benachrichtigung (noch gibt es einen zentralen Manager für die Steuerung von Benachrichtigungen). Es macht die Antwort nicht falsch , aber es sollte beachtet werden, um Leute davon abzuhalten, Dinge mit dem falschen Namen zu nennen ...Nehmen wir also an, Sie möchten das Observer-Muster nicht, da Sie Ihre Klassenmethoden ändern müssen, um die Aufgabe des Abhörens zu bewältigen, und etwas Allgemeines wünschen. Angenommen, Sie möchten keine
extends
Vererbung verwenden, da Sie möglicherweise bereits in Ihrer Klasse von einer anderen Klasse erben. Wäre es nicht großartig, eine generische Möglichkeit zu haben, eine Klasse ohne großen Aufwand steckbar zu machen ? Hier ist wie:In Teil 1 können Sie dies mit einem
require_once()
Aufruf oben in Ihrem PHP-Skript einschließen . Es lädt die Klassen, um etwas steckbar zu machen.In Teil 2 laden wir dort eine Klasse. Hinweis: Ich musste nichts Besonderes für die Klasse tun, was sich erheblich vom Observer-Muster unterscheidet.
In Teil 3 schalten wir unsere Klasse in "steckbar" um (dh unterstützt Plugins, mit denen wir Klassenmethoden und -eigenschaften überschreiben können). Wenn Sie beispielsweise eine Web-App haben, verfügen Sie möglicherweise über eine Plugin-Registrierung und können hier Plugins aktivieren. Beachten Sie auch die
Dog_bark_beforeEvent()
Funktion. Wenn ich$mixed = 'BLOCK_EVENT'
vor der return-Anweisung setze , blockiert dies das Bellen des Hundes und blockiert auch das Dog_bark_afterEvent, da es kein Ereignis geben würde.In Teil 4 ist dies der normale Betriebscode. Beachten Sie jedoch, dass das, was Sie vielleicht für möglich halten, überhaupt nicht so ausgeführt wird. Zum Beispiel gibt der Hund seinen Namen nicht als "Fido" bekannt, sondern als "Coco". Der Hund sagt nicht "Miau", sondern "Woof". Und wenn Sie sich später den Namen des Hundes ansehen möchten, stellen Sie fest, dass er "anders" anstelle von "Coco" ist. Alle diese Überschreibungen wurden in Teil 3 bereitgestellt.
Wie funktioniert das? Nun, lassen Sie uns ausschließen
eval()
(was jeder als "böse" bezeichnet) und ausschließen, dass es sich nicht um ein Beobachtermuster handelt. Die Art und Weise, wie es funktioniert, ist die hinterhältige leere Klasse namens Pluggable, die nicht die von der Dog-Klasse verwendeten Methoden und Eigenschaften enthält. Da dies geschieht, werden sich die magischen Methoden für uns engagieren. Deshalb spielen wir in Teil 3 und 4 mit dem Objekt, das von der Pluggable-Klasse abgeleitet ist, und nicht mit der Dog-Klasse selbst. Stattdessen lassen wir die Plugin-Klasse das Dog-Objekt für uns "berühren". (Wenn das eine Art Designmuster ist, von dem ich nichts weiß - lassen Sie es mich bitte wissen.)quelle
Die Hook- und Listener- Methode wird am häufigsten verwendet, aber Sie können auch andere Dinge tun. Abhängig von der Größe Ihrer App und davon, wem Sie das Anzeigen des Codes erlauben (wird dies ein FOSS-Skript oder etwas im Haus sein), wird dies einen großen Einfluss darauf haben, wie Sie Plugins zulassen möchten.
kdeloach hat ein schönes Beispiel, aber seine Implementierung und Hook-Funktion ist etwas unsicher. Ich würde Sie bitten, mehr Informationen über die Art der PHP-App zu geben, die Sie schreiben, und darüber, wie Plugins passen.
+1 bis kdeloach von mir.
quelle
Hier ist ein Ansatz, den ich verwendet habe: Es ist ein Versuch, aus dem Qt-Signal- / Slot-Mechanismus eine Art Beobachtermuster zu kopieren. Objekte können Signale aussenden. Jedes Signal hat eine ID im System - es besteht aus der ID des Absenders + dem Objektnamen. Jedes Signal kann an die Empfänger gebunden werden, was einfach "aufrufbar" ist. Sie verwenden eine Busklasse, um die Signale an alle weiterzuleiten, die daran interessiert sind, sie zu empfangen, wenn etwas passiert, "senden" Sie ein Signal. Unten finden Sie eine Beispielimplementierung
quelle
Ich glaube, der einfachste Weg wäre, Jeffs eigenen Ratschlägen zu folgen und sich den vorhandenen Code anzusehen. Schauen Sie sich Wordpress, Drupal, Joomla und andere bekannte PHP-basierte CMS an, um zu sehen, wie ihre API-Hooks aussehen und sich anfühlen. Auf diese Weise können Sie sogar Ideen erhalten, an die Sie vorher vielleicht noch nicht gedacht haben, um die Dinge ein wenig rubustiger zu machen.
Eine direktere Antwort wäre, allgemeine Dateien zu schreiben, die sie "include_once" in ihre Datei aufnehmen würden, um die Benutzerfreundlichkeit zu bieten, die sie benötigen würden. Dies würde in Kategorien unterteilt und NICHT in einer MASSIVEN "hooks.php" -Datei bereitgestellt. Seien Sie jedoch vorsichtig, denn was am Ende passiert, ist, dass Dateien, die sie enthalten, immer mehr Abhängigkeiten und Funktionen aufweisen. Versuchen Sie, die API-Abhängigkeiten gering zu halten. IE weniger Dateien für sie enthalten.
quelle
Es gibt ein nettes Projekt namens Stickleback von Matt Zandstra bei Yahoo, das einen Großteil der Arbeit für den Umgang mit Plugins in PHP erledigt.
Es erzwingt die Schnittstelle einer Plugin-Klasse, unterstützt eine Befehlszeilenschnittstelle und ist nicht allzu schwer in Betrieb zu nehmen - insbesondere, wenn Sie die Titelgeschichte im PHP Architect Magazine lesen .
quelle
Ein guter Rat ist, zu sehen, wie andere Projekte dies getan haben. Viele fordern die Installation von Plugins und deren Registrierung für Dienste (wie bei WordPress), sodass Sie in Ihrem Code "Punkte" haben, an denen Sie eine Funktion aufrufen, die registrierte Listener identifiziert und ausführt. Ein Standard-OO-Designmuster ist das Observer Pattern , das eine gute Option für die Implementierung in einem wirklich objektorientierten PHP-System darstellt.
Das Zend Framework verwendet viele Hook-Methoden und ist sehr gut aufgebaut. Das wäre ein gutes System.
quelle
Ich bin überrascht, dass die meisten Antworten hier auf Plugins ausgerichtet zu sein scheinen, die lokal für die Webanwendung sind, dh Plugins, die auf dem lokalen Webserver ausgeführt werden.
Was ist, wenn Sie möchten, dass die Plugins auf einem anderen Remote-Server ausgeführt werden? Der beste Weg, dies zu tun, besteht darin, ein Formular bereitzustellen, mit dem Sie verschiedene URLs definieren können, die aufgerufen werden, wenn bestimmte Ereignisse in Ihrer Anwendung auftreten.
Unterschiedliche Ereignisse senden unterschiedliche Informationen basierend auf dem gerade aufgetretenen Ereignis.
Auf diese Weise führen Sie einfach einen cURL-Aufruf an die URL durch, die Ihrer Anwendung bereitgestellt wurde (z. B. über https), wo Remoteserver Aufgaben basierend auf Informationen ausführen können, die von Ihrer Anwendung gesendet wurden.
Dies bietet zwei Vorteile:
quelle