הבעיה / הצורך
אם כבר סיפקתם אתר אלמנטור ולקוח שואל אתכם "אני רוצה ווידג'ט" שנעשו למדוד, אבל בלי להתקין 12 תוספים”, כבר יש לך את הרפלקס הנכון: עברו על הקוד.
אלמנטור (חינם/מקצועי) חושף API יציב מספיק של וויג'טים ואירועים כדי להתאים אישית כראוי את הבונה: הוספת קטגוריה של ווידג'טים, שמירת ווידג'ט מותאם אישית, הזרקת פקדים, כפיית ערכי ברירת מחדל, טעינת סקריפטים רק בעת הצורך, ואפילו הוספת שדה דינמי באמצעות תג.
הצורך העסקי הטיפוסי: תעשייה של רכיבים רב פעמיים (קריאה לפעולה, תיבות כתיבה, דפי מוצר, טבלאות, באנרים של GDPR וכו') תוך שמירה על חוויית המשתמש של אלמנטור. בסוף, תדעו כיצד לבנות מיני-תוסף נקי ותואם. וורדפרס 6.9.4+ ו-PHP 8.1+, ויהיה לכם בסיס רב פעמי לפרויקטים שלכם.
סיכום קצר
- צור מיני-תוסף וורדפרס (לא קטע חד פעמי) שמשתלב עם אלמנטור מבלי לשבור אתמנהל.
- השתמשו בווים הנכונים של אלמנטור:
elementor/init,elementor/widgets/register,elementor/elements/categories_registered,elementor/frontend/after_register_scripts. - הוסף ווידג'ט "תג" מותאם אישית (כותרת + טקסט + צבע + סמל) עם פקדים, רינדור בטוח וסגנונות.
- הוסף תג דינמי (אפשרות מתקדמת) כדי להזריק ערך ממטא המשתמש (למשל, תפקיד/מיקום).
- טען CSS/JS רק אם קיים ווידג'ט מהתוסף שלך (מונע "טעינת הכל בכל מקום").
מתי להשתמש בפתרון זה
- אתם רוצים רכיב יציב עם גרסאות שניתן לעשות בו שימוש חוזר באתרים מרובים (סוכנות, פרילנסר, צוות).
- עליכם לדבוק במדריך סגנון (צבעים, טיפוגרפיה, מרווחים) מבלי להשאיר 50 אפשרויות "מסוכנות" ללקוח.
- אתם זקוקים לרינדור קדמי מדויק מבלי להסתמך על תוסף של צד שלישי שיכול להשתנות ללא אזהרה.
- אתם רוצים לשפר את הביצועים: נכסים נטענים רק בעת הצורך, בלי "חבילה גדולה" של ווידג'טים.
- אתם רוצים לשלב נתוני וורדפרס (מטא, אפשרויות, ACF/Pods וכו') באמצעות תגיות דינמיות.
מתי לא להשתמש בפתרון זה
- הצורך הוא ויזואלי בלבד ומזדמן: א. פשוט תבנית אלמנטור, קונטיינר וקצת CSS עשויים להספיק.
- אין לך שליטה על התחזוקה: ווידג'ט מותאם אישית מרמז על מעקב אחר אלמנטור (ולפעמים על הוצאת האפליקציות שלו מהשימוש).
- אם אתם רוצים "לתקן" את אלמנטור באופן נרחב (למשל, לשנות את ההתנהגות הפנימית של העורך), הוא לעיתים רחוקות יציב. בחרו בהרחבות רשמיות, או קבלו מידה מסוימת של חוב טכני.
- הלקוח שלך משתמש בעיקר ב-Gutenberg/blocks: במקרה זה, בלוק מותאם אישית (Block API) לרוב מתאים יותר. עיין בתיעוד הרשמי: מדריך עורך בלוק.
דרישות מוקדמות / לפני שמתחילים
- וורדפרס 6.9.4+ ו-PHP 8.1+ (רצוי 8.2/8.3 בשנת 2026 אם ספק האירוח שלכם יכול לעמוד בקצב).
- Elementor מותקן ומופעל (הגרסה החינמית מספיקה לדוגמה זו של הווידג'ט). עבור תגיות דינמיות מתקדמות, Elementor Pro משמש לעתים קרובות, אך אנו דבקים בממשקי API ציבוריים ככל האפשר.
- סביבת בימוי וגיבוי חיוניים לפני ביצוע שינויים כלשהם. ראיתי לעתים קרובות קטעי טקסט מודבקים למצב הייצור שגורמים לשגיאה חמורה ונועלים את ממשק הניהול.
- תוסף יומני רישום (או לפחות
WP_DEBUG_LOG) כדי לקרוא שגיאות PHP.
מקורות שימושיים לוורדפרס:
הגישה הנאיבית (ומדוע להימנע ממנה)
הגישה הקלאסית: הדבקת קטע קוד גדול לתוך functions.php של ערכת הנושא (לעתים קרובות ללא ערכת נושא של צאצאים), לשמור סקריפטים בכל מקום, וליצור מופעים של מחלקות אלמנטור בעת הטעינה.
דוגמה אופיינית (אנטי-דפוס)
<?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');
});
למה זה נשבר (לעתים קרובות)
- תזמון אלמנטור טרם סיימה לאתחל את המנהלים שלה בזמן
init(בהתאם לגרסאות/הקשרים). - שגיאה חמורה אם אלמנטור מושבת,
ElementorPluginלא קיים. - ביצוע CSS/JS נטען בכל מקום, כולל בדפים שאינם משתמשים באלמנטור.
- תחזוקה : קוד אבוד בערכת נושא, בלתי אפשרי לגרסה נכונה, שביר בעת החלפת ערכות נושא.
הגישה הנכונה - מדריך שלב אחר שלב
אנחנו הולכים ליצור מיני-תוסף, עם:
- 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הנקודה המרכזית: לעולם אל תקראו לקלאסים של אלמנטור עד שהתוסף מוכן.
שלב 3 - שמירת קטגוריה + ווידג'ט
אלמנטור חושף פעולות ייעודיות. בפועל, אלו היו יציבות עבור מספר גרסאות:
elementor/elements/categories_registeredכדי להוסיף קטגוריה,elementor/widgets/registerכדי לשמור ווידג'ט.
אני מתעקש: הימנעו משימוש בווים "באופן אקראי" (כמו init ou wp_loaded) לגעת באלמנטור. הבעיה נובעת לעיתים רחוקות מהקוד של הווידג'ט, אלא מהרגע שהוא מבוצע.
שלב 4 - טעינת CSS/JS בזמן הנכון
נכסים נרשמים באמצעות elementor/frontend/after_register_styles / elementor/frontend/after_register_scripts, אז אנחנו enqueue רק אם הווידג'ט בפועל מעובד.
שלב 5 — (אופציונלי) הוסף תג דינמי
אם אתם משתמשים ב-Elementor Pro (או אם ה-stack שלכם תומך בתגיות דינמיות), תג מותאם אישית לרוב נקי יותר מקוד קצר. אתם חושפים את הנתונים, ו-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 — כולל/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_loadedוורדפרס טעינה את התוספים. נוכל לבדוק אם אלמנטור נמצא שם.elementor/initאלמנטור אותחל את הקונטיינר הראשי שלו. כאן מוסיפים את ה-hooks של אלמנטור.elementor/widgets/registerאתה מקבל את מנהל הווידג'טים ואתה שומר את השיעורים שלך.elementor/elements/categories_registeredאתה מצהיר על קטגוריה הנראית בממשק המשתמש של הבונה.
פירוט זה נמנע מהבאג הקלאסי: "המחלקה 'ElementorPlugin' לא נמצאה" או "קריאה לפונקציית member register() על null".
3) טעינה מותנית של נכסים
הצמד get_style_depends() / get_script_depends() אינו מנוצל מספיק. ובכל זאת, זוהי אחת הדרכים הנקיות ביותר לטעון את הנכסים שלך רק כאשר Elementor מעבד את הווידג'ט שלך.
מאחורי הקלעים: אלמנטור אוסף את התלויות של הווידג'טים בדף ומבצע שאילתה על ה-handles המתאימים. אתה פשוט... wp_register_style() / wp_register_script() בזמן הנכון.
4) רינדור מאובטח: חיטוי + בריחה
- כניסה אלמנטור שומר ערכים במסד הנתונים. עדיין צריך לנקות אותם בהתאם להקשר.
- יציאה :
esc_html()עבור טקסט,wp_kses_post()אם אתם מאפשרים HTML מוגבל.
המלכודת שאני רואה הכי הרבה: לצאת ישר החוצה $settings['text'] Sans 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 ויצירת קישור נקי
קריאה לפעולה (CTA) עם תג שניתן ללחוץ עליו מופיעה כל הזמן. אלמנטור מספק בקרת 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 - טעינת נכס רק בדפים מסוימים (אפילו מחמירה יותר)
אם יש לכם סקריפט מורכב, תוכלו לשלב את התלות של הווידג'ט עם תנאי וורדפרס. לדוגמה: רק בדפים (לא ב...) מאמרים):
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 (בונה ערכות נושא), הווידג'ט נשאר זמין בכל מקום.
- הנכסים מותנים: נקודה טובה באתרים עמוסים מאוד.
Divi 5
Divi 5 לא משתמש ב-API של Elementor. הווידג'ט שלך לא יופיע ב-Divi, וזה נורמלי.
אם המטרה שלכם היא לעשות שימוש חוזר באותו רכיב בדפי Divi, אני ממליץ על אסטרטגיה "שאינה תלויה בבונה":
- צור קוד קצר (או טוב יותר: בלוק גוטנברג) בוורדפרס,
- לאחר מכן הכנס אותו ל-Divi דרך מודול Code/Shortcode,
- ולשמור את Elementor כ"שכבת-על של ממשק משתמש" כאשר היא קיימת.
מניסיוני, זוהי הגישה היחידה שעובדת אם יש לכם פארק עם מספר בונים.
אבדה (בונה פיוז'ן)
אותו היגיון חל: Avada לא תשתמש בווידג'טים של Elementor. עם זאת, התוסף שלך יישאר שימושי אם האתר משתמש ב-Elementor בחלק מהדפים.
עבור Avada, התבנית הנקי ביותר היא גם: קוד קצר או בלוק, ואז אלמנט "Code Block" / "Shortcode" ב-Fusion Builder.
בדיקות לאחר ההתקנה
- הפעל את התוסף ב רחבות.
- פתח דף עם אלמנטור.
- בחלונית הווידג'טים, חפשו את הקטגוריה BPCAB ואז הווידג'ט תג (BPCAB).
- מקם אותו בדף, ערוך את הכותרת/טקסט/צבעים ופרסם.
- בחזית, בדקו את הדף: אתם אמורים לראות
bpcab-badge.cssנטען (ולא בדפים שאינם משתמשים בווידג'ט).
תרשים אבחון מהיר
| סימפטום | סיבה סבירה | אימות | פתרון |
|---|---|---|---|
| קטגוריית BPCAB אינה מופיעה | הוק מעולם לא בוצע (אלמנטור לא נטען) | בדוק ש ELEMENTOR_VERSION מוגדר, ואלמנטור פעיל |
הפעל את Elementor, בדוק אם יש התנגשויות/mu-plugins |
| שגיאה חמורה "המחלקה ElementorWidget_Base לא נמצאה" | קובץ הווידג'ט נטען מוקדם מדי / אלמנטור אינו פעיל | צפה ביומן PHP + מעקב אחר מחסנית | נדרש רק הווידג'ט ב elementor/widgets/register האפרה elementor/init |
| CSS/JS לא נטען | ידיות לא רשומות או וו רישום פגום | לבדוק wp_head / wp_footer + קונסולה |
מאמת after_register_styles/scripts et get_style_depends() |
| הווידג'ט מוצג, אבל הסגנונות שבורים. | אחסון במטמון (תוסף/CDN) או מזעור אגרסיבי | השבתת מטמון, ניקוי CDN, בדיקה במצב גלישה פרטית | אי הכללת קבצים מהמטמון/מיניפי, גרסת bump |
| תג דינמי לא נמצא | התכונה אינה זמינה (בהתאם לתצורה/Pro) או שה-Hook לא הופעל | בדוק אם החלונית "דינמית" קיימת בשדה טקסט | התקן/הפעל את Elementor Pro במידת הצורך, או הסר את מקטע התגיות |
אם זה לא עובד
- אשר את הגרסאות וורדפרס 6.9.4+, PHP 8.1+, אלמנטור מעודכן. גרסת PHP מיושנת גורמת לשגיאות ב
declare(strict_types=1)או הסוגים?self. - הפעל רישום ב
wp-config.php(בשלבי בימוי):
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false); - Open
wp-content/debug.logוחפשו "BPCAB" או "אלמנטור". - השבתה זמנית תוספי קטעי טקסט. כבר ראיתי קטע טקסט "ממדריך ישן של אלמנטור" שמצהיר על מחלקה עם אותו שם וגורם להתנגשות חמורה.
- נקו את המטמונים מטמון של תוספים, מטמון של שרת, CDN, מטמון של דפדפן. באלמנטור, אחסון אגרסיבי במטמון יכול גם לשמור על נכסים חסרים.
- צור מחדש את ה-CSS של אלמנטור (אם האתר שלכם משתמש באפשרות יצירת CSS). באלמנטור, בדרך כלל יש פעולת רגנרציה בהגדרות הכלים/ביצועים.
- נסה את זה עם נושא ניטרלי (זמני): Twenty Twenty-* או ערכת נושא קלת משקל. ערכת נושא יכולה לבטל רישום של סקריפטים/סגנונות.
מלכודות וטעויות נפוצות
| שגיאה | לגרום | פתרון |
|---|---|---|
| קוד הודבק לקובץ הלא נכון | נוסף ב functions.php במקום תוסף |
צור תוסף, ערוך לו גרסה והפעל/בטל אותו כראוי. |
| "שגיאת ניתוח: שגיאת תחביר" | חסרה נקודה-פסיק, סוגריים מתולתלים נוספים, העתקה והדבקה לא שלמה | בדוק את השורה המצוינת ביומן, השתמש ב-IDE עם עיצוב PHP |
| אלמנטור הוק לא מתאים | השימוש של init / wp_loaded כדי לשמור ווידג'ט |
Utiliser elementor/init אז elementor/widgets/register |
| "המחלקה ElementorPlugin לא נמצאה" | אלמנטור מושבת או נטען לאחר הקוד שלך | מאמת defined('ELEMENTOR_VERSION') ולעולם לא תתקשרו לאלמנטור לפני כן elementor/init |
| CSS/JS לא נטען | זיהוי פגום, וו פגום, או מטמון/מיניפיקציה | שמור דרך after_register_styles/scripts, להכריז על תלויות דרך get_*_depends()נקה את המטמון |
| התנגשות בשמות הכיתה | שני תוספים מצהירים BPCAB_Widget_Badge (או טוען אוטומטי שהוגדר בצורה שגויה) |
השתמש תמיד בקידומות ובמרחבי שמות אם אתה מתועש. |
| בלבול בין פעולה לפילטר | אתה מנסה "לחזור" למניה | פעולות: תופעות לוואי. מסננים: החזרת ערך. סקור את ה-hook בו נעשה שימוש. |
| בדיקות ישירות בייצור | אין בימוי, אין גיבוי | תוכנית Staging + גיבוי + החזרה למצב קודם (ביטול הפעלה של תוספים דרך FTP במידת הצורך) |
| קישורים קבועים/תבניות לא עקביות | אתה בודק על תבנית שונה מזו שעובדה (בונה ערכות נושא). | בדוק איזו תבנית אלמנטור מוחלת בפועל, ונקה את המטמון. |
טיפים לבטיחות, ביצועים ותחזוקה
אבטחה
- בריחה שיטתית כל מה שמופיע ב-HTML חייב להיות מבוטל בהתאם להקשר (
esc_html,esc_attr,esc_url,wp_kses_post). הפניה: וורדפרס: אימות נתונים. - אין אפשרויות "HTML חינמי" עבור תפקידים שאינם מנהלים. באתרים מרובי מחברים, זהו וקטור XSS.
- אין ביצוע PHP דרך ווידג'ט (זה נראה ברור מאליו, אבל כבר ראיתי כמה "ווידג'טים של קוד" מורכבים).
ביצוע
- נכסים מותנים באמצעות
get_style_depends()/get_script_depends()זהו יחס מאמץ/רווח הטוב ביותר. - הימנעו מבקשות לולאה ב
render()אם אתם צריכים לטעון נתונים (פוסטים, מטא), לאחסן אותם במטמון (מטמון זמני/אובייקט) או להכין אותם באמצעות שאילתה אופטימלית. - CSS מינימלי ווידג'ט = קובץ קטן. אם יש לכם 20, קבצו אותם בצורה חכמה (אך שמרו על התנאי).
תחזוקה
- גִרְסָה השתמשו בתוסף (Git) ותייגו את הגרסאות שלכם. כאשר Elementor משנה API, תדעו מה לפרוס.
- הימנעו ממדריכים "ישנים" אשר משתמשים ב-hooks מיושנים. אם אתם משתמשים שוב בקטע מ-2021-2023, ודאו שהוא תואם ל-Elementor ול-WordPress 6.9.4 הנוכחיים.
- הכינו אסטרטגיית גיבוי אם אלמנטור מושבת, התוסף שלך אמור "לא לעשות כלום" מבלי להיות קטלני.
משאבים
- מדריך למפתחי תוספים של וורדפרס
- הודעות וורדפרס
- אסקייפינג של וורדפרס (אבטחה)
- wp_register_style()
- wp_register_script()
- אלמנטור ב-WordPress.org
- ליבת וורדפרס (GitHub)
- מעקב ליבת וורדפרס
- מדריך PHP
שאלות נפוצות
האם הקוד הזה עובד עם וורדפרס 6.9.4?
כן: התוסף פועל לפי שיטות עבודה סטנדרטיות של וורדפרס (hooks, enqueue) ומכוון ל-PHP 8.1+. בעיית התאימות העיקרית נותרה גרסת Elementor (יש לעדכן אותה).
למה לא להשתמש בתוסף של snippets?
לבדיקה מהירה, זה בסדר. עבור ווידג'ט אלמנטור רב פעמי, תוסף אמיתי אמין יותר: טעינה מבוקרת, קבצים מאורגנים, ניהול גרסאות וכיבוי נקי אם הוא מתקלקל.
הווידג'ט שלי מופיע, אבל הוא לא בקטגוריה הנכונה.
בדוק ש get_categories() לְהִסְתוֹבֵב ['bpcab']ושהקטגוריה רשומה דרך elementor/elements/categories_registered.
איך אני מוסיף ווידג'טים מרובים?
הוסף עוד קבצים ל includes/widgets/ ולשמור אותם ב register_widgets()שמירה על קובץ אחד = מחלקה אחת.
איך אני יכול להימנע מטעינת JS אם אני לא צריך אותו?
לִמְחוֹק get_script_depends() או להחזיר מערך ריק. לשמור על הווידג'ט פונקציונלי ללא JS ככל האפשר.
האם נוכל להשתמש בטוען אוטומטי (Composer)?
כן, במיוחד אם יש לכם 10+ ווידג'טים. בהקשר של וורדפרס, היזהרו לא לכפות את Composer באתר הסופי. גישה נפוצה היא לכלול טוען אוטומטי של PSR-4 בתוך התוסף.
למה להשתמש wp_kses_post() בשביל הטקסט?
מכיוון שאזור טקסט יכול להכיל HTML אם אלמנטור מאפשר זאת (או אם המשתמש מדביק תוכן). wp_kses_post() מאפשר תת-קבוצה בטוחה, בניגוד להד גולמי.
התג הדינמי אינו מוצג: האם זה נורמלי?
זה תלוי בתצורת Elementor שלך. בדוק שממשק המשתמש "דינמי" זמין עבור השדות שלך. אם האתר שלך אינו תומך בתגים דינמיים, הסר את החלק. elementor/dynamic_tags/register והקובץ המשויך אליו.
איך אני יכול לבדוק כמו שצריך בלי לפגוע בעורך?
בדוק במצב staging, הפעל רישום (logging), והתחל עם ווידג'ט מינימלי (רנדרד + פקד אחד). הוסף פקדים אחד אחד. שגיאות Elementor לרוב שקטות בצד ממשק המשתמש, אך גלויות בקונסולה ובלוג PHP.
האם זה תואם לערכת נושא של Divi/Avada?
כן, כי זה תוסף. עם זאת, הווידג'ט יופיע רק באלמנטור. עבור Divi/Avada, השתמשו בקוד קצר או בבלוק אם אתם רוצים רכיב שניתן לשתף בין בוני תוכנה.