Помилка PHP з обробником короткого коду з класу


13

В даний час я використовую наступний загальний потік для додавання короткого коду для плагіна.

class MyPlugin {

    private $myvar;

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

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

Тепер, коли цей клас і його метод називаються, я отримую таку помилку.

Фатальна помилка: Використання $ this, коли не в об'єктному контексті у ...

(Рядок № там, де я надрукував $this->myvar)

Це проблема в кінці Wordpress чи є щось, що я роблю неправильно? Здається, це щось справді просте.


поза темою - зробіть функцію 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' ) );

Але це вже не справжній OOP, а просто простір імен.

Створіть спочатку справжній об’єкт

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. Я вирішив це рішення, але оскільки ви визнали це поганою практикою, і ви маєте краще рішення, тому я
позначу

Мені дуже шкода, щоб розкопати це старе питання, але чи можете ви докладно пояснити, що робить цей рядок NULL === self::$instance and self::$instance = new self;:? Я трохи розгублений, тому що ===і andвикористовуюсь, але без if, якщо ви знаєте, що я маю на увазі.
Свен

@Sven Це перевірка для запобігання другої інстанції. Це робить цей клас Сінглтоном ... Я б цього не робив сьогодні. Я перепишу цю відповідь.
fuxia

Дякую за це! Я думаю, що зараз я на вірному шляху, хоча дивно, наскільки складним може бути використання WordPress & OOP ;-)
Sven

2
Сервер @Sven WordPress написаний якомога більше анти-OOP. Навіть новий код ігнорує все, що решта світу PHP дізналися за останні десять років, наприклад, ін'єкцію залежності. Так що так, OOP у 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

Переконайтеся, що ви робите примірник свого класу, перш ніж використовувати його, якщо ви не впевнені, що його слід називати статично. Коли ви викликаєте метод статично, ви не використовуєте жодних екземплярів, і тому він не має доступу до будь-яких змінних чи методів-членів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.