Estou iniciando um novo aplicativo Web em PHP e desta vez quero criar algo que as pessoas possam estender usando uma interface de plug-in.
Como alguém escreve 'hooks' em seu código para que plugins possam se conectar a eventos específicos?
fonte
Estou iniciando um novo aplicativo Web em PHP e desta vez quero criar algo que as pessoas possam estender usando uma interface de plug-in.
Como alguém escreve 'hooks' em seu código para que plugins possam se conectar a eventos específicos?
Você pode usar um padrão Observer. Uma maneira funcional simples de fazer isso:
<?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;
?>
Resultado:
This is my CRAZY application
4 + 5 = 9
4 * 5 = 20
Notas:
Para este exemplo de código-fonte, você deve declarar todos os seus plug-ins antes do código-fonte real que deseja que seja extensível. Incluí um exemplo de como lidar com valores únicos ou múltiplos sendo passados para o plug-in. A parte mais difícil disso é escrever a documentação real, que lista quais argumentos são passados para cada gancho.
Este é apenas um método de realizar um sistema de plugins no PHP. Existem alternativas melhores, sugiro que você verifique a documentação do WordPress para obter mais informações.
Mediator Pattern
. Os verdadeiros observadores são puramente notificações, não há passagem de mensagens ou notificação condicional (nem um gerente central para controlar as notificações). Não faz a resposta errada , mas deve-se observar a parada pessoas chamando as coisas pelo nome errado ...Então, digamos que você não queira o padrão Observer, pois exige que você altere seus métodos de classe para lidar com a tarefa de escutar e queira algo genérico. E digamos que você não queira usar
extends
herança, porque você já pode estar herdando sua classe de alguma outra classe. Não seria ótimo ter uma maneira genérica de tornar qualquer classe conectável sem muito esforço ? Aqui está como:Na Parte 1, é isso que você pode incluir com uma
require_once()
chamada na parte superior do seu script PHP. Carrega as classes para tornar algo plugável.Na parte 2, é aí que carregamos uma classe. Observe que não precisei fazer nada de especial na classe, o que é significativamente diferente do padrão Observador.
Na Parte 3, é aí que mudamos nossa classe para "plugável" (ou seja, suporta plugins que nos permitem substituir métodos e propriedades de classe). Portanto, por exemplo, se você possui um aplicativo da web, pode ter um registro de plug-in e ativar plug-ins aqui. Observe também a
Dog_bark_beforeEvent()
função. Se eu definir$mixed = 'BLOCK_EVENT'
antes da declaração de retorno, ele impedirá o cão de latir e também bloqueará o Dog_bark_afterEvent porque não haveria nenhum evento.Na Parte 4, esse é o código de operação normal, mas observe que o que você poderia pensar que seria executado não é assim. Por exemplo, o cão não anuncia seu nome como 'Fido', mas 'Coco'. O cão não diz 'miau', mas 'Woof'. E quando você quiser olhar o nome do cachorro depois, descobrirá que é 'Diferente' em vez de 'Coco'. Todas essas substituições foram fornecidas na Parte 3.
Então, como isso funciona? Bem, vamos descartar
eval()
(que todo mundo diz que é "mau") e descartar que não é um padrão de Observador. Portanto, a maneira como funciona é a classe vazia sorrateira chamada Pluggable, que não contém os métodos e propriedades usados pela classe Dog. Assim, desde que isso ocorra, os métodos mágicos se envolverão para nós. É por isso que nas partes 3 e 4 mexemos no objeto derivado da classe Pluggable, não na classe Dog. Em vez disso, deixamos a classe Plugin fazer o "toque" no objeto Dog para nós. (Se esse é um tipo de padrão de design que eu não conheço - entre em contato.)fonte
O método hook e listener é o mais usado, mas há outras coisas que você pode fazer. Dependendo do tamanho do seu aplicativo e de quem você permitirá que veja o código (este será um script FOSS ou algo interno) influenciará bastante a maneira como você deseja permitir plug-ins.
O kdeloach tem um bom exemplo, mas sua implementação e função de gancho são um pouco inseguras. Eu pediria que você desse mais informações sobre a natureza do aplicativo php e como você vê os plugins adequados.
+1 para kdeloach de mim.
fonte
Aqui está uma abordagem que eu usei, é uma tentativa de copiar do mecanismo de sinais / slots Qt, um tipo de padrão Observer. Objetos podem emitir sinais. Todo sinal tem um ID no sistema - é composto pelo id do remetente + nome do objeto. Todo sinal pode ser ligado aos receptores, o que é simplesmente "callable". Você usa uma classe de barramento para transmitir os sinais a qualquer pessoa interessada em recebê-los. acontece, você "envia" um sinal. Abaixo está um exemplo de implementação
fonte
Acredito que a maneira mais fácil seria seguir os conselhos de Jeff e dar uma olhada no código existente. Tente olhar para Wordpress, Drupal, Joomla e outros CMSs baseados em PHP bem conhecidos para ver como suas APIs se parecem. Dessa forma, você pode até ter idéias que talvez não tenha pensado anteriormente para tornar as coisas um pouco mais irritadas.
Uma resposta mais direta seria escrever arquivos gerais que eles "incluiriam" em seu arquivo que forneceriam a usabilidade de que precisariam. Isso seria dividido em categorias e NÃO fornecido em um arquivo "hooks.php" MASSIVO. Porém, tenha cuidado, porque o que acaba acontecendo é que os arquivos que eles incluem acabam tendo mais e mais dependências e funcionalidades. Tente manter baixas as dependências da API. IE menos arquivos para incluir.
fonte
Existe um projeto interessante chamado Stickleback, de Matt Zandstra, no Yahoo, que lida com grande parte do trabalho de manipulação de plug-ins no PHP.
Ele reforça a interface de uma classe de plug-in, suporta uma interface de linha de comando e não é muito difícil de instalar - especialmente se você ler a matéria de capa sobre ela na revista de arquitetos PHP .
fonte
Um bom conselho é verificar como outros projetos o fizeram. Muitos pedem a instalação de plug-ins e seu "nome" registrado para serviços (como o wordpress), para que você tenha "pontos" em seu código, onde você chama uma função que identifica os ouvintes registrados e os executa. Um padrão de design OO padrão é o Observer Pattern , que seria uma boa opção para implementar em um sistema PHP verdadeiramente orientado a objetos.
O Zend Framework faz uso de muitos métodos de conexão e é muito bem arquitetado. Esse seria um bom sistema para se olhar.
fonte
Estou surpreso que a maioria das respostas aqui pareçam ser voltadas para plug-ins locais ao aplicativo da web, ou seja, plugins executados no servidor da web local.
E se você quiser que os plugins sejam executados em um servidor remoto diferente? A melhor maneira de fazer isso seria fornecer um formulário que permita definir diferentes URLs que seriam chamados quando eventos específicos ocorrerem no seu aplicativo.
Eventos diferentes enviariam informações diferentes com base no evento que acabou de ocorrer.
Dessa forma, você apenas executaria uma chamada cURL para a URL que foi fornecida ao seu aplicativo (por exemplo, através de https), na qual os servidores remotos podem executar tarefas com base nas informações enviadas pelo seu aplicativo.
Isso oferece dois benefícios:
fonte