Ошибка PHP с обработчиком шорткода из класса

13

В настоящее время я использую следующий общий поток для добавления шорткода для плагина.

class MyPlugin {

    private $myvar;

    function baztag_func() {
        print $this->myvar;            
    }
}

add_shortcode( 'baztag', array('MyPlugin', 'baztag_func') );

Теперь, когда этот класс и его метод вызваны, я получаю следующую ошибку.

Неустранимая ошибка: использование $ this, когда не в контексте объекта в ...

(Строка №, где я напечатал $this->myvar)

Это проблема на стороне WordPress или я что-то не так делаю? Кажется, что-то действительно простое.

xmaestro
источник
не по теме - сделать функцию static.
Кайзер

Ответы:

31

Как говорит ошибка, вам нужен экземпляр класса для использования $this. Есть как минимум три возможности:

Сделай все статичным

class My_Plugin
{
    private static $var = 'foo';

    static function foo()
    {
        return self::$var; // never echo or print in a shortcode!
    }
}
add_shortcode( 'baztag', array( 'My_Plugin', 'foo' ) );

Но это уже не настоящий ООП, просто пространство имен.

Сначала создайте реальный объект

class My_Plugin
{
    private $var = 'foo';

    public function foo()
    {
        return $this->var; // never echo or print in a shortcode!
    }
}

$My_Plugin = new My_Plugin;

add_shortcode( 'baztag', array( $My_Plugin, 'foo' ) );

Это работает. Но вы столкнетесь с некоторыми неясными проблемами, если кто-то захочет заменить шорткод.

Поэтому добавьте метод для предоставления экземпляра класса:

final class My_Plugin
{
    private $var = 'foo';

    public function __construct()
    {
        add_filter( 'get_my_plugin_instance', [ $this, 'get_instance' ] );
    }

    public function get_instance()
    {
        return $this; // return the object
    }

    public function foo()
    {
        return $this->var; // never echo or print in a shortcode!
    }
}

add_shortcode( 'baztag', [ new My_Plugin, 'foo' ] );

Теперь, когда кто-то хочет получить экземпляр объекта, ему нужно написать:

$shortcode_handler = apply_filters( 'get_my_plugin_instance', NULL );

if ( is_a( $shortcode_handler, 'My_Plugin ' ) )
{
    // do something with that instance.
}

Старое решение: создать объект в вашем классе

class My_Plugin
{
    private $var = 'foo';

    protected static $instance = NULL;

    public static function get_instance()
    {
        // create an object
        NULL === self::$instance and self::$instance = new self;

        return self::$instance; // return the object
    }

    public function foo()
    {
        return $this->var; // never echo or print in a shortcode!
    }
}

add_shortcode( 'baztag', array( My_Plugin::get_instance(), 'foo' ) );
Фуксия
источник
спасибо человек ... это бесценная информация, так как wordpress.org не рассказал об этом на странице документации add_shortcode. Я нашел решение, но так как вы исключили это как плохую практику, и у вас есть лучшее решение, поэтому я
отмечаю
Мне очень жаль , чтобы выкопать этот старый вопрос, но не могли бы вы Plase уточнить , что делает эта строка: NULL === self::$instance and self::$instance = new self;? Я немного запутался, потому что ===и andиспользуется, но без if, если вы понимаете, о чем я.
Свен
@Sven Это проверка для предотвращения второго экземпляра. Это делает этот класс Синглтоном ... Я бы не стал этого делать в наше время. Я перепишу этот ответ.
fuxia
Спасибо за это! Я думаю, что теперь я на правильном пути, хотя удивительно, насколько сложно это может быть с использованием WordPress & OOP ;-)
Sven
2
Ядро @Sven WordPress написано как можно более анти-ООП. Даже новый код игнорирует все то, чему научился остальной мир PHP за последние десять лет, например внедрение зависимостей. Так что да, ООП в плагинах и темах WordPress всегда хакерская. : /
fuxia
7

Вы можете использовать как это, короткий код внутри класса

class stockData{


    function __construct() {
        add_shortcode( 'your_shortcode_name', array( $this, 'showData' ) );
        //add_action('login_enqueue_scripts', array( $this,'my_admin_head'));
    }

    function showData(){
        return '<h1>My shortcode content</h1>' ;
    }
}

$object=new stockData();

Если вы хотите получить доступ к шорткоду из другого класса. Вы можете сделать это так.

class my_PluginClass {

  public function __construct( $Object ) {

    $test = add_shortcode( 'your_shortcode_name', array( $Object, 'your_method_name' ) );

  }

}

class CustomHandlerClass{

  public function your_method_name( $atts, $content ) {
     return '<h1>My shortcode content</h1>' ;
  }
}

$Customobject  = new CustomHandlerClass();
$Plugin         = new my_PluginClass( $Customobject );
Павниш Ядав
источник
1
Мне очень нравится это решение. Это действительно чисто и понятно. Разработчик React.js, я доволен этим.
AaronDancer
1

Убедитесь, что вы создаете экземпляр своего класса перед его использованием, если вы не уверены, что он должен вызываться статически. Когда вы вызываете метод статически, вы не используете никаких экземпляров, и поэтому он не имеет доступа ни к каким переменным или методам-членам.

woony
источник