The plugin activated, the booking form worked, and then I built an Elementor widget so users could drag the booking form into their page designs, and the site crashed. The error named a class I had definitely not misspelled, Elementor’s own widget base class, not found. The code was correct. The timing was wrong, and the rule I learned here governs every plugin that extends another plugin.
An Elementor widget is a PHP class extending Elementor’s base:
class Elite_Limo_Widget extends ElementorWidget_Base {
public function get_name() { return 'elite_limo_booking'; }
public function get_title() { return 'Limo Booking Form'; }
// controls and render...
}
Here is the trap. PHP processes that extends clause the moment the file defining the class is loaded. If my plugin loads this file while Elementor has not loaded yet, PHP looks for ElementorWidget_Base, finds nothing, and dies with class not found. WordPress loads plugins in its own order and mine happened to load before Elementor, so my widget file was extending a class that did not exist yet. Same code, loaded a moment too early, fatal.
The fix is never to load such a file eagerly, and instead register through Elementor’s own hook, which by definition fires only after Elementor exists:
add_action('elementor/widgets/register', function($widgets_manager) {
require_once ELITE_LIMO_PLUGIN_PATH . 'includes/class-elementor-widget.php';
$widgets_manager->register(new Elite_Limo_Widget());
});
Two things happen there. The widget file is required inside the hook callback, so PHP only reads the extends line after Elementor’s classes exist. And Elementor hands over its widgets manager, the official registration door. For extra safety when Elementor might not be installed at all, guard before touching anything of theirs:
if ( did_action('elementor/loaded') ) {
// safe to reference Elementor classes
}
did_action asks whether a hook has already fired, making it the polite way to ask, is that plugin actually here, before extending its classes. With the require moved inside the hook and the guard in place, the widget appeared in Elementor’s panel and the crash never returned. The general rule extends far past Elementor, WooCommerce, ACF, any plugin you integrate with, your code must not touch their classes until their loaded hook says they exist.
A few things people ask me about this
Why do I get Elementor Widget_Base not found? Your widget class file loads before Elementor does. Require it inside the elementor/widgets/register hook callback instead of at the top of your plugin.
How do I check another plugin is active before using it? Check its signature hook or class, did_action(‘elementor/loaded’), or class_exists on its main class, before touching anything it provides.
Next
With the interface stable, the flow needed trust. Verifying that a booking’s phone number is real, with OTP codes, and why the check must live on the server, is the next post.

