我第一次尝试使用PHP + WP。我打算使用WP插件钩子。作为一名C ++程序员,我还打算将所有代码放入类中。目前我有点困在应该安装WP插件钩子的以下片段:
class SettingsHandler
{
public function __construct()
{
add_filter('plugin_action_links', array($this, 'AddSettingsLink'), 10, 2);
}
private function AddSettingsLink($links, $file)
{
if ($file==plugin_basename(__FILE__))
{
$settings_link = '<a href="options-general.php?page=options_page">Settings</a>';
array_unshift($links, $settings_link);
}
return $links;
}
}
$settingsHandler = new SettingsHandler();
这给了我一条错误信息: 警告:call_user_func_array()期望参数1是有效的回调,无法在第199行的E:\ xampp \ apps \ wordpress \ htdocs \ wp-includes \ plugin.php中访问私有方法SettingsHandler :: AddSettingsLink()
当我将回调切换为公共时,错误消失了。看来我不能在PHP / WP中使用私有方法作为回调。这将是非常糟糕的,因为它揭示了许多不应由其他任何人直接访问的回调方法。我可以将这些回调设为私人吗?
我还发现以下代码段运行良好:
class a
{
public function __construct()
{
$str = " test test ";
$result = preg_replace_callback('/test/', array($this, 'callback'), $str);
echo $result;
}
private function callback($m)
{
return 'replaced';
}
}
$a = new a();
为什么第二个片段在第一个片段失败时有效?区别在哪里?
答案 0 :(得分:4)
第二个版本有效,因为从类范围内调用preg_match_all
并立即执行回调。
但是the add_filter
function only adds the callback to the global $wp_filter
array。然后在稍后阶段从 outside 您定义方法的类调用该数组中的回调。因此,可见性规则适用于使回调无法访问。
你可以通过将对方法的调用包装成anonymous function来解决这个问题,例如
public function __construct()
{
add_filter(
'plugin_action_links',
function($links, $file) {
return $this->AddSettingsLink($links, $file);
},
10,
2
);
}
但是,由于$this
在该版本之前的匿名函数中不可用,因此至少需要PHP 5.4(请参阅手册中的changelog)。
另一种选择是让SettingsHandler
实施__invoke
将其转换为Functor,例如你添加
public function __invoke($links, $file)
{
return $this->AddSettingsLink($links, $file);
}
并将ctor代码更改为
add_filter('plugin_action_links', $this, 10, 2);
由于该类将__invoke
实现为公共入口点,因此该实例可用作回调。这样,您就可以将私有内容保密。
在旁注中,我会移动代码在类外添加过滤器。在ctor中使用它会使类不易测试(是的,我知道没有人测试WP插件,但仍然)。相反,将它放入您的插件文件中,然后包含其中所需的所有其他内容,例如
// your-plugin.php
include 'SettingsHandler.php';
add_filter('plugin_action_links', new SettingsHandler, 10, 2);
但这取决于你。
¹ 注意:显然这在Wordpress中不起作用,因为它会尝试在此过程中的某个地方序列化闭包。通常,这是一种工作模式,用于提供私有方法作为回调。