PHP 使用私有(private)方法作为回调

标签 php callback wordpress private

我是第一次尝试使用 PHP+WP。我打算使用 WP 插件 Hook 。作为一名 C++ 程序员,我还打算将我所有的代码放入类中。目前我有点卡在下面应该安装 WP 插件 Hook 的代码片段中:

   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 是有效回调,无法访问 E:\xampp\apps\wordpress\htdocs\wp-includes\plugin.php 中的私有(private)方法 SettingsHandler::AddSettingsLink() on line 199

当我将回调切换为公共(public)时,错误消失了。看来我不能在 PHP/WP 中使用私有(private)方法作为回调。这将是非常糟糕的,因为它揭示了许多不应该被其他任何人直接访问的回调方法。我可以将此类回调设为私有(private)吗?

我还发现以下代码段运行良好:

   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();

为什么第二个片段有效而第一个片段失败?哪里不一样了?

最佳答案

第二个版本有效,因为 preg_match_all 是从类范围内调用的,并且会立即执行回调。

但是the add_filter function only adds the callback to the global $wp_filter array .该数组中的回调随后会在稍后阶段从您在其中定义方法的类外部调用。因此,可见性规则适用,使回调不可访问。

您可以通过将对方法的调用包装到 anonymous function 中来解决此问题。 ,例如

public function __construct()
{
    add_filter(
        'plugin_action_links',
        function($links, $file) {
            return $this->AddSettingsLink($links, $file);
        },
        10,
        2
    );
}

但是,这至少需要 PHP 5.4(请参阅手册中的变更日志),因为 $this 在该版本之前的匿名函数中不可用。

另一种选择是让 SettingsHandler 实现 __invoke把它变成一个仿函数,例如你加

public function __invoke($links, $file)
{
    return $this->AddSettingsLink($links, $file);
}

并将构造函数代码更改为

add_filter('plugin_action_links', $this, 10, 2);

由于该类将 __invoke 实现为公共(public)入口点,因此该实例可用作回调。这样,您就可以将私有(private)内容保密。

附带说明一下,我会将添加过滤器的代码移到类外部。将它放在 ctor 中会使类的可测试性降低(是的,我知道没有人测试 WP 插件,但仍然如此)。相反,将它放入您的插件文件中,然后包含那里所需的所有其他内容,例如

// your-plugin.php
include 'SettingsHandler.php';
add_filter('plugin_action_links', new SettingsHandler, 10, 2);

但这取决于你。

¹注意:显然这在 Wordpress 中不起作用,因为它会尝试在某个地方序列化闭包。通常,这是一种提供私有(private)方法作为回调的工作模式。

关于PHP 使用私有(private)方法作为回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22426794/

相关文章:

javascript - 如何在复选框中组合相同命名的值并为其指定默认值

javascript - 将数据获取到数据库,如果匹配则重新插入

php - 两个 SQL 查询返回奇怪的结果

javascript - CSS 转换没有开始/回调没有被调用

callback - 带有参数的 Ionic2 navController pop(回调)

reactjs - 如何使用 React 功能组件通过循环回调获取 api

php - Elasticsearch查找子域

php - 为什么 Wordpress 的 'save_post_{$post->post_type}' Action 钩子(Hook)没有传递正确数量的参数?

javascript - lightgallery 库 + lg-thumbnail 插件

wordpress - Fishpig Magento 模块 : How to get data from postmeta table?