Problém / Potreba

Ak ste už dodali webovú stránku na Elementore a klient sa vás opýta: „Chcem widget“ na mieru„ale bez inštalácie 12 doplnkov“, už máte správny reflex: prejdite si kód.

Elementor (Free/Pro) poskytuje dostatočne stabilné API s hookmi a udalosťami na správne prispôsobenie nástroja na tvorbu: pridanie kategórie widgetov, uloženie vlastného widgetu, vloženie ovládacích prvkov, vynútenie predvolených hodnôt, načítanie skriptov iba v prípade potreby a dokonca pridanie dynamického poľa prostredníctvom značky.

Typická obchodná potreba: industrializovať opakovane použiteľné komponenty (výzvy na akciu, autorské rámčeky, produktové listy, tabuľky, bannery GDPR atď.) a zároveň zachovať používateľskú skúsenosť Elementoru. Na konci budete vedieť, ako štruktúrovať čistý a kompatibilný mini-plugin. WordPress 6.9.4+ a PHP 8.1+ a budete mať opakovane použiteľnú základňu pre vaše projekty.

Rýchle zhrnutie

  • Vytvorte mini-plugin WordPress (nie je to jednorazový úryvok), ktorý sa integruje s Elementorom bez narušeniaadmin.
  • Použite správne hooky Elementoru: elementor/init, elementor/widgets/register, elementor/elements/categories_registered, elementor/frontend/after_register_scripts.
  • Pridajte si vlastný widget „Odznak“ (názov + text + farba + ikona) s ovládacími prvkami, bezpečným vykresľovaním a štýlmi.
  • Pridajte dynamickú značku (rozšírená možnosť) na vloženie hodnoty z metaúdajov používateľa (napr. pozícia/rola).
  • CSS/JS načítajte iba v prípade, že je k dispozícii widget z vášho pluginu (zabráni sa tak „načítaniu všetkého všade“).

Kedy použiť toto riešenie

  • Chcete stabilný komponent s rôznymi verziami, ktorý je možné opätovne použiť na viacerých miestach (agentúra, freelancer, tím).
  • Musíte sa držať štýlového sprievodcu (farby, typografia, medzery) bez toho, aby ste klientovi nechali 50 „nebezpečných“ možností.
  • Potrebujete presné vykresľovanie front-endu bez toho, aby ste sa spoliehali na doplnok tretej strany, ktorý sa môže zmeniť bez varovania.
  • Chcete zlepšiť výkon: prvky načítané iba v prípade potreby, žiadny „veľký balík“ widgetov.
  • Chcete integrovať dáta WordPressu (meta, možnosti, ACF/Pody atď.) prostredníctvom dynamických značiek.

Kedy toto riešenie NEPOUŽÍVAŤ

  • Potreba je čisto vizuálna a príležitostná: a proces Šablóna Elementoru, kontajner a trochu CSS môže stačiť.
  • Nemáte kontrolu nad údržbou: vlastný widget znamená dodržiavanie Elementoru (a niekedy aj jeho zastaraných verzií).
  • Ak chcete Elementor rozsiahlo „záplatovať“ (napr. upraviť vnútorné správanie editora), zriedkakedy je stabilný. Zvoľte si oficiálne rozšírenia alebo akceptujte určitú mieru technického dlhu.
  • Váš klient primárne používa Gutenberg/blocks: v tomto prípade je často vhodnejší vlastný blok (Block API). Pozrite si oficiálnu dokumentáciu: Príručka editora blokov.

Predpoklady / pred začatím

  • WordPress 6.9.4+ a PHP 8.1+ (ideálne 8.2/8.3 v roku 2026, ak váš poskytovateľ hostingu dokáže držať krok).
  • Elementor je nainštalovaný a aktivovaný (pre tento príklad widgetu postačuje bezplatná verzia). Pre pokročilé dynamické značky sa často používa Elementor Pro, ale vždy, keď je to možné, sa držíme verejných API.
  • Pred vykonaním akýchkoľvek zmien je nevyhnutné vytvoriť testovacie prostredie a zálohu. Často som videl úryvky kódu vložené do produkčného prostredia, ktoré spustili fatálnu chybu a zablokovali administrátorské rozhranie.
  • Plugin pre protokoly (alebo aspoň WP_DEBUG_LOG) na čítanie chýb PHP.

Užitočné referencie pre WordPress:

Naivný prístup (a prečo sa mu vyhnúť)

