Вопрос или проблема
В плагине 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 интеграции должен соответствовать логике, реализованной в вашем плагине, и всегда проверяйте статус ваших хуков для предотвращения потенциальных конфликтов.