Проблемът / Нуждата
Ако вече сте доставили сайт на Elementor и клиент ви попита „Искам уиджет“ съобразени, но без да инсталирате 12 добавки“, вече имате правилния рефлекс: прегледайте кода.
Elementor (безплатен/професионален) предоставя достатъчно стабилен API от куки и събития, за да персонализира правилно конструктора: добавяне на категория джаджи, запазване на персонализирана джаджа, инжектиране на контроли, налагане на стойности по подразбиране, зареждане на скриптове само когато е необходимо и дори добавяне на динамично поле чрез етикет.
Типичната бизнес нужда: да се индустриализират компоненти за многократна употреба (призиви към действие, полета за авторство, продуктови листове, таблици, GDPR банери и др.), като същевременно се запази потребителското изживяване на Elementor. До края ще знаете как да структурирате чист, съвместим мини-плъгин. WordPress 6.9.4+ и PHP 8.1+ и ще имате база за многократна употреба за вашите проекти.
Бързо обобщение
- Създайте мини-плъгин WordPress (не е фрагмент за еднократна употреба), който се интегрира с Elementor, без да нарушаваадминистратор.
- Използвайте правилните куки на Elementor:
elementor/init,elementor/widgets/register,elementor/elements/categories_registered,elementor/frontend/after_register_scripts. - Добавете персонализиран уиджет „Значка“ (заглавие + текст + цвят + икона) с контроли, безопасно рендиране и стилове.
- Добавете динамичен етикет (разширена опция), за да инжектирате стойност от мета данни на потребителя (напр. позиция/роля).
- Зареждайте CSS/JS само ако е наличен уиджет от вашия плъгин (избягва се „зареждане на всичко навсякъде“).
Кога да използвате това решение
- Искате стабилен, версиониран компонент, който може да се използва повторно в множество сайтове (агенция, фрийлансъри, екип).
- Трябва да се придържате към стилово ръководство (цветове, типография, разстояние), без да оставяте 50 „опасни“ опции за клиента.
- Нуждаете се от точно рендериране от предния край, без да разчитате на добавка на трета страна, която може да се промени без предупреждение.
- Искате да подобрите производителността: ресурси, зареждани само когато е необходимо, без „голям пакет“ от джаджи.
- Искате да интегрирате данни от WordPress (мета, опции, ACF/Pods и др.) чрез динамични тагове.
Кога НЕ трябва да използвате това решение
- Необходимостта е чисто визуална и спорадична: a прост Шаблон на Elementor, контейнер и малко CSS може да са достатъчни.
- Нямате контрол върху поддръжката: персонализираната джаджа предполага следване на Elementor (а понякога и на неговите остарели версии).
- Ако искате да „закърпите“ Elementor значително (например, да промените вътрешното поведение на редактора), той рядко е стабилен. Изберете официални разширения или приемете известна степен на технически дълг.
- Вашият клиент използва предимно Gutenberg/blocks: в този случай, персонализиран блок (Block API) често е по-подходящ. Вижте официалната документация: Наръчник за блоков редактор.
Предварителни изисквания / преди започване
- WordPress 6.9.4+ и PHP 8.1+ (в идеалния случай 8.2/8.3 през 2026 г., ако вашият доставчик на хостинг услуги може да се справи).
- Elementor е инсталиран и активиран (безплатната версия е достатъчна за този примерен уиджет). За напреднали динамични тагове често се използва Elementor Pro, но ние се придържаме към публични API, когато е възможно.
- Средата за подготовка и архивирането са от съществено значение, преди да се направят каквито и да е промени. Често съм виждал фрагменти, поставени в продукцията, които предизвикват фатална грешка и заключват администраторския интерфейс.
- Плъгин за регистрационни файлове (или поне
WP_DEBUG_LOG) за четене на PHP грешки.
Полезни препратки към WordPress:
- Plugin Наръчник за разработчици
- Еднократни номера (сигурност)
- wp_enqueue_script ()
- esc_html()
- PHP Ръководство
Наивният подход (и защо да го избягваме)
Класическият подход: поставяне на голямо парче код в functions.php на темата (често без дъщерна тема), запазване на скриптове навсякъде и създаване на инстанции на класове на Elementor при зареждане.
Типичен пример (анти-модел)
<?php
// ❌ Exemple volontairement mauvais : ne copiez pas tel quel.
add_action('init', function () {
// ❌ Elementor n'est pas forcément chargé ici, et cette classe peut ne pas exister.
$widgets_manager = ElementorPlugin::instance()->widgets_manager;
require_once __DIR__ . '/widgets/badge.php';
$widgets_manager->register(new My_Badge_Widget());
// ❌ Charge CSS/JS sur toutes les pages, même si le widget n'est pas utilisé.
wp_enqueue_style('my-badge', get_stylesheet_directory_uri() . '/badge.css');
});
Защо се чупи (често)
- Синхронизиране Elementor все още не беше завършил инициализацията на своите мениджъри по време на
init(в зависимост от версиите/контекста). - Фатална грешка : ако Elementor е деактивиран,
ElementorPluginне съществува. - Изпълнение CSS/JS се зарежда навсякъде, включително на страници, които не използват Elementor.
- поддръжка Кодът е изгубен в темата, невъзможно е да се версионира правилно, нестабилно е при смяна на теми.
Правилният подход — стъпка по стъпка урок
Ще направим мини-плъгин с:
- bootstrap, който проверява дали Elementor е активен,
- специална категория джаджи,
- персонализиран уиджет,
- условно зареждане на активи,
- опционален вариант на „Динамичен етикет“, илюстриращ усъвършенстван филтър/регистър.
Стъпка 1 — Създайте плъгина
Създайте тази папка: wp-content/plugins/bpcab-elementor-hooks/
След това този файл: wp-content/plugins/bpcab-elementor-hooks/bpcab-elementor-hooks.php
Стъпка 2 — Bootstrap + Elementor проверка
Прикачваме нашия код към plugins_loaded тогава чакаме elementor/initКлючовият момент: никога не извиквайте класове на Elementor, докато плъгинът не е готов.
Стъпка 3 — Запазване на категория + уиджет
Elementor предоставя специални действия. На практика те са стабилни в продължение на няколко версии:
elementor/elements/categories_registeredза да добавите категория,elementor/widgets/registerза да запазите уиджет.
Настоявам: избягвайте да използвате кукички „на случаен принцип“ (като init ou wp_loaded) за да докоснете Elementor. Проблемът рядко идва от кода на уиджета, а от момента, в който той се изпълнява.
Стъпка 4 — Заредете CSS/JS в точния момент
Активите се записват чрез elementor/frontend/after_register_styles / elementor/frontend/after_register_scriptsтогава ние Поставяне в опашката само ако уиджетът действително е рендиран.
Стъпка 5 — (По избор) Добавяне на динамичен етикет
Ако използвате Elementor Pro (или ако вашият стек поддържа динамични тагове), персонализираният тагове често е по-чист от шорткод. Вие предоставяте данните, а Elementor обработва инжектирането в своите „динамични“ контроли.
Пълен код
Копирайте и поставете всичко по-долу. Плъгинът е самостоятелен и можете да добавяте джаджи по-късно.
Файл 1 — bpcab-elementor-hooks.php
<?php
/**
* Plugin Name: BPCAB - Personnalisation Elementor par hooks
* Description: Exemple pédagogique : catégorie + widget custom + assets conditionnels + (option) Dynamic Tag.
* Version: 1.0.0
* Requires at least: 6.9
* Requires PHP: 8.1
* Author: BPCAB
* License: GPLv2 or later
*/
declare(strict_types=1);
if (!defined('ABSPATH')) {
exit;
}
final class BPCAB_Elementor_Hooks_Plugin {
public const VERSION = '1.0.0';
public const SLUG = 'bpcab-elementor-hooks';
private static ?self $instance = null;
public static function instance(): self {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
add_action('plugins_loaded', [$this, 'bootstrap']);
}
public function bootstrap(): void {
// Elementor définit généralement ELEMENTOR_VERSION quand il est actif.
if (!defined('ELEMENTOR_VERSION')) {
// Pas d'Elementor : on ne fait rien. Évitez d'afficher une notice agressive en front.
add_action('admin_notices', [$this, 'admin_notice_missing_elementor']);
return;
}
// On attend l'initialisation d'Elementor avant d'appeler ses classes/managers.
add_action('elementor/init', [$this, 'on_elementor_init']);
}
public function admin_notice_missing_elementor(): void {
if (!current_user_can('activate_plugins')) {
return;
}
$plugin_name = esc_html__('BPCAB - Personnalisation Elementor par hooks', 'bpcab');
$message = esc_html__('Elementor doit être activé pour utiliser ce plugin.', 'bpcab');
echo '<div class="notice notice-warning">';
echo '<p><strong>' . $plugin_name . '</strong> — ' . $message . '</p>';
echo '</div>';
}
public function on_elementor_init(): void {
// 1) Catégorie de widgets.
add_action('elementor/elements/categories_registered', [$this, 'register_category']);
// 2) Widgets.
add_action('elementor/widgets/register', [$this, 'register_widgets']);
// 3) Assets : on les enregistre au bon moment côté front.
add_action('elementor/frontend/after_register_styles', [$this, 'register_frontend_styles']);
add_action('elementor/frontend/after_register_scripts', [$this, 'register_frontend_scripts']);
// 4) Option : Dynamic Tag (si l'API est disponible).
add_action('elementor/dynamic_tags/register', [$this, 'register_dynamic_tags']);
}
public function register_category($elements_manager): void {
// $elements_manager est typiquement une instance de ElementorElements_Manager.
$elements_manager->add_category(
'bpcab',
[
'title' => esc_html__('BPCAB', 'bpcab'),
'icon' => 'fa fa-plug',
]
);
}
public function register_widgets($widgets_manager): void {
// Chargement des classes de widgets.
require_once __DIR__ . '/includes/widgets/class-bpcab-widget-badge.php';
// Enregistrement.
$widgets_manager->register(new BPCAB_Widget_Badge());
}
public function register_frontend_styles(): void {
wp_register_style(
'bpcab-badge',
plugins_url('assets/css/badge.css', __FILE__),
[],
self::VERSION
);
}
public function register_frontend_scripts(): void {
wp_register_script(
'bpcab-badge',
plugins_url('assets/js/badge.js', __FILE__),
[],
self::VERSION,
true
);
}
public function register_dynamic_tags($dynamic_tags_manager): void {
// Certains sites n'utilisent pas cette feature : on protège le require.
require_once __DIR__ . '/includes/dynamic-tags/class-bpcab-dynamic-tag-user-position.php';
// Enregistrement du tag.
$dynamic_tags_manager->register(new BPCAB_Dynamic_Tag_User_Position());
}
}
BPCAB_Elementor_Hooks_Plugin::instance();
Файл 2 — includes/widgets/class-bpcab-widget-badge.php
<?php
declare(strict_types=1);
if (!defined('ABSPATH')) {
exit;
}
use ElementorWidget_Base;
use ElementorControls_Manager;
use ElementorIcons_Manager;
final class BPCAB_Widget_Badge extends Widget_Base {
public function get_name(): string {
return 'bpcab_badge';
}
public function get_title(): string {
return esc_html__('Badge (BPCAB)', 'bpcab');
}
public function get_icon(): string {
return 'eicon-badge';
}
public function get_categories(): array {
return ['bpcab'];
}
public function get_keywords(): array {
return ['badge', 'label', 'cta', 'bpcab'];
}
public function get_style_depends(): array {
// Elementor enqueuera ce style seulement si le widget est présent.
return ['bpcab-badge'];
}
public function get_script_depends(): array {
// Idem pour le script.
return ['bpcab-badge'];
}
protected function register_controls(): void {
$this->start_controls_section(
'section_content',
[
'label' => esc_html__('Contenu', 'bpcab'),
'tab' => Controls_Manager::TAB_CONTENT,
]
);
$this->add_control(
'title',
[
'label' => esc_html__('Titre', 'bpcab'),
'type' => Controls_Manager::TEXT,
'default' => esc_html__('Nouveau', 'bpcab'),
'placeholder' => esc_html__('Ex: Nouveau', 'bpcab'),
'label_block' => true,
]
);
$this->add_control(
'text',
[
'label' => esc_html__('Texte', 'bpcab'),
'type' => Controls_Manager::TEXTAREA,
'default' => esc_html__('Offre limitée', 'bpcab'),
'placeholder' => esc_html__('Ex: Offre limitée', 'bpcab'),
'rows' => 3,
]
);
$this->add_control(
'icon',
[
'label' => esc_html__('Icône', 'bpcab'),
'type' => Controls_Manager::ICONS,
'default' => [
'value' => 'fas fa-star',
'library' => 'fa-solid',
],
]
);
$this->end_controls_section();
$this->start_controls_section(
'section_style',
[
'label' => esc_html__('Style', 'bpcab'),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$this->add_control(
'bg_color',
[
'label' => esc_html__('Couleur de fond', 'bpcab'),
'type' => Controls_Manager::COLOR,
'default' => '#111827',
'selectors' => [
'{{WRAPPER}} .bpcab-badge' => 'background-color: {{VALUE}};',
],
]
);
$this->add_control(
'text_color',
[
'label' => esc_html__('Couleur du texte', 'bpcab'),
'type' => Controls_Manager::COLOR,
'default' => '#ffffff',
'selectors' => [
'{{WRAPPER}} .bpcab-badge' => 'color: {{VALUE}};',
],
]
);
$this->add_responsive_control(
'padding',
[
'label' => esc_html__('Padding', 'bpcab'),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => ['px', 'em', 'rem'],
'default' => [
'top' => 12,
'right' => 14,
'bottom' => 12,
'left' => 14,
'unit' => 'px',
],
'selectors' => [
'{{WRAPPER}} .bpcab-badge' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->end_controls_section();
}
protected function render(): void {
$settings = $this->get_settings_for_display();
// Sanitization/escaping : Elementor stocke des valeurs, mais vous devez sortir du HTML propre.
$title = isset($settings['title']) ? sanitize_text_field((string) $settings['title']) : '';
$text = isset($settings['text']) ? wp_kses_post((string) $settings['text']) : '';
// Icône : Elementor fournit Icons_Manager pour rendre proprement.
$icon = $settings['icon'] ?? null;
echo '<div class="bpcab-badge" role="note">';
echo '<div class="bpcab-badge__head">';
if (!empty($icon) && is_array($icon)) {
echo '<span class="bpcab-badge__icon" aria-hidden="true">';
Icons_Manager::render_icon($icon, ['aria-hidden' => 'true']);
echo '</span>';
}
if ($title !== '') {
echo '<strong class="bpcab-badge__title">' . esc_html($title) . '</strong>';
}
echo '</div>';
if ($text !== '') {
// wp_kses_post permet un sous-ensemble HTML (liens, strong, em, etc.).
echo '<div class="bpcab-badge__text">' . $text . '</div>';
}
echo '</div>';
}
}
Файл 3 — includes/dynamic-tags/class-bpcab-dynamic-tag-user-position.php
<?php
declare(strict_types=1);
if (!defined('ABSPATH')) {
exit;
}
use ElementorCoreDynamicTagsTag;
final class BPCAB_Dynamic_Tag_User_Position extends Tag {
public function get_name(): string {
return 'bpcab-user-position';
}
public function get_title(): string {
return esc_html__('Utilisateur : Poste (BPCAB)', 'bpcab');
}
public function get_group(): string {
// Groupe "Site" ou "User" selon votre organisation.
return 'site';
}
public function get_categories(): array {
// Catégorie TEXT pour insertion dans des champs texte.
return [ElementorModulesDynamicTagsModule::TEXT_CATEGORY];
}
protected function register_controls(): void {
// Exemple : choisir une meta key (simple). En prod, vous pourriez proposer une liste.
$this->add_control(
'meta_key',
[
'label' => esc_html__('Meta key utilisateur', 'bpcab'),
'type' => ElementorControls_Manager::TEXT,
'default' => 'position',
'placeholder' => 'position',
]
);
}
public function render(): void {
$user_id = get_current_user_id();
if (!$user_id) {
return;
}
$settings = $this->get_settings();
$meta_key = isset($settings['meta_key']) ? sanitize_key((string) $settings['meta_key']) : 'position';
$value = get_user_meta($user_id, $meta_key, true);
if (!is_scalar($value) || $value === '') {
return;
}
echo esc_html((string) $value);
}
}
Файл 4 — assets/css/badge.css
.bpcab-badge{
display:block;
border-radius:12px;
line-height:1.35;
}
.bpcab-badge__head{
display:flex;
gap:10px;
align-items:center;
}
.bpcab-badge__icon{
display:inline-flex;
}
.bpcab-badge__title{
font-weight:700;
}
.bpcab-badge__text{
margin-top:8px;
opacity:.95;
}
Файл 5 — assets/js/badge.js
(function () {
// Script minimal : exemple de point d'accroche.
// Ici, on ne fait rien de critique. Gardez vos widgets robustes sans JS si possible.
})();
Обяснение на кода
1) Защо плъгин (а не functions.php)?
Плъгинът ви дава ясен жизнен цикъл, активиране/деактивиране, версии и стабилно местоположение за вашите класове. Често съм виждал сайтове на Avada/Divi да се актуализират и малък фрагмент в темата да изчезва или да става несъвместим.
2) Ключовият момент: времето на закачане на куките
plugins_loadedWordPress е заредил плъгините. Можем да проверим дали Elementor е наличен.elementor/initElementor е инициализирал основния си контейнер. Тук добавяте вашите Elementor hooks-и.elementor/widgets/register: получавате мениджъра на уиджети и запазвате класовете си.elementor/elements/categories_registered: декларирате категория, видима в потребителския интерфейс на конструктора.
Тази разбивка избягва класическия бъг: „Класът 'ElementorPlugin' не е намерен“ или „Извикване на членска функция register() при null“.
3) Условно зареждане на активи
Дуетът get_style_depends() / get_script_depends() е недоизползван. И все пак, това е един от най-чистите начини да заредите вашите ресурси само когато Elementor рендира вашата джаджа.
Зад кулисите: Elementor събира зависимостите на джаджите на страницата и запитва съответните манипулатори. Вие просто... wp_register_style() / wp_register_script() в правилното време.
4) Сигурно рендиране: санитизация + екраниране
- влизане Elementor съхранява стойности в базата данни. Все още е необходимо да ги почиствате в зависимост от контекста.
- вилазка :
esc_html()за текст,wp_kses_post()ако разрешите ограничен HTML.
Капанът, който виждам най-често: да излизам директно навън $settings['text'] без wp_kses_post() „Защото е администраторът.“ В сайт с множество автори това се превръща в XSS риск.
5) Динамичен етикет: защо е полезен
Динамичният таг елиминира нуждата от шорткодове в полетата на Elementor. Вие предоставяте данни (потребителски мета данни, опция, ACF поле) и потребителят избира тага в потребителския интерфейс. Това е по-лесно за поддръжка от шорткод, поставен в 30 уиджета.
Варианти и случаи на употреба
Вариант 1 — Принудително „заключени“ стойности (по-малко опции за клиента)
Ако искате да попречите на клиента да променя определени опции, можете да:
- не излагайте контрола (не
add_control), - или да се покаже затворен списък (SELECT),
- или да наложите стойност в
render().
Пример: налагане на CSS клас въз основа на „тип“:
// Dans register_controls()
$this->add_control(
'type',
[
'label' => esc_html__('Type', 'bpcab'),
'type' => Controls_Manager::SELECT,
'default' => 'info',
'options' => [
'info' => esc_html__('Info', 'bpcab'),
'warning' => esc_html__('Alerte', 'bpcab'),
],
]
);
// Dans render()
$type = isset($settings['type']) ? sanitize_key((string) $settings['type']) : 'info';
$type_class = in_array($type, ['info', 'warning'], true) ? 'is-' . $type : 'is-info';
echo '<div class="bpcab-badge ' . esc_attr($type_class) . '">...</div>';
Вариант 2 — Добавяне на контрола за URL адрес и създаване на чиста връзка
Призив към действие с кликаема значка се появява през цялото време. Elementor предоставя контрол за URL адреси с опции „отваряне в нов раздел“ и „nofollow“.
// Contrôle URL
$this->add_control(
'link',
[
'label' => esc_html__('Lien', 'bpcab'),
'type' => Controls_Manager::URL,
'options' => ['url', 'is_external', 'nofollow'],
'default' => [
'url' => '',
],
]
);
// Dans render()
$link = $settings['link'] ?? [];
$url = isset($link['url']) ? esc_url((string) $link['url']) : '';
if ($url) {
$target = !empty($link['is_external']) ? ' target="_blank"' : '';
$rel = !empty($link['nofollow']) ? ' rel="nofollow noopener"' : ' rel="noopener"';
echo '<a class="bpcab-badge" href="' . $url . '"' . $target . $rel . '>...</a>';
return;
}
Забележка: Ако отворите връзка в нов раздел, запазете noopener (охрана).
Вариант 3 — Зареждане на ресурс само на определени страници (още по-строго)
Ако имате сложен скрипт, можете да комбинирате зависимостта на уиджета с условие на WordPress. Например: само на страници (не на членове):
public function register_frontend_scripts(): void {
wp_register_script(
'bpcab-badge',
plugins_url('assets/js/badge.js', __FILE__),
[],
self::VERSION,
true
);
// ⚠️ Ne faites pas wp_enqueue_script ici : Elementor gère l'enqueue via get_script_depends().
// Si vous voulez vraiment empêcher le chargement sur certains contextes, vous pouvez deregister :
if (!is_page()) {
wp_deregister_script('bpcab-badge');
}
}
Рядко го използвам: може да е изненадващо, ако даден уиджет се използва в шаблон, който се показва другаде. Тествайте го старателно.
Съвместимост с Divi 5 / Elementor / Avada
Elementor
- Горният плъгин се интегрира „в“ Elementor, без да зависи от тема.
- Ако използвате шаблони на Elementor (Theme Builder), джаджата остава достъпна навсякъде.
- Активите са условни: добър момент за много натоварени сайтове.
Диви 5
Divi 5 не използва Elementor API. Вашият уиджет няма да се показва в Divi и това е нормално.
Ако целта ви е да използвате повторно един и същ компонент на Divi страници, препоръчвам стратегия „независимо от конструктора“:
- създайте шорткод за WordPress (или по-добре: блок на Gutenberg),
- след това го вмъкнете в Divi чрез модул за код/кратък код,
- и запазете Elementor като „UI overlay“, когато е наличен.
Според моя опит, това е единственият подход, който работи, ако имате парк с множество строители.
Авада (Fusion Builder)
Същата логика важи: Avada няма да използва уиджети на Elementor. Вашият плъгин обаче остава полезен, ако сайтът използва Elementor на някои страници.
За Avada, най-чистият модел е също: шорткод или блок, след това елемент „Кодов блок“ / „Шорткод“ във Fusion Builder.
Проверки след инсталацията
- Активирайте плъгина в Разширения.
- Отворете страница с Elementor.
- В панела с джаджи потърсете категорията БПКАБ след това джаджата Значка (BPCAB).
- Поставете го на страницата, редактирайте заглавието/текста/цветовете и публикувайте.
- На лицевата страна проверете страницата: трябва да видите
bpcab-badge.cssзаредени (а не на страници, които не използват уиджета).
Бърза диагностична диаграма
| симптом | Вероятна причина | проверка | Решение |
|---|---|---|---|
| Категорията BPCAB не се показва | Куката никога не се изпълнява (Елементорът не е зареден) | Проверете това ELEMENTOR_VERSION е дефиниран и Elementor е активен |
Активирайте Elementor, проверете за конфликти/mu-плъгини |
| Фатална грешка „Класът ElementorWidget_Base не е намерен“ | Файлът с уиджета е зареден твърде рано / Elementor е неактивен | Преглед на PHP лога + стека | Изисква се само джаджата в elementor/widgets/register après elementor/init |
| CSS/JS не е зареден | Нерегистрирани манипулатори или лоша кука за регистрация | инспектира wp_head / wp_footer + конзола |
Проверяващият after_register_styles/scripts et get_style_depends() |
| Джаджата се показва, но стиловете са счупени. | Кеширане (плъгин/CDN) или агресивно минифициране | Деактивиране на кеша, изчистване на CDN, тестване в режим на частно сърфиране | Изключване на файлове от кеша/минимизиране, bump версия |
| Динамичният етикет не е намерен | Функцията не е налична (в зависимост от конфигурацията/Pro) или куката не е задействана | Проверете дали панелът „Динамичен“ съществува в текстово поле | Инсталирайте/активирайте Elementor Pro, ако е необходимо, или премахнете секцията с етикети |
Ако това не проработи
- Потвърдете версиите WordPress 6.9.4+, PHP 8.1+, Elementor са актуални. Остаряла версия на PHP причинява грешки на
declare(strict_types=1)или видовете?self. - Активиране на регистриране в
wp-config.php(в етап на подготовка):
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false); - отворено
wp-content/debug.logи потърсете „BPCAB“ или „Elementor“. - Временно деактивиране Плъгини за фрагменти. Вече съм виждал фрагмент „от стар урок за Elementor“, който декларира клас със същото име и причинява фатален конфликт.
- Изчистване на кешовете : кеш на плъгини, кеш на сървъра, CDN, кеш на браузъра. В Elementor, агресивното кеширане може също да запази липсващи ресурси.
- Регенерирайте CSS кода на Elementor (ако вашият сайт използва опцията за генериране на CSS). В Elementor обикновено имате действие за регенериране в настройките за инструменти/производителност.
- Опитайте с неутрална тема (временно): Twenty Twenty-* или лека тема. Темата може да отписва скриптове/стилове.
Често срещани капани и грешки
| Грешка | Причина | Решение |
|---|---|---|
| Кодът е поставен в грешен файл | Добавено в functions.php вместо плъгин |
Създайте плъгин, актуализирайте го и го активирайте/деактивирайте правилно. |
| „Грешка при синтактичен анализ: синтактична грешка“ | Липсваща точка и запетая, допълнителна къдрава скоба, непълно копиране и поставяне | Прегледайте реда, посочен в лога, използвайте IDE с PHP форматиране |
| Неподходящ елемент Hook | Използването на init / wp_loaded за запазване на уиджет |
употреба elementor/init puis elementor/widgets/register |
| „Класът ElementorPlugin не е намерен“ | Elementor е деактивиран или зареден след вашия код | Проверяващият defined('ELEMENTOR_VERSION') и никога преди не се обаждайте на Elementor elementor/init |
| CSS/JS не е зареден | Лош дескриптор, лоша кука или кеш/минификация | Запазване чрез after_register_styles/scripts, декларирайте зависимости чрез get_*_depends()изчистване на кеша |
| Конфликт с имената на класовете | Два плъгина декларират BPCAB_Widget_Badge (или неправилно конфигуриран автозареждащ механизъм) |
Винаги използвайте префикси и именни пространства, ако индустриализирате. |
| Объркване между действие и филтър | Опитвате се да се „върнете“ към акция | Действия: странични ефекти. Филтри: връщат стойност. Прегледайте използвания hook. |
| Директно тестване в производство | Без подготовка, без резервно копие | План за подготовка + архивиране + връщане към предишни версии (деактивиране на плъгина чрез FTP, ако е необходимо) |
| Непоследователни постоянни връзки/шаблони | Тествате върху различен шаблон от този, който се рендира (Theme Builder). | Проверете кой шаблон на Elementor е действително приложен и изчистете кеша. |
Съвети за безопасност, производителност и поддръжка
Сигурност
- Систематично бягство всичко, което се извежда в HTML, трябва да бъде екранирано според контекста (
esc_html,esc_attr,esc_url,wp_kses_post). Референция: WordPress: Валидиране на данни. - Няма опции за „безплатен HTML“ за роли, които не са администратори. В сайтове с множество автори това е XSS вектор.
- Няма изпълнение на PHP чрез уиджет (Изглежда очевидно, но вече съм виждал някои сглобени „кодови джаджи“).
Изпълнение
- Условни активи от
get_style_depends()/get_script_depends(): това е най-доброто съотношение усилия/печалба. - Избягвайте циклични заявки в
render()Ако трябва да заредите данни (публикации, мета данни), кеширайте ги (tranzients/object cache) или ги подгответе чрез оптимизирана заявка. - Минимален CSS : уиджет = малък файл. Ако имате 20, групирайте ги интелигентно (но запазете условността).
поддръжка
- Версия Използвайте плъгина (Git) и маркирайте изданията си. Когато Elementor промени API, ще знаете какво да внедрите.
- Избягвайте „стари“ уроци които използват остарели куки. Ако използвате повторно фрагмент от 2021-2023 г., уверете се, че е съвместим с текущите Elementor и WordPress 6.9.4.
- Подгответе резервна стратегия : ако Elementor е деактивиран, вашият плъгин не би трябвало да „прави нищо“, без да е фатален.
ресурси
- Ръководство за разработчици на плъгини за WordPress
- WordPress Nonces
- WordPress Escaping (сигурност)
- wp_register_style()
- wp_register_script()
- Elementor на WordPress.org
- WordPress Core (GitHub)
- WordPress Core Trac
- Ръководство за PHP
ЧЗВ
Този код работи ли с WordPress 6.9.4?
Да: плъгинът следва стандартните практики на WordPress (hooks, queue) и е насочен към PHP 8.1+. Основният проблем със съвместимостта остава версията на Elementor (поддържайте я актуална).
Защо да не използвате плъгин за фрагменти?
За бърз тест е добре. За многократно използваем уиджет на Elementor, истинският плъгин е по-надежден: контролирано зареждане, организирани файлове, версии и чисто деактивиране, ако се повреди.
Моят уиджет се показва, но не е в правилната категория.
Провери това get_categories() обърни се ['bpcab']и че категорията е регистрирана чрез elementor/elements/categories_registered.
Как да добавя няколко джаджи?
Добавете още файлове към includes/widgets/ и ги запазете в register_widgets()Един файл = един клас.
Как мога да избегна зареждането на JS, ако не ми е нужен?
Изтрий get_script_depends() или върнете празен масив. Поддържайте джаджата функционална без JS, доколкото е възможно.
Можем ли да използваме автозареждащ се (Composer)?
Да, особено ако имате 10+ джаджи. В контекста на WordPress, внимавайте да не насилвате Composer на крайния сайт. Често срещан подход е да се включи PSR-4 автозареждащ механизъм в плъгина.
Защо да използвам wp_kses_post() За текста?
Защото текстовото поле може да съдържа HTML, ако Elementor го позволява (или ако потребителят постави съдържание). wp_kses_post() позволява безопасно подмножество, за разлика от сурово ехо.
Динамичният етикет не се показва: това нормално ли е?
Зависи от конфигурацията на вашия Elementor. Проверете дали потребителският интерфейс „Dynamic“ е наличен за вашите полета. Ако сайтът ви не поддържа динамични тагове, премахнете частта elementor/dynamic_tags/register и свързания файл.
Как мога да тествам правилно, без да повредя редактора?
Тествайте в режим на подготовка, активирайте логване и започнете с минимален уиджет (рендериран + един контрол). Добавяйте контролите един по един. Грешките в Elementor често са безшумни от страна на потребителския интерфейс, но видими в конзолата и PHP лога.
Съвместимо ли е с детска тема Divi/Avada?
Да, защото е плъгин. Уиджетът обаче ще се показва само в Elementor. За Divi/Avada използвайте шорткод или блок, ако искате компонент, който може да се споделя между конструктори.