Klasický prístup: vložiť veľký kus kódu do functions.php témy (často bez podradenej témy), ukladať skripty všade a pri načítaní vytvárať inštancie tried Elementoru.

Typický príklad (anti-vzor)

<?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');
});

Prečo sa to (často) láme

  • Načasovanie Elementor v čase ešte nedokončil inicializáciu svojich manažérov init (v závislosti od verzií/kontextov).
  • Fatálna chyba ak je Elementor vypnutý, ElementorPlugin neexistuje.
  • výkon CSS/JS sa načítava všade, vrátane stránok, ktoré nepoužívajú Elementor.
  • údržba Kód stratený v téme, nemožné správne verziovať, krehké pri zmene tém.

Správny prístup – podrobný návod

Vytvoríme mini plugin s:

  • bootstrap, ktorý kontroluje, či je Elementor aktívny,
  • špecializovaná kategória widgetov,
  • vlastný widget,
  • podmienené zaťaženie majetku,
  • voliteľný variant „Dynamický tag“ na ilustráciu pokročilého filtra/registra.

Krok 1 – Vytvorenie doplnku

Vytvorte tento priečinok: wp-content/plugins/bpcab-elementor-hooks/

Potom tento súbor: wp-content/plugins/bpcab-elementor-hooks/bpcab-elementor-hooks.php

Krok 2 – Overenie Bootstrapu + Elementoru

Pripájame náš kód k plugins_loaded potom čakáme elementor/initKľúčový bod: nikdy nevolajte triedy Elementoru, kým nie je plugin pripravený.

Krok 3 – Uložte kategóriu + widget

Elementor sprístupňuje špecializované akcie. V praxi sú tieto stabilné už niekoľko verzií:

  • elementor/elements/categories_registered pridať kategóriu,
  • elementor/widgets/register uložiť widget.

Trvám na tom: vyhnite sa používaniu háčikov „náhodne“ (ako napríklad init ou wp_loaded) na dotyk Elementoru. Problém zriedkakedy pramení z kódu widgetu, ale skôr z okamihu jeho spustenia.

Krok 4 – Načítajte CSS/JS v správnom čase

Majetok sa zaznamenáva prostredníctvom elementor/frontend/after_register_styles / elementor/frontend/after_register_scriptspotom my Enqueue iba ak je widget skutočne vykreslený.

Krok 5 – (Voliteľné) Pridajte dynamickú značku

Ak používate Elementor Pro (alebo ak váš stack podporuje dynamické tagy), vlastný tag je často čistejší ako shortcode. Vy sprístupníte dáta a Elementor sa postará o ich vkladanie do svojich „dynamických“ ovládacích prvkov.

Úplný kód

Skopírujte a vložte všetko nižšie. Plugin je samostatný a widgety môžete pridať neskôr.

Súbor 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();

Súbor 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>';
	}
}

Súbor 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);
	}
}

Súbor 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;
}

Súbor 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.
})();

Vysvetlenie kódu

1) Prečo plugin (a nie functions.php)?

Plugin vám poskytuje jasný životný cyklus, aktiváciu/deaktiváciu, verzovanie a stabilné umiestnenie pre vaše triedy. Často som videl aktualizované stránky Avada/Divi a malý úryvok v téme zmizol alebo sa stal nekompatibilným.

2) Kľúčový bod: načasovanie háčikov

  • plugins_loaded WordPress nahral pluginy. Môžeme skontrolovať, či je tam Elementor.
  • elementor/init Elementor inicializoval svoj hlavný kontajner. Tu pridáte svoje hooky Elementoru.
  • elementor/widgets/register : dostanete správcu widgetov a uložíte si svoje triedy.
  • elementor/elements/categories_registered : deklarujete kategóriu viditeľnú v používateľskom rozhraní nástroja na tvorbu.

Toto rozdelenie sa vyhýba klasickej chybe: „Trieda 'ElementorPlugin' sa nenašla“ alebo „Volanie členskej funkcie register() pri hodnote null“.

3) Podmienené načítanie aktív

Duo get_style_depends() / get_script_depends() je nedostatočne využívaný. Napriek tomu je to jeden z najčistejších spôsobov, ako načítať vaše dáta iba vtedy, keď Elementor vykreslí váš widget.

V zákulisí: Elementor zhromažďuje závislosti widgetov na stránke a dotazuje sa na zodpovedajúce úchyty. Jednoducho... wp_register_style() / wp_register_script() v správnom čase.

4) Bezpečné vykresľovanie: sanitizácia + escaping

  • vstup Elementor ukladá hodnoty do databázy. V závislosti od kontextu ich však treba vyčistiť.
  • výjazd : esc_html() pre text, wp_kses_post() ak povolíte obmedzený HTML.

