Доступ к дочернему классу плагина экземпляра главного класса

Вопрос или проблема

В плагине WordPress, где автор определил родительский класс и использует стандартный метод экземпляра для доступа других авторов плагинов, пример плагина:

function WP_Plugin() {
     return WP_PLUGIN_NAME::instance();
}

В функции __construct инициализации этого класса плагина используется require_once для нескольких других классов, пример:

require_once( 'includes/class-wp-plugin-child-class.php' );

Этот класс также имеет функцию __construct (которая выполняется при инициализации основного класса).

Проблема в том, что другие классы, загружаемые из основного класса, не имеют метода экземпляра и никакого способа прямого доступа к ним (насколько я могу найти).

Как получить доступ к любым функциям/хукам и т.д. в этих других классах. Без, конечно же, повторного объявления класса, т.е.:

$subclass = new WpPluginChildClass();

Это не сработает (это снова вызовет все функции __construct и т.д.).


Редактировать – добавление гораздо более подробной информации и точного кода образца плагина, с которым я пытаюсь это сделать.

Я столкнулся с этим в нескольких разных крупных плагинах (особенно связанных с WooCommerce). Текущий, над которым я пытаюсь работать, является платным плагином, поэтому я считаю, что только ответственно включить то, что должно быть актуально для вопроса 🙂

Плагин использует паттерн однозначной (singleton) инициализации:

class WC_Freshdesk {
    protected static $instance = null;

    public static function get_instance() {
        // Если единственный экземпляр еще не установлен, установите его сейчас.
        if ( null == self::$instance ) {
            self::$instance = new self;
        }
        return self::$instance;
    }
}

В методе __construct() родительский класс включает несколько файлов. Один из них является дочерним классом.

class WC_Freshdesk_Integration extends WC_Integration {
    public function __construct() {
        add_action( 'woocommerce_view_order', array( $this, 'view_order_create_ticket' ), 40 );
    }
}

Я пытаюсь получить доступ к этому add_action, чтобы удалить его из шаблона темы.

Я пробовал следующее:

$freshdesk = WC_Freshdesk::get_instance();

remove_action( 'woocommerce_view_order', array( $freshdesk, 'view_order_create_ticket', 40 ) );

Ничего не вышло.

Затем, когда пытался:

$freshdesk = new WC_Freshdesk_Integration();

remove_action( 'woocommerce_view_order', array( $freshdesk, 'view_order_create_ticket', 40 ) );

Оказалось, что я снова объявляю класс WC_Freshdesk_integration(), потому что хук add_action срабатывает два раза.

Какой правильный способ получить доступ к этому дочернему классу, чтобы удалить это действие?

Если вы хотите получить экземпляр WC_Freshdesk без повторной инициализации, тогда вызовите:

$integrations = WC()->integrations->get_integrations();

remove_action('woocommerce_view_order', array($integrations['wc-freshdesk'], 'view_order_create_ticket'), 40 ); 

Заметка: Я просто предполагаю, что ключ – это wc-freshdesk, иначе проверьте массив

Вызов WC()->integrations->get_integrations() возвращает все интеграции, которые были инициализированы ранее в процессе инициализации woocommerce. Вы можете выбрать нужный экземпляр, если знаете id интеграции.

Вы найдете свойство id класса внутри класса, который расширяет WC_Integration, в данном случае WC_Freshdesk_Integration.

Ответ или решение

Чтобы получить доступ к дочернему классу экземпляра основного класса плагина в WordPress, где используется паттерн одиночки (Singleton), следуйте описанным ниже шагам. В этом ответе мы уделим внимание пониманию структуры классов, метода инциализации и правильной манере удаления хука, без повторной инициализации дочернего класса.

1. Понимание структуры классов

В вашем примере класс WC_Freshdesk реализует паттерн одиночки с использованием защищённого статического свойства $instance. Это гарантирует, что только один экземпляр класса будет создан, когда вызывается метод get_instance().

Класс WC_Freshdesk_Integration расширяет класс WC_Integration, добавляя действие (hook) с помощью метода add_action в своём конструкторе.

2. Удаление действия без повторной инициализации

Для того чтобы удалить действие без повторной инициализации дочернего класса, вы можете использовать метод WC()->integrations->get_integrations(), который возвращает массив всех интеграций. Это позволяет вам получить доступ к уже созданному экземпляру WC_Freshdesk_Integration и удалить действие.

Используйте следующий код:

// Получаем интеграции
$integrations = WC()->integrations->get_integrations();

// Убедитесь, что $integrations содержит ваш класс. 
// В данном случае вам нужно знать ID интеграции
$freshdesk_integration = $integrations['wc-freshdesk']; // Подставьте правильный ключ

// Удаляем действие
remove_action('woocommerce_view_order', array($freshdesk_integration, 'view_order_create_ticket'), 40);

Обратите внимание, что для успешного удаления действия вы должны использовать правильный ключ для доступа к вашей интеграции из массива $integrations. Ключ часто соответствует ID интеграции, который можно найти в классе, который вы расширяете (WC_Freshdesk_Integration).

3. Как узнать ID интеграции

Чтобы узнать ID интеграции, откройте файл, в котором определён класс WC_Freshdesk_Integration, и найдите соответствующее свойство, которое представляет собой ID (обычно это свойство называется id). Например:

class WC_Freshdesk_Integration extends WC_Integration {
    public function __construct() {
        $this->id = 'wc-freshdesk'; // Пример
        add_action( 'woocommerce_view_order', array( $this, 'view_order_create_ticket' ), 40 );
    }
}

Заключение

С использованием подхода, описанного выше, вы сможете эффективно удалить действие, добавленное дочерним классом, без повторной инициализации этого класса. Это позволяет управлять хуками и интеграциями в вашем WordPress приложении с минимальными усилиями и без негативных последствий для производительности. Убедитесь, что вы осознаёте, что ID интеграции должен соответствовать логике, реализованной в вашем плагине, и всегда проверяйте статус ваших хуков для предотвращения потенциальных конфликтов.

Оцените материал
Добавить комментарий

Капча загружается...