Vous pouvez utiliser un modèle Observer. Un moyen fonctionnel simple pour y parvenir:
<?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;
?>
Production:
This is my CRAZY application
4 + 5 = 9
4 * 5 = 20
Remarques:
Pour cet exemple de code source, vous devez déclarer tous vos plugins avant le code source réel que vous souhaitez étendre. J'ai inclus un exemple de gestion des valeurs uniques ou multiples transmises au plugin. La partie la plus difficile est d'écrire la documentation réelle qui répertorie les arguments transmis à chaque hook.
Ce n'est qu'une méthode pour réaliser un système de plugins en PHP. Il existe de meilleures alternatives, je vous suggère de consulter la documentation WordPress pour plus d'informations.
Mediator Pattern
. Les vrais observateurs sont purement des notifications, il n'y a pas de passage de message ou de notification conditionnelle (ni de gestionnaire central pour contrôler les notifications). Cela ne rend pas la réponse fausse , mais il convient de noter pour empêcher les gens d'appeler des choses par le mauvais nom ...Supposons donc que vous ne vouliez pas du modèle Observer car il nécessite que vous modifiiez vos méthodes de classe pour gérer la tâche d'écoute et que vous vouliez quelque chose de générique. Et disons que vous ne voulez pas utiliser l'
extends
héritage parce que vous héritez peut-être déjà dans votre classe d'une autre classe. Ne serait-il pas formidable d'avoir un moyen générique de rendre n'importe quelle classe enfichable sans trop d'effort ? Voici comment:Dans la partie 1, c'est ce que vous pourriez inclure avec un
require_once()
appel en haut de votre script PHP. Il charge les classes pour rendre quelque chose enfichable.Dans la partie 2, c'est là que nous chargeons une classe. Notez que je n'ai rien eu à faire de spécial pour la classe, ce qui est très différent du modèle Observer.
Dans la partie 3, c'est là que nous basculons notre classe pour qu'elle soit "enfichable" (c'est-à-dire, supporte les plugins qui nous permettent de remplacer les méthodes et les propriétés de la classe). Ainsi, par exemple, si vous avez une application Web, vous pouvez avoir un registre de plugins et vous pouvez activer les plugins ici. Remarquez également la
Dog_bark_beforeEvent()
fonction. Si je mets$mixed = 'BLOCK_EVENT'
avant la déclaration de retour, cela empêchera le chien d'aboyer et bloquerait également Dog_bark_afterEvent car il n'y aurait aucun événement.Dans la partie 4, c'est le code de fonctionnement normal, mais notez que ce que vous pourriez penser ne fonctionnerait pas du tout comme ça. Par exemple, le chien n'annonce pas son nom comme «Fido», mais «Coco». Le chien ne dit pas «miaou», mais «woof». Et quand vous voulez regarder le nom du chien par la suite, vous trouvez qu'il est «différent» au lieu de «Coco». Tous ces remplacements ont été fournis dans la partie 3.
Donc comment ça fonctionne? Eh bien, excluons
eval()
(ce que tout le monde dit être "diabolique") et excluons que ce n'est pas un modèle Observateur. Ainsi, la façon dont cela fonctionne est la classe vide sournoise appelée Pluggable, qui ne contient pas les méthodes et les propriétés utilisées par la classe Dog. Ainsi, puisque cela se produit, les méthodes magiques vont s'engager pour nous. C'est pourquoi dans les parties 3 et 4, nous gâchons avec l'objet dérivé de la classe Pluggable, pas la classe Dog elle-même. Au lieu de cela, nous laissons la classe Plugin faire le "toucher" sur l'objet Dog pour nous. (Si c'est une sorte de modèle de conception que je ne connais pas - veuillez me le faire savoir.)la source
La méthode du hook et de l' écouteur est la plus utilisée, mais vous pouvez faire d'autres choses. Selon la taille de votre application et qui vous autoriserez à voir le code (est-ce que ce sera un script FOSS, ou quelque chose en interne) influencera grandement la façon dont vous voulez autoriser les plugins.
kdeloach a un bel exemple, mais sa mise en œuvre et sa fonction de hook sont un peu dangereuses. Je vous demanderais de donner plus d'informations sur la nature de l'application php dans votre écriture, et comment vous voyez les plugins s'intégrer.
+1 à kdeloach de ma part.
la source
Voici une approche que j'ai utilisée, c'est une tentative de copier du mécanisme de signaux / slots Qt, une sorte de modèle Observer. Les objets peuvent émettre des signaux. Chaque signal a un ID dans le système - il est composé de l'identifiant de l'expéditeur + nom de l'objet Chaque signal peut être lié aux récepteurs, qui est simplement un "appelable" Vous utilisez une classe de bus pour transmettre les signaux à toute personne intéressée à les recevoir Quand quelque chose arrive, vous "envoyez" un signal. Ci-dessous et exemple d'implémentation
la source
Je crois que le moyen le plus simple serait de suivre les propres conseils de Jeff et de jeter un œil au code existant. Essayez de regarder Wordpress, Drupal, Joomla et d'autres CMS bien connus basés sur PHP pour voir à quoi ressemblent leurs hooks API. De cette façon, vous pouvez même obtenir des idées auxquelles vous n'aviez pas pensé auparavant pour rendre les choses un peu plus rubustes.
Une réponse plus directe serait d'écrire des fichiers généraux qu'ils «incluraient» une fois dans leur fichier pour fournir l'utilisabilité dont ils auraient besoin. Cela serait divisé en catégories et NON fourni dans un fichier MASSIVE "hooks.php". Attention cependant, car ce qui finit par arriver, c'est que les fichiers qu'ils contiennent finissent par avoir de plus en plus de dépendances et de fonctionnalités. Essayez de garder les dépendances de l'API faibles. IE moins de fichiers à inclure.
la source
Il y a un projet soigné appelé Stickleback par Matt Zandstra chez Yahoo qui gère une grande partie du travail de gestion des plugins en PHP.
Il applique l'interface d'une classe de plug-in, prend en charge une interface de ligne de commande et n'est pas trop difficile à mettre en place - en particulier si vous lisez l'histoire de couverture à ce sujet dans le magazine PHP architect .
la source
Un bon conseil est de voir comment d'autres projets l'ont fait. Beaucoup demandent que les plugins soient installés et que leur "nom" soit enregistré pour les services (comme wordpress le fait), vous avez donc des "points" dans votre code où vous appelez une fonction qui identifie les écouteurs enregistrés et les exécute. Un modèle de conception OO standard est le modèle Observer , qui serait une bonne option à implémenter dans un système PHP véritablement orienté objet.
Le Zend Framework utilise de nombreuses méthodes de hook et est très bien conçu. Ce serait un bon système à examiner.
la source
Je suis surpris que la plupart des réponses ici semblent être axées sur les plugins locaux à l'application Web, c'est-à-dire les plugins qui s'exécutent sur le serveur Web local.
Et si vous vouliez que les plugins s'exécutent sur un autre serveur distant? La meilleure façon de le faire serait de fournir un formulaire qui vous permet de définir différentes URL qui seraient appelées lorsque des événements particuliers se produisent dans votre application.
Différents événements enverraient des informations différentes en fonction de l'événement qui vient de se produire.
De cette façon, vous effectueriez simplement un appel cURL à l'URL qui a été fournie à votre application (par exemple via https) où les serveurs distants peuvent effectuer des tâches en fonction des informations qui ont été envoyées par votre application.
Cela offre deux avantages:
la source