Pasca, ktorú vidím najčastejšie: ísť rovno von $settings['text'] sans wp_kses_post() „Pretože je to administrátor.“ Na stránke s viacerými autormi sa to stáva rizikom XSS.

5) Dynamický tag: prečo je užitočný

Dynamický tag eliminuje potrebu krátkych kódov v poliach Elementoru. Vy sprístupníte údaje (metadáta používateľa, možnosť, pole ACF) a používateľ vyberie tag v používateľskom rozhraní. Toto je jednoduchšie vložiť ako krátky kód do 30 widgetov.

Varianty a prípady použitia

Variant 1 – Vynútenie „uzamknutých“ hodnôt (menej možností pre zákazníka)

Ak chcete zákazníkovi zabrániť v zmene určitých možností, môžete:

  • neodhaľujte ovládanie (nie add_control),
  • alebo zobraziť uzavretý zoznam (SELECT),
  • alebo zaviesť hodnotu v render().

Príklad: zavedenie CSS triedy na základe „typu“:

// 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>';

Variant 2 – Pridajte ovládací prvok URL a vytvorte čistý odkaz

Klikateľný odznak s výzvou na akciu sa zobrazuje neustále. Elementor poskytuje ovládací prvok URL s možnosťami „otvoriť na novej karte“ a „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;
}

Poznámka: Ak otvoríte odkaz na novej karte, ponechajte noopener (bezpečnosť).

Variant 3 – Načítanie podkladu iba na určitých stránkach (ešte prísnejšie)

Ak máte zložitý skript, môžete skombinovať závislosť widgetu s podmienkou WordPressu. Napríklad: iba na stránkach (nie na tovar):

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');
	}
}

Používam ho zriedka: môže byť prekvapujúce, ak sa widget použije v šablóne, ktorá sa zobrazuje inde. Dôkladne ho otestujte.

Kompatibilita s Divi 5 / Elementor / Avada

Elementor

  • Vyššie uvedený plugin sa integruje „do“ Elementoru bez závislosti od témy.
  • Ak používate šablóny Elementor (Theme Builder), widget zostáva dostupný všade.
  • Prostriedky sú podmienené: dobrý postreh na veľmi rušných stránkach.

Divi 5

Divi 5 nepoužíva rozhranie Elementor API. Váš widget sa v Divi nezobrazí a to je normálne.

Ak je vaším cieľom opätovne použiť rovnaký komponent na stránkach Divi, odporúčam stratégiu „bez ohľadu na tvorcu“:

  • vytvorte shortcode pre WordPress (alebo lepšie: blok Gutenberg),
  • potom ho vložte do Divi pomocou modulu Code/Shortcode,
  • a ponechajte Elementor ako „prekrytie používateľského rozhrania“, keď je prítomný.

Podľa mojich skúseností je to jediný prístup, ktorý funguje, ak máte park s viacerými staviteľmi.

Avada (výrobca fúzií)

Platí rovnaká logika: Avada nebude používať widgety Elementoru. Váš plugin však zostáva užitočný, ak web používa Elementor na niektorých stránkach.

Pre Avada je najčistejší vzor tiež: krátky kód alebo blok, potom prvok „Blok kódu“ / „Krátky kód“ vo Fusion Builderi.

Kontroly po inštalácii

  1. Aktivujte plugin v Rozšírenie.
  2. Otvorte stránku pomocou Elementoru.
  3. V paneli widgetov vyhľadajte kategóriu BPCAB potom widget Odznak (BPCAB).
  4. Umiestnite to na stránku, upravte názov/text/farby a publikujte.
  5. Na prednej strane skontrolujte stránku: mali by ste vidieť bpcab-badge.css načítané (a nie na stránkach, ktoré nepoužívajú widget).

Rýchla diagnostická tabuľka

