Как использовать классы, объявленные в другом плагине?
Я разрабатываю плагин для WordPress Woocommerce. В локальной среде он работает нормально, но возникают проблемы при добавлении плагина в копию продакшн-среды. Я новичок в WordPress и не очень знаком с веб-разработкой (я Java программист).
В файле плагина я создаю экземпляр класса из пакета плагина Woocommerce следующим образом:
$coupon = new WC_Coupon($some_code);
В локальной среде (php 5.4.10, Woocommerce 2.0.13, Wordpress 3.6) всё работает нормально. В продакшн-среде (php 5.4.10, Woocommerce 1.6.5.2, Wordpress 3.4.2) возникает следующая ошибка:
Fatal error: Class 'WC_Coupon' not found
Я пытался подключить файл, где определен класс WC_Coupon, но тогда ошибка становится следующей:
Fatal error: Cannot redeclare class WC_Coupon
Так какой правильный способ использования классов, объявленных в другом плагине?
Примечание: обновление на данный момент не является возможным вариантом.
Вам нужно проверить существование класса, но перед этим необходимо дождаться загрузки всех плагинов: никто не может гарантировать, что ваш плагин загрузится после WooCommerce.
Для выполнения кода из плагина после загрузки всех плагинов используйте хук plugins_loaded
.
Обратите внимание, что этот хук нельзя использовать в теме, потому что к моменту загрузки темы этот хук уже сработал.
add_action('plugins_loaded', 'my_coupon_init');
function my_coupon_init() {
if ( class_exists('WC_Coupon') ) {
$coupon = new WC_Coupon($some_code);
// какой-то код здесь
} else {
add_action('admin_notices', 'wc_not_loaded');
}
}
function wc_not_loaded() {
printf(
'<div class="error"><p>%s</p></div>',
__('Извините, невозможно создать купон, потому что WooCommerce не загружен')
);
}

Не уверен, что в этом случае plugins_loaded
- это правильный хук. Нужно выяснить, когда именно этот класс становится доступен, и подключиться после этого. В любом случае +1

В данном конкретном случае я подключаюсь к хуку деактивации register_deactivation_hook( __FILE__, 'deactivate');
. Так что ждать я не могу. Могу ли я попросить WordPress загрузить класс, если он ещё не загружен?

Спасибо, @kaiser. Класс WC_Coupon
загружается через __construct
главного класса WooCommerce
(фактически через метод includes()
, вызываемый непосредственно из __construct
), а класс WooCommerce
создаётся (как синглтон) сразу после загрузки плагина. Так что plugins_loaded
в этом случае действительно подходящий хук ;)

Это уже поздно, но я хотел бы поделиться, как использовать WooCommerce и его классы без ошибки "class not found".
Первое - проверить, установлен ли WooCommerce, и использовать хук действия woocommerce_loaded
.
/**
* Проверяем, активен ли WooCommerce
**/
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
// Поместите сюда код вашего плагина
add_action('woocommerce_loaded' , function (){
//Поместите сюда код, который требует каких-либо классов WooCommerce
//Вы также можете инициализировать здесь основной файл вашего плагина
});
}
Надеюсь, это кому-то поможет.

Правильный способ будет следующим:
if( class_exists('WC_Coupon') ) $coupon = new WC_Coupon($some_code);
Лучше проверять, существует ли класс, перед его использованием, это позволяет избежать фатальной ошибки, если плагин отключен.
Вы не можете переопределить класс - это запрещено в PHP.
Вы также можете расширить класс:
class My_WC_Coupon extends WC_Coupon {
//код
//хук
}
Но в большинстве случаев, и в данном случае с WooCommerce, лучше найти подходящий хук в документации, который выполнит нужную задачу.

Заголовок "Requires Plugins" был добавлен в 2024 году, Введение зависимостей плагинов в WordPress 6.5
/**
* Plugin Name: Экспресс-платежный шлюз для магазина
* Requires Plugins: shop, payment-gateway
*/
Это позволяет плагину зависеть от другого плагина, который должен быть активирован. Порядок загрузки по-прежнему имеет значение, и другие ответы содержат решения, которые ожидают загрузки всех плагинов и дополнительно проверяют наличие ожидаемых классов.
