Ошибка Elementor: Класс 'Elementor\Widget_Base' не найден
Я пытаюсь создать базовый виджет в Elementor. При следовании документации разработчика для создания нового виджета возникает следующая ошибка:
Fatal error: Class 'Elementor\Widget_Base' not found
Вот мой код (в основном скопирован из официальной документации)
Основной класс расширения плагина:
<?php
/**
* Plugin Name: Deo Elementor Extension
* Description: Кастомное расширение для Elementor.
* Plugin URI: https://elementor.com/
* Version: 1.0.0
* Author: DeoThemes
* Author URI: https://elementor.com/
* Text Domain: deo-elementor-extension
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Выход, если доступ напрямую
}
/**
* Основной класс расширения Elementor Test
*
* Главный класс, который инициирует и запускает плагин.
*
* @since 1.0.0
*/
final class Elementor_Test_Extension {
/**
* Версия плагина
*
* @since 1.0.0
*
* @var string Версия плагина.
*/
const VERSION = '1.0.0';
/**
* Минимальная версия Elementor
*
* @since 1.0.0
*
* @var string Минимальная версия Elementor, необходимая для работы плагина.
*/
const MINIMUM_ELEMENTOR_VERSION = '2.0.0';
/**
* Минимальная версия PHP
*
* @since 1.0.0
*
* @var string Минимальная версия PHP, необходимая для работы плагина.
*/
const MINIMUM_PHP_VERSION = '7.0';
/**
* Экземпляр
*
* @since 1.0.0
*
* @access private
* @static
*
* @var Elementor_Test_Extension Единственный экземпляр класса.
*/
private static $_instance = null;
/**
* Экземпляр
*
* Гарантирует, что загружен или может быть загружен только один экземпляр класса.
*
* @since 1.0.0
*
* @access public
* @static
*
* @return Elementor_Test_Extension Экземпляр класса.
*/
public static function instance() {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Конструктор
*
* @since 1.0.0
*
* @access public
*/
public function __construct() {
add_action( 'init', [ $this, 'i18n' ] );
add_action( 'plugins_loaded', [ $this, 'init' ] );
}
/**
* Загрузка языкового файла
*
* Загружает файлы локализации плагина.
*
* Вызывается хуком `init`.
*
* @since 1.0.0
*
* @access public
*/
public function i18n() {
load_plugin_textdomain( 'elementor-test-extension' );
}
/**
* Инициализация плагина
*
* Загружает плагин только после загрузки Elementor (и других плагинов).
* Проверяет базовые требования плагина, если проверка не пройдена - не продолжает,
* если все проверки пройдены - загружает файлы, необходимые для работы плагина.
*
* Вызывается хуком `plugins_loaded`.
*
* @since 1.0.0
*
* @access public
*/
public function init() {
// Проверка, установлен и активирован ли Elementor
if ( ! did_action( 'elementor/loaded' ) ) {
add_action( 'admin_notices', [ $this, 'admin_notice_missing_main_plugin' ] );
return;
}
// Проверка требуемой версии Elementor
if ( ! version_compare( ELEMENTOR_VERSION, self::MINIMUM_ELEMENTOR_VERSION, '>=' ) ) {
add_action( 'admin_notices', [ $this, 'admin_notice_minimum_elementor_version' ] );
return;
}
// Проверка требуемой версии PHP
if ( version_compare( PHP_VERSION, self::MINIMUM_PHP_VERSION, '<' ) ) {
add_action( 'admin_notices', [ $this, 'admin_notice_minimum_php_version' ] );
return;
}
// Подключение файлов плагина
$this->includes();
// Регистрация виджетов
add_action( 'elementor/widgets/widgets_registered', [ $this, 'register_widgets' ] );
}
/**
* Уведомление администратора
*
* Предупреждение, когда на сайте не установлен или не активирован Elementor.
*
* @since 1.0.0
*
* @access public
*/
public function admin_notice_missing_main_plugin() {
if ( isset( $_GET['activate'] ) ) unset( $_GET['activate'] );
$message = sprintf(
/* translators: 1: Название плагина 2: Elementor */
esc_html__( '"%1$s" требует "%2$s" быть установленным и активированным.', 'elementor-test-extension' ),
'<strong>' . esc_html__( 'Elementor Test Extension', 'elementor-test-extension' ) . '</strong>',
'<strong>' . esc_html__( 'Elementor', 'elementor-test-extension' ) . '</strong>'
);
printf( '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', $message );
}
/**
* Уведомление администратора
*
* Предупреждение, когда на сайте не соответствует минимальная требуемая версия Elementor.
*
* @since 1.0.0
*
* @access public
*/
public function admin_notice_minimum_elementor_version() {
if ( isset( $_GET['activate'] ) ) unset( $_GET['activate'] );
$message = sprintf(
/* translators: 1: Название плагина 2: Elementor 3: Требуемая версия Elementor */
esc_html__( '"%1$s" требует "%2$s" версии %3$s или выше.', 'elementor-test-extension' ),
'<strong>' . esc_html__( 'Elementor Test Extension', 'elementor-test-extension' ) . '</strong>',
'<strong>' . esc_html__( 'Elementor', 'elementor-test-extension' ) . '</strong>',
self::MINIMUM_ELEMENTOR_VERSION
);
printf( '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', $message );
}
/**
* Уведомление администратора
*
* Предупреждение, когда на сайте не соответствует минимальная требуемая версия PHP.
*
* @since 1.0.0
*
* @access public
*/
public function admin_notice_minimum_php_version() {
if ( isset( $_GET['activate'] ) ) unset( $_GET['activate'] );
$message = sprintf(
/* translators: 1: Название плагина 2: PHP 3: Требуемая версия PHP */
esc_html__( '"%1$s" требует "%2$s" версии %3$s или выше.', 'elementor-test-extension' ),
'<strong>' . esc_html__( 'Elementor Test Extension', 'elementor-test-extension' ) . '</strong>',
'<strong>' . esc_html__( 'PHP', 'elementor-test-extension' ) . '</strong>',
self::MINIMUM_PHP_VERSION
);
printf( '<div class="notice notice-warning is-dismissible"><p>%1$s</p></div>', $message );
}
/**
* Подключение файлов
*
* Загружает основные файлы плагина.
*
* @since 1.0.0
*
* @access public
*/
public function includes() {
require_once( __DIR__ . '/widgets/test-widget.php' );
//require_once( __DIR__ . '/controls/test-control.php' );
}
public function register_widgets() {
\Elementor\Plugin::instance()->widgets_manager->register_widget_type( new \Elementor_oEmbed_Widget() );
}
}
Elementor_Test_Extension::instance();
Класс тестового виджета:
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Выход, если доступ напрямую
}
class Elementor_oEmbed_Widget extends \Elementor\Widget_Base {
/**
* Получить название виджета.
*
* Получает название виджета oEmbed.
*
* @since 1.0.0
* @access public
*
* @return string Название виджета.
*/
public function get_name() {
return 'oembed';
}
/**
* Получить заголовок виджета.
*
* Получает заголовок виджета oEmbed.
*
* @since 1.0.0
* @access public
*
* @return string Заголовок виджета.
*/
public function get_title() {
return __( 'oEmbed', 'plugin-name' );
}
/**
* Получить иконку виджета.
*
* Получает иконку виджета oEmbed.
*
* @since 1.0.0
* @access public
*
* @return string Иконка виджета.
*/
public function get_icon() {
return 'fa fa-code';
}
/**
* Получить категории виджета.
*
* Получает список категорий, к которым принадлежит виджет oEmbed.
*
* @since 1.0.0
* @access public
*
* @return array Категории виджета.
*/
public function get_categories() {
return [ 'general' ];
}
/**
* Регистрация настроек виджета oEmbed.
*
* Добавляет различные поля ввода, позволяющие пользователю изменять и настраивать параметры виджета.
*
* @since 1.0.0
* @access protected
*/
protected function _register_controls() {
$this->start_controls_section(
'content_section',
[
'label' => __( 'Контент', 'plugin-name' ),
'tab' => \Elementor\Controls_Manager::TAB_CONTENT,
]
);
$this->add_control(
'url',
[
'label' => __( 'URL для вставки', 'plugin-name' ),
'type' => \Elementor\Controls_Manager::TEXT,
'input_type' => 'url',
'placeholder' => __( 'https://your-link.com', 'plugin-name' ),
]
);
$this->end_controls_section();
}
/**
* Отображение виджета oEmbed на фронтенде.
*
* Написано на PHP и используется для генерации итогового HTML.
*
* @since 1.0.0
* @access protected
*/
protected function render() {
$settings = $this->get_settings_for_display();
$html = wp_oembed_get( $settings['url'] );
echo '<div class="oembed-elementor-widget">';
echo ( $html ) ? $html : $settings['url'];
echo '</div>';
}
}

У меня была такая же проблема. Перенесите $this->includes(); из метода init в метод register_widgets:
public function init() {
...
// Подключение файлов плагина
// $this->includes(); // <-- удалите эту строку
}
public function register_widgets() {
$this->includes(); // <- поместите сюда
\Elementor\Plugin::instance()->widgets_manager->register_widget_type( new \Elementor_oEmbed_Widget() );
}

Большое спасибо, Фрэнк! Именно это я вчера и обнаружил. Я создал отдельный метод, поместил туда $this->includes, и это сработало. Я опубликовал проблему в репозитории Elementor на Github. Не понимаю, почему другие поставили минусы этому посту – здесь явно что-то не так либо с кодом в документации, либо с ядром. Но репозиторий на Github сейчас отключен из-за DMCA :) В любом случае ваш ответ правильный.

Не приведет ли это к редактированию файлов основной темы ReservoirLabs_v2, что в лучшем случае не позволит обновлять ядро без потери изменений, а в худшем — может сломать другие функции? Пожалуйста, также попробуйте включить объяснение, почему ваш ответ работает и что он пытается достичь.