symptóm Príčina pravdepodobná overenie Riešenie
Kategória BPCAB sa nezobrazuje Hook sa nikdy nevykonal (Elementor sa nenačítal) Skontrolujte, či ELEMENTOR_VERSION je definovaný a Elementor je aktívny Aktivujte Elementor, skontrolujte konflikty/mu-pluginy
Závažná chyba „Trieda ElementorWidget_Base sa nenašla“ Súbor widgetu bol načítaný príliš skoro / Elementor je neaktívny Zobraziť protokol PHP + stopu zásobníka Vyžadovať iba widget v elementor/widgets/register po elementor/init
CSS/JS nie je načítaný Neregistrované úchyty alebo chybný registračný hook preskúmať wp_head / wp_footer + konzola skontrolovať after_register_styles/scripts et get_style_depends()
Widget sa zobrazuje, ale štýly sú poškodené. Ukladanie do vyrovnávacej pamäte (plugin/CDN) alebo agresívna minifikácia Vypnúť vyrovnávaciu pamäť, vymazať CDN, otestovať v režime súkromného prehliadania Vylúčiť súbory z vyrovnávacej pamäte/minifikácie, zväčšiť verziu
Dynamická značka sa nenašla Funkcia nie je k dispozícii (v závislosti od konfigurácie/Pro) alebo sa neaktivoval hák Skontrolujte, či sa v textovom poli nachádza panel „Dynamický“ V prípade potreby nainštalujte/aktivujte Elementor Pro alebo odstráňte sekciu so značkami

Ak to nefunguje

  1. Potvrďte verzie WordPress 6.9.4+, PHP 8.1+, Elementor aktualizovaný. Zastaraná verzia PHP spôsobuje chyby na declare(strict_types=1) alebo typy ?self.
  2. Povoliť protokolovanie v wp-config.php (v štádiu prípravy):

    define('WP_DEBUG', true);

    define('WP_DEBUG_LOG', true);

    define('WP_DEBUG_DISPLAY', false);
  3. otvorené wp-content/debug.log a vyhľadajte „BPCAB“ alebo „Elementor“.
  4. Dočasne deaktivovať Pluginy s úryvkami kódu. Už som videl úryvok kódu „zo starého tutoriálu Elementoru“, ktorý deklaroval triedu s rovnakým názvom a spôsobil fatálny konflikt.
  5. Vymazať vyrovnávaciu pamäť : vyrovnávacia pamäť pluginov, vyrovnávacia pamäť servera, CDN, vyrovnávacia pamäť prehliadača. V Elementore môže agresívne ukladanie do vyrovnávacej pamäte tiež zachovať chýbajúce prvky.
  6. Obnovte CSS kód Elementoru (ak vaša stránka používa možnosť generovania CSS). V Elementore máte zvyčajne akciu regenerácie v nastaveniach nástrojov/výkonu.
  7. Skúste to s neutrálnou témou (dočasné): Twenty Twenty-* alebo odľahčená téma. Téma dokáže zrušiť registráciu skriptov/štýlov.

Časté úskalia a chyby

Chyba Spôsobiť Riešenie
Kód vložený do nesprávneho súboru Pridané v functions.php namiesto pluginu Vytvorte plugin, nastavte jeho verziu a správne ho aktivujte/deaktivujte
„Chyba pri analýze: syntaktická chyba“ Chýbajúca bodkočiarka, zložená zátvorka navyše, neúplné kopírovanie a vkladanie Skontrolujte riadok uvedený v protokole, použite IDE s formátovaním PHP
Nevhodné pre háčiky Elementor Použitie init / wp_loaded uložiť widget použitie elementor/init potom elementor/widgets/register
„Trieda ElementorPlugin sa nenašla“ Elementor bol zakázaný alebo načítaný po zadaní kódu skontrolovať defined('ELEMENTOR_VERSION') a nikdy predtým nevolajte Elementoru elementor/init
CSS/JS sa nenačítal Zlý handle, zlý hook alebo vyrovnávacia pamäť/minifikacia Uložiť cez after_register_styles/scripts, deklarovať závislosti prostredníctvom get_*_depends()vymazať vyrovnávaciu pamäť
Konflikt názvov tried Dva pluginy deklarujú BPCAB_Widget_Badge (alebo nesprávne nakonfigurovaný automatický načítač) Ak industrializujete, vždy používajte predpony a menné priestory.
Zmätok medzi akciou a filtrom Snažíte sa „vrátiť“ k akcii Akcie: vedľajšie účinky. Filtre: vracajú hodnotu. Skontrolujte použitý hook.
Priame testovanie vo výrobe Žiadne stagingové riešenia, žiadne zálohovanie Plán prípravy + zálohovania + vrátenia zmien (deaktivácia pluginu cez FTP, ak je to potrebné)
Nekonzistentné trvalé odkazy/šablóny Testujete na inej šablóne, ako je tá, ktorá je vykreslená (Tvorca tém). Skontrolujte, ktorá šablóna Elementoru je skutočne použitá, a vymažte vyrovnávaciu pamäť.

Tipy na bezpečnosť, výkon a údržbu

