为什么在WordPress插件中的类中使用$this会抛出致命错误?

8
我正在编写一个WordPress插件,它会创建一个管理区域的页面,并执行一些前端代码。
下面的代码会抛出一个很好的“Fatal error: Using $this when not in object context”错误。这相当令人困惑,因为变量在类内部被调用。
也许我没有按照预期的WordPress插件结构来编写函数和类,但是下面的概念代码是使用WordPress Codex中有关插件开发的相关条目创建的。
有人能解释一下为什么会触发此错误吗?因为当我在WordPress代码库之外创建类的实例时,一切都很好。
if (!class_exists("MyClass")) {
  class MyClass {
    var $test = 'Test variable';

    public function index() {
      //Index code
    }

    public function add() {
      echo $this->test;
    }
  }
}

add_action('admin_menu', 'my_plugin_menu');

function my_plugin_menu() {
  add_menu_page('My Plugin', 'My Plugin', 'manage_options', 'my-plugin', array('MyClass', 'index'));
  add_submenu_page('my-plugin', 'Add New Thing', 'Add New', 'manage_options', 'my-plugin-add', array('MyClass', 'add'));
}
4个回答

10

所以,我似乎已经解决了它,回到基础并向谷歌提出了这个简单的问题:"在WordPress插件中使用类"

两篇文章都很有帮助,分别是Jay FortnerdConstructing.com

基本上,我现在是从类内调用add_menu_page和add_submenu_page。 我原来认为这些函数会创建一个对象,但显然不是这样的。

我的代码现在看起来像这样,并且我可以调用已声明的类变量而没有错误:

if (!class_exists("MyClass")) {
  class MyClass {
    var $test = 'Test variable';

    function __construct() {
      add_action('admin_menu', 'my_plugin_menu');
    }

    function my_plugin_menu() {
      add_menu_page('My Plugin', 'My Plugin', 'manage_options', 'my-plugin', array(&$this, 'index'));
      add_submenu_page('my-plugin', 'Add New Thing', 'Add New', 'manage_options', 'my-plugin-add', array(&$this, 'add'));
    }

    public function index() {
      //Index code
    }

    public function add() {
      echo $this->test;
    }
  }
  new MyClass;
}

嘿...,这段代码对我不起作用。因此,我将这个函数add_action('admin_menu', 'my_plugin_menu');更改为add_action('admin_menu', array($this, 'my_plugin_menu')); - Ari

5

这已经不再是真的了。

请注意,如果您传递类,可能需要通过引用传递它,甚至可以在类内部使用&$this来传递类自己的函数并继续修改相同的实例,这有助于不必每次调用插件的不同部分时重新创建一个类但是保持相同的类。

来自:https://codex.wordpress.org/Function_Reference/do_action_ref_array

自PHP 5.4以来,尽管函数名称中仍然包含引用,但数组不再通过引用传递。您甚至不能使用引用符号'&',因为现在调用时间的传递按引用抛出错误。您可以将引用指针作为数组元素传递。这样做确实要求将添加到操作的所有回调都期望引用指针。这不是您将在WordPress操作中看到的内容。此技术仅供信息参考。

$Class = new MyClass();
 add_menu_page(
       'My Plugin',
        'My Plugin',
        'manage_options',
        'my-plugin',
        array(&$Class, 'index')

或者

$myClass= new MyClass ;

add_action('admin_menu', array( $myClass, 'admin_menu' ) );

class MyClass 
{
    public function admin_menu()
    {   
        add_menu_page('MyMenu', 'MyMenu', 'read', 'mymenu', array( $this, 'action' ));  
    }
    public function action()
    {   
        //Do something here
    }
}

在 action 中添加了 form 标签。那我应该传递什么到 action 中,还有哪里可以获取到 post 的值呢?先谢谢了。 - Vishal Tanna
检查 $_POST 数组以获取提交的值。 - geilt

4
你需要做的是以下几点:
function my_plugin_menu()
{
add_menu_page('My Plugin', 'My Plugin', 'manage_options', 'my-plugin', array(new MyClass, 'index'));
add_submenu_page('my-plugin', 'Add New Thing', 'Add New', 'manage_options', 'my-plugin-add', array('MyClass', 'add'));
}

使用 array('MyClass', 'index') 会导致php将该方法执行为静态方法,但是如果将实际对象作为第一个参数传递,则会通过对象调用该方法。

function my_plugin_menu()
{
    $Class = new MyClass();
    add_menu_page(
        'My Plugin',
        'My Plugin',
        'manage_options',
        'my-plugin',
        array($Class, 'index')
    );
}

如果您想重复使用该对象,这也是可行的。

1

这取决于类的调用方式,静态调用 Class::method() 会抛出错误。如果是这种情况,我认为你需要使用 self::$test;但也可能是我错了。


我不确定WordPress如何调用这个类,但是使用self::test而不是$this->test并不能解决错误,恐怕是其他问题引起的。 - mensch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接