我正在编写一个脚本,我需要让它成为可插件。现在,我提供的语法应该适用于我,就是让它使用类。例如,为了创建一个在到达某个点(钩子)时运行的新插件,您需要声明一个新类。我不确定的是如何在该语法中指定钩子,所以我正在寻找建议。
语法示例:
<?php
class ScriptPlugin
{
function runPlugin() {} // would be run when the time has to come to execute this plugin
}
?>此外,如果语法不起作用,如果你们能给我一个很好的语法示例,那就太好了。
发布于 2011-12-27 01:34:53
脑海中浮现出观察者模式。插件会自行注册,并在钩子被调用时收到通知。
想到的另一件事是PHP中的回调。有一个带有an answer的similar question already出现在我的脑海中。它显示了基于回调的钩子。
观察者模式运行得有点短,因为使用钩子通常需要提供参数和返回值等内容。使用回调的链接答案也没有这个,所以我写了一个小的Hooks示例类,它为注册的回调提供了命名钩子/事件,并提供了一种注册自己的类的方法,例如插件。
这个想法很基本:
Hooks类中进行管理。Hooks挂接上的函数来调用挂接的主代码(和其他类)可以注册它们自己的回调,这是在Registerable接口的帮助下完成的。<代码>H214<代码>F215一些带有一个插件和两个钩子的示例代码:
<?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");我这样做是为了防止每个插件都必须有一个具体的基类,因为它想要使用钩子。此外,一切都可以注册钩子,唯一需要的是一个回调。例如,一个匿名函数:
$hooks->attach('hookName', function() {echo "Hook was called\n";});但是,您可以创建自己的插件基类,例如实现register函数,并自动注册具有特定docblock标记或函数名称的函数
class MyNewPlugin extends PluginSuper
{
/**
* @hook postPublished
*/
public function justAnotherFunction() {}
public hookPostPublished() {}
}超类可以利用Reflection在运行时添加钩子。然而,反射可能会减慢速度,并可能使调试变得更加困难。
发布于 2011-12-26 23:37:49
我会为所有可能被调用的钩子创建一个带有函数的抽象基类。
abstract class Plugin {
abstract function yourHook();
}所有的插件类都应该继承这个基类,并用它们自己的函数覆盖这些基函数。
class SomePlugin extends Plugin {
function yourHook() {
echo 'yourHook() Called!';
}
}现在,当您的程序运行时,您需要找到所有要包含的插件文件,并以某种方式将它们放入一个数组中,例如$plugins。请参阅本文:https://stackoverflow.com/a/599694/362536
foreach (glob("classes/*.php") as $filename)
{
include $filename;
}(摘自Karsten)
定义一个可以从任何地方访问的函数,例如registerPlugin()
function registerPlugin($classname) {
$plugins[] = new $classname();
}让每个插件文件的顶行像这样(在类之前):
registerPlugin('SomePlugin');如果这样做,您将在$plugins中拥有一个数组,其中包含每个插件的实例。在适当的时候,你可以这样做:
foreach ($plugins as $plugin) {
$plugin->yourHook();
}作为另一种选择,在您的情况下使用interfaces可能更合适。您应该决定哪种方法最适合您的应用程序。
发布于 2011-12-26 23:39:20
假设一个插件是这样的:
class NewsPlugin extends Plugin
{
function onCreate($title)
{
# Do some stuff
}
}然后,当你创建一条新闻时,你可以在所有注册的插件上调用onCreate。
https://stackoverflow.com/questions/8637054
复制相似问题