Zabezpečenie

  • Systematický útek všetko, čo sa vypíše v HTML, musí byť escapované podľa kontextu (esc_html, esc_attr, esc_url, wp_kses_post). Referencia: WordPress: Overovanie údajov.
  • Žiadne možnosti „bezplatného HTML“ pre neadministrátorské role. Na stránkach s viacerými autormi je to vektor XSS.
  • Žiadne spustenie PHP cez widget (Zdá sa to samozrejmé, ale už som videl nejaké poskladané „kódové widgety“).

výkon

  • Podmienené aktíva via get_style_depends() / get_script_depends() je to najlepší pomer úsilia a zisku.
  • Vyhnite sa cyklickým požiadavkám v render()Ak potrebujete načítať dáta (príspevky, meta), uložte ich do vyrovnávacej pamäte (vyrovnávacia pamäť prechodných údajov/vyrovnávacia pamäť objektov) alebo ich pripravte pomocou optimalizovaného dotazu.
  • Minimálne CSS : widget = malý súbor. Ak ich máte 20, inteligentne ich zoskupte (ale zachovajte podmienenosť).

údržba

  • Verzia Použite plugin (Git) a označte svoje vydania. Keď Elementor zmení API, budete vedieť, čo máte nasadiť.
  • Vyhnite sa „starým“ návodom ktoré používajú zastarané hooky. Ak znovu používate úryvok z rokov 2021 – 2023, uistite sa, že je kompatibilný so súčasným Elementorom a WordPressom 6.9.4.
  • Pripravte si záložnú stratégiu Ak je Elementor vypnutý, váš doplnok by nemal „robiť nič“ bez toho, aby bol fatálny.

zdroje

Často kladené otázky

Funguje tento kód s WordPressom 6.9.4?

Áno: plugin sa riadi štandardnými postupmi WordPressu (hooky, zaraďovanie do frontu) a je určený pre PHP 8.1+. Hlavným problémom s kompatibilitou zostáva verzia Elementoru (udržiavajte ju aktualizovanú).

Prečo nepoužiť plugin na úryvky?

Pre rýchly test je to v poriadku. Pre opakovane použiteľný widget Elementoru je skutočný plugin spoľahlivejší: kontrolované načítavanie, organizované súbory, verzovanie a čistá deaktivácia, ak sa pokazí.

Môj widget sa zobrazuje, ale nie je v správnej kategórii.

Skontrolujte, či get_categories() otoč sa ['bpcab']a že kategória je registrovaná prostredníctvom elementor/elements/categories_registered.

Ako pridám viacero widgetov?

Pridať ďalšie súbory do includes/widgets/ a uložte ich do register_widgets()Jeden súbor = jedna trieda.

Ako sa môžem vyhnúť načítaniu JS, ak ho nepotrebujem?

Odstrániť get_script_depends() alebo vrátiť prázdne pole. Udržujte widget funkčný bez JS čo najviac.

Dá sa použiť automatický načítač (Composer)?

Áno, najmä ak máte viac ako 10 widgetov. V kontexte WordPressu dávajte pozor, aby ste nevynútili používanie Composera na finálnej stránke. Bežným prístupom je zahrnutie automatického načítavania PSR-4 do pluginu.

Prečo používať wp_kses_post() Kvôli textu?

Pretože textové pole môže obsahovať HTML, ak to Elementor umožňuje (alebo ak používateľ vloží obsah). wp_kses_post() umožňuje bezpečnú podmnožinu, na rozdiel od surovej ozveny.

Dynamický tag sa nezobrazuje: je to normálne?

Záleží to od konfigurácie vášho Elementoru. Skontrolujte, či je pre vaše polia k dispozícii „dynamické“ používateľské rozhranie. Ak vaša stránka nepodporuje dynamické značky, odstráňte túto časť elementor/dynamic_tags/register a pridružený súbor.

Ako môžem správne testovať bez toho, aby som porušil editor?

Otestujte v režime staging, povoľte logovanie a začnite s minimálnym widgetom (vykreslený + jeden ovládací prvok). Ovládacie prvky pridávajte jeden po druhom. Chyby Elementoru sú často na strane používateľského rozhrania tiché, ale viditeľné v konzole a PHP logu.

Je kompatibilný s podradenou témou Divi/Avada?

Áno, pretože ide o plugin. Widget sa však zobrazí iba v Elementore. V Divi/Avada použite shortcode alebo blok, ak chcete komponent, ktorý je možné zdieľať medzi tvorcami.