Cum să folosești clase declarate în alt plugin?
Dezvolt un plugin WordPress WooCommerce. În mediul local funcționează bine, dar am probleme când adaug plugin-ul într-o replică a mediului de producție. Sunt nou în WordPress și nu sunt foarte familiarizat cu dezvoltarea web (sunt programator Java).
În fișierul plugin-ului, instanțiez o clasă din pachetul plugin-ului WooCommerce astfel:
$coupon = new WC_Coupon($some_code);
În mediul local (php 5.4.10, WooCommerce 2.0.13, WordPress 3.6) funcționează bine. În mediul de producție (php 5.4.10, WooCommerce 1.6.5.2, WordPress 3.4.2) am următoarea eroare:
Fatal error: Class 'WC_Coupon' not found
Am încercat să includ fișierul unde este definită clasa WC_Coupon, dar apoi eroarea devine:
Fatal error: Cannot redeclare class WC_Coupon
Care este modalitatea corectă de a folosi clase declarate în alt plugin?
Notă: actualizarea nu este o opțiune în acest moment.
Trebuie să verifici dacă clasa există, dar înainte de asta trebuie să aștepți ca toate pluginurile să fie încărcate: nimeni nu poate garanta că pluginul tău este încărcat după WooCommerce.
Pentru a rula un cod dintr-un plugin atunci când toate pluginurile sunt încărcate, folosește hook-ul plugins_loaded
.
Atenție: nu poți folosi acest hook într-o temă, deoarece atunci când tema se încarcă, acest hook a fost deja declanșat.
add_action('plugins_loaded', 'my_coupon_init');
function my_coupon_init() {
if ( class_exists('WC_Coupon') ) {
$coupon = new WC_Coupon($some_code);
// codul tău aici
} else {
add_action('admin_notices', 'wc_not_loaded');
}
}
function wc_not_loaded() {
printf(
'<div class="error"><p>%s</p></div>',
__('Ne pare rău, nu pot crea cuponul deoarece WooCommerce nu este încărcat')
);
}

Nu sunt sigur dacă în acest caz plugins_loaded
este hook-ul potrivit. Va trebui să căutăm exact când acea clasă devine disponibilă și să folosim hook-ul după acel moment. Oricum, +1

În acest caz particular, mă conectez la hook-ul de dezactivare register_deactivation_hook( __FILE__, 'deactivate');
. Așadar, nu pot aștepta. Pot să cer WordPress să încarce clasa dacă nu este încărcată?

Mulțumesc @kaiser. Clasa WC_Coupon
este încărcată de __construct
din clasa principală WooCommerce
(mai exact prin metoda includes()
apelată direct de __construct
), iar clasa WooCommerce
este instanțiată (ca singleton) imediat ce plugin-ul este încărcat. Deci plugins_loaded
este hook-ul potrivit în acest caz ;)

Este prea târziu, dar aș vrea să împărtășesc cum să folosești WooCommerce și clasele sale fără a primi eroarea "class not found".
Primul pas este să verifici dacă WooCommerce este instalat și să folosești hook-ul de acțiune woocommerce_loaded
.
/**
* Verifică dacă WooCommerce este activ
**/
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
// Pune codul plugin-ului tău aici
add_action('woocommerce_loaded' , function (){
//Pune aici codul care are nevoie de orice clasă WooCommerce
//Poți de asemenea să instanțiezi fișierul principal al plugin-ului tău aici
});
}
Sper că acest lucru va ajuta pe cineva.

Modul corect ar fi:
if( class_exists('WC_Coupon') ) $coupon = new WC_Coupon($some_code);
Este mai bine să verifici dacă clasa există înainte de a o utiliza, evitând astfel erori fatale dacă plugin-ul este dezactivat.
Nu poți redeclara o clasă, acest lucru nu este permis în PHP.
De asemenea, poți extinde clasa:
class My_WC_Coupon extends WC_Coupon {
//unele coduri
//unele hook-uri
}
Dar de cele mai multe ori, și în acest caz cu WooCommerce, este mai bine să găsești un hook în documentație care să se ocupe de treabă.

Un antet "Requires Plugins" a fost adăugat în 2024, Introducerea dependențelor de plugin-uri în WordPress 6.5
/**
* Plugin Name: Express Payment Gateway Checkout for Shop
* Requires Plugins: shop, payment-gateway
*/
Acest lucru permite unui plugin să depindă de activarea altui plugin. Ordinea de încărcare rămâne o preocupare, iar alte răspunsuri oferă soluții care așteaptă încărcarea tuturor plugin-urilor și verifică suplimentar dacă clasele așteptate există.
