2011-12-26 12 views
5

Estoy trabajando en un script, y tengo que hacerlo conectable. Ahora la sintaxis con la que he venido y que debería funcionar para mí, es hacer que use clases. Por ejemplo, para crear un nuevo complemento que se ejecutaría cuando se alcanza un determinado punto (gancho), declararía una nueva clase. Lo que no estoy seguro es cómo se especificará el gancho en esa sintaxis, entonces estoy buscando sugerencias.Hacer un script conectable

ejemplo de sintaxis:

<?php 
class ScriptPlugin 
{ 
    function runPlugin() {} // would be run when the time has to come to execute this plugin 
} 
?> 

Además, si la sintaxis que no va a funcionar, sería grande si ustedes me podría dar un buen ejemplo de sintaxis.

+0

No ha agregado el código a su pregunta, que en realidad mostraría la sintaxis sobre la que pregunta. Por favor agregue ese código; de lo contrario, es difícil de decir. – hakre

+0

posible duplicado de [La mejor forma de permitir complementos para una aplicación PHP] (http://stackoverflow.com/questions/42/best-way-to-allow-plugins-for-a-php-application) – hakre

Respuesta

3

Existe el Patrón de observador que viene a la mente. Los complementos se registrarán y recibirán notificaciones cuando se invoque el enlace.

Otra cosa que me viene a la mente son las devoluciones de llamada en PHP. Y había un similar question already con an answer que me vino a la mente. Muestra ganchos basados ​​en callbacks.

Observer Pattern se ejecuta un poco corto porque con ganchos a menudo quiere proporcionar cosas como argumentos y un valor de retorno.La respuesta vinculada que usa devoluciones de llamada tampoco tiene esto, así que escribí una pequeña clase de ejemplo Hooks que proporciona ganchos/eventos con nombre para las devoluciones de llamada registradas, y una forma de registrar sus propias clases, p. un plugin

La idea es bastante básico:

  • Un gancho tiene un nombre y cero o más devoluciones de llamada adjunta.
  • Todos los enganches se administran en una clase Hooks.
  • El código principal invoca los ganchos llamando a una función en el objeto Hooks.
  • Los complementos (y otras clases) pueden registrar sus propias devoluciones de llamada, lo que se hace con la ayuda de la interfaz Registerable.

un código de ejemplo con un plugin y dos ganchos:

<?php 
Namespace Addon; 

class Hooks 
{ 
    private $hooks = array(); 
    private $arguments; 
    private $name; 
    private $return; 
    public function __call($name, array $arguments) 
    { 
     $name = (string) $name; 
     $this->name = $name; 
     $this->arguments = $arguments; 
     $this->return = NULL; 
     foreach($this->getHooks($name) as $hook) 
     { 
      $this->return = call_user_func($hook, $this); 
     } 
     return $this->return; 
    } 
    public function getHooks($name) 
    { 
     return isset($this->hooks[$name]) ? $this->hooks[$name] : array(); 
    } 
    public function getArguments() 
    { 
     return $this->arguments; 
    } 
    public function getName() 
    { 
     return $this->name; 
    } 
    public function getReturn() 
    { 
     return $this->return; 
    } 
    public function setReturn($return) 
    { 
     $this->return = $return; 
    } 
    public function attach($name, $callback) 
    { 
     $this->hooks[(string) $name][] = $callback; 
    } 
    public function register(Registerable $plugin) 
    { 
     $plugin->register($this); 
    } 
} 

interface Registerable 
{ 
    public function register(Hooks $hooks); 
} 

class MyPlugin implements Registerable 
{ 
    public function register(Hooks $hooks) 
    { 
     $hooks->attach('postPublished', array($this, 'postPublished')); 
     $hooks->attach('postDisplayFilter', array($this, 'filterToUpper')); 
    } 
    public function postPublished() 
    { 
     echo "MyPlugin: postPublished.\n"; 
    } 
    public function filterToUpper(Hooks $context) 
    { 
     list($post) = $context->getArguments(); 
     return strtoupper($post); 
    } 
} 

$hooks = new Hooks(); 

$plugin = new MyPlugin(); 
$hooks->register($plugin); 

$hooks->postPublished(); 

echo $hooks->postDisplayFilter("Some post text\n"); 

lo he hecho de esta manera para evitar que cada Plugin debe tener una clase base de hormigón sólo porque quiere hacer uso de ganchos . Además, todo puede registrar ganchos, lo único que se necesita es una devolución de llamada. Por ejemplo una función anónima:

$hooks->attach('hookName', function() {echo "Hook was called\n";}); 

sin embargo, puede crear usted mismo una clase base plugin, que, por ejemplo implementa la función register y se registrará automáticamente las funciones que tienen una determinada etiqueta de bloque de documentación o el nombre de una función

class MyNewPlugin extends PluginSuper 
{ 
    /** 
    * @hook postPublished 
    */ 
    public function justAnotherFunction() {} 

    public hookPostPublished() {} 
} 

La superclase puede hacer uso de Reflection para agregar los ganchos en el tiempo de ejecución. Sin embargo, la reflexión puede ralentizar las cosas y hacer que las cosas sean más difíciles de depurar.

+0

Esto funciona de la manera que quería que funcionara. Traté de implementar la clase que automáticamente registraría una función, que debería ejecutarse cuando se inicia el complemento, pero no tuvo éxito. Lamentablemente, no sé mucho sobre OOP :( –

+0

El complemento necesita registrar su función en un gancho. Es posible que desee agregar su código al final de mi respuesta para que pueda echar un vistazo. – hakre

0

Haría una clase abstracta base con funciones para todos los enganches que pudieran llamarse.

abstract class Plugin { 
    abstract function yourHook(); 
} 

Todas las clases de complementos deben heredar esta clase base y anularán esas funciones básicas con las suyas propias.

class SomePlugin extends Plugin { 
    function yourHook() { 
     echo 'yourHook() Called!'; 
    } 
} 

Ahora, cuando el programa se ejecuta, tiene que encontrar todos los archivos de plugin para incluir, y de alguna manera ponerlos en una matriz, tal como $plugins. Ver este artículo: https://stackoverflow.com/a/599694/362536

foreach (glob("classes/*.php") as $filename) 
{ 
    include $filename; 
} 

(De Karsten)

definir una función accesible desde todo, como registerPlugin():

function registerPlugin($classname) { 
    $plugins[] = new $classname(); 
} 

hacer que la línea superior de cada archivo plugin como esto (antes de la clase):

registerPlugin('SomePlugin'); 

Si hace esto, tendrá una matriz en $plugins con instancias de cada complemento. En el momento adecuado, se puede hacer algo como esto:

foreach ($plugins as $plugin) { 
    $plugin->yourHook(); 
} 

Como alternativa, puede ser más apropiado utilizar interfaces en su caso, en lugar. Debe decidir qué método es mejor para su aplicación.

+0

Todo lo que es multa. Es exactamente lo que quiero lograr. Pero, en lo que fallé, es que no pude reconocer cuál es el nombre de la clase que está en el archivo del complemento. No creo que sea tan bueno exigir que el archivo del complemento tenga el mismo nombre que la clase, para saber qué nombre tiene realmente la clase, ¿verdad? –

+0

Ah, veo, un segundo mientras actualizo mi publicación con un método. – Brad

+0

Ok, actualicé mi publicación. ¿Eso tiene más sentido ahora? – Brad

0

Digamos que un plugin es como:

class NewsPlugin extends Plugin 
{ 
    function onCreate($title) 
    { 
    # Do some stuff 
    } 
} 

A continuación, cuando se crea una noticia que sólo puede llamar onCreate en todos los plugins registrados.

+0

Esa es la sintaxis que intento lograr. Pero, tengo problemas para encontrar todos los complementos. ¿Cómo podría hacer eso? –

+0

Normalmente los incluyo en un directorio llamado 'plugins' y los necesito todos en mi encabezado usando' glob'. Todos extienden la misma clase base. – Cydonia7

+0

¿Qué piensas si pudiera utilizar el método a__construct() en la clase Plugin, de modo que cuando se crea una nueva instancia y se basa en esa clase, de alguna manera debe pasar $ esta variable a la matriz plugins? –

Cuestiones relacionadas