সমস্যাটি / প্রয়োজন
আপনি যদি ইতিমধ্যেই একটি এলিমেন্টর সাইট তৈরি করে থাকেন এবং কোনো ক্লায়েন্ট আপনাকে জিজ্ঞাসা করে “আমি একটি উইজেট চাই” বিশেষভাবে তৈরিকিন্তু ১২টি অ্যাড-অন ইনস্টল না করেই, আপনার মধ্যে সঠিক প্রবৃত্তিটি ইতিমধ্যেই রয়েছে: কোডটি খতিয়ে দেখুন।
এলিমেন্টর (ফ্রি/প্রো) বিল্ডারকে যথাযথভাবে কাস্টমাইজ করার জন্য হুক এবং ইভেন্টের একটি যথেষ্ট স্থিতিশীল এপিআই প্রদান করে: উইজেটের একটি ক্যাটাগরি যোগ করা, কাস্টম উইজেট সেভ করা, কন্ট্রোল ইনজেক্ট করা, ডিফল্ট ভ্যালু প্রয়োগ করা, শুধু প্রয়োজনের সময় স্ক্রিপ্ট লোড করা, এবং এমনকি একটি ট্যাগের মাধ্যমে ডাইনামিক ফিল্ড যোগ করা।
সাধারণ ব্যবসায়িক প্রয়োজন হলো: এলিমেন্টরের ইউএক্স (UX) বজায় রেখে পুনঃব্যবহারযোগ্য কম্পোনেন্টগুলোকে (যেমন: সিটিএ, অথর বক্স, প্রোডাক্ট শিট, টেবিল, জিডিপিআর ব্যানার ইত্যাদি) শিল্পায়িত করা। কোর্স শেষে, আপনি একটি পরিচ্ছন্ন ও সামঞ্জস্যপূর্ণ মিনি-প্লাগইন কীভাবে গঠন করতে হয় তা শিখে যাবেন। ওয়ার্ডপ্রেস 6.9.4+ এবং PHP 8.1+, তাহলে আপনি আপনার প্রোজেক্টগুলোর জন্য একটি পুনঃব্যবহারযোগ্য ভিত্তি পাবেন।
দ্রুত সারসংক্ষেপ
- একটি মিনি-প্লাগইন তৈরি করুন ওয়ার্ডপ্রেস (কোনো একবার ব্যবহারযোগ্য কোড নয়) যা এলিমেন্টরের সাথে কোনো রকম সমস্যা ছাড়াই একীভূত হয়অ্যাডমিন.
- সঠিক এলিমেন্টর হুক ব্যবহার করুন:
elementor/init,elementor/widgets/register,elementor/elements/categories_registered,elementor/frontend/after_register_scripts. - কন্ট্রোল, সেফ রেন্ডারিং ও স্টাইল সহ একটি কাস্টম “ব্যাজ” উইজেট (শিরোনাম + টেক্সট + রঙ + আইকন) যোগ করুন।
- ব্যবহারকারীর মেটা থেকে কোনো মান (যেমন, পদ/ভূমিকা) অন্তর্ভুক্ত করতে একটি ডাইনামিক ট্যাগ (উন্নত বিকল্প) যোগ করুন।
- আপনার প্লাগইনের কোনো উইজেট উপস্থিত থাকলেই কেবল CSS/JS লোড করুন (এতে "সব জায়গায় সবকিছু লোড হওয়া" এড়ানো যায়)।
কখন এই সমাধানটি ব্যবহার করবেন
- আপনি এমন একটি স্থিতিশীল ও ভার্সনযুক্ত কম্পোনেন্ট চান যা একাধিক সাইটে (এজেন্সি, ফ্রিল্যান্স, টিম) পুনরায় ব্যবহার করা যাবে।
- আপনাকে অবশ্যই একটি স্টাইল গাইড (রং, টাইপোগ্রাফি, স্পেসিং) মেনে চলতে হবে এবং ক্লায়েন্টের জন্য ৫০টি “ঝুঁকিপূর্ণ” বিকল্প রাখা যাবে না।
- আপনার এমন কোনো থার্ড-পার্টি অ্যাড-অনের ওপর নির্ভর না করে নির্ভুল ফ্রন্ট-এন্ড রেন্ডারিং প্রয়োজন, যা কোনো পূর্বসতর্কতা ছাড়াই পরিবর্তিত হতে পারে।
- আপনি পারফরম্যান্স উন্নত করতে চান: অ্যাসেটগুলো শুধু প্রয়োজনের সময় লোড হবে, উইজেটের কোনো "বড় প্যাক" থাকবে না।
- আপনি ডাইনামিক ট্যাগের মাধ্যমে ওয়ার্ডপ্রেস ডেটা (মেটা, অপশন, ACF/Pods, ইত্যাদি) একীভূত করতে চান।
কখন এই সমাধানটি ব্যবহার করা উচিত নয়
- প্রয়োজনটি সম্পূর্ণরূপে দৃষ্টিগত এবং মাঝে মাঝে দেখা দেয়: একটি সহজ একটি এলিমেন্টর টেমপ্লেট, একটি কন্টেইনার এবং সামান্য CSS-ই যথেষ্ট হতে পারে।
- রক্ষণাবেক্ষণের উপর আপনার কোনো নিয়ন্ত্রণ নেই: একটি কাস্টম উইজেট ব্যবহার করতে হলে এলিমেন্টর (এবং কখনও কখনও এর অপ্রচলিত সংস্করণগুলো) অনুসরণ করতে হয়।
- আপনি যদি এলিমেন্টরকে গভীরভাবে 'প্যাচ' করতে চান (যেমন, এডিটরের অভ্যন্তরীণ আচরণ পরিবর্তন করতে চান), তবে এটি খুব কমই স্থিতিশীল থাকে। অফিসিয়াল এক্সটেনশন ব্যবহার করুন, অথবা কিছুটা প্রযুক্তিগত সীমাবদ্ধতা মেনে নিন।
- আপনার ক্লায়েন্ট প্রধানত গুটেনবার্গ/ব্লক ব্যবহার করেন: এক্ষেত্রে, একটি কাস্টম ব্লক (ব্লক এপিআই) প্রায়শই বেশি উপযুক্ত হয়। অফিসিয়াল ডকুমেন্টেশন দেখুন: ব্লক এডিটর হ্যান্ডবুক.
শুরু করার আগে পূর্বশর্তসমূহ /
- ওয়ার্ডপ্রেস ৬.৯.৪+ এবং পিএইচপি ৮.১+ (আদর্শগতভাবে ২০২৬ সালের মধ্যে ৮.২/৮.৩, যদি আপনার হোস্টিং প্রোভাইডার তাল মিলিয়ে চলতে পারে)।
- এলিমেন্টর ইনস্টল এবং সক্রিয় করা আছে (এই উইজেট উদাহরণের জন্য এর ফ্রি ভার্সনই যথেষ্ট)। উন্নত ডাইনামিক ট্যাগের জন্য প্রায়শই এলিমেন্টর প্রো ব্যবহার করা হয়, কিন্তু আমরা যথাসম্ভব পাবলিক এপিআই-ই ব্যবহার করে থাকি।
- যেকোনো পরিবর্তন করার আগে একটি স্টেজিং এনভায়রনমেন্ট এবং ব্যাকআপ থাকা অপরিহার্য। আমি প্রায়শই দেখেছি যে প্রোডাকশনে কোডের কিছু অংশ পেস্ট করার ফলে একটি মারাত্মক ত্রুটি (fatal error) ঘটে এবং অ্যাডমিন ইন্টারফেসটি লক হয়ে যায়।
- একটি লগস প্লাগইন (বা অন্তত
WP_DEBUG_LOGপিএইচপি ত্রুটিগুলো পড়ার জন্য।
দরকারী ওয়ার্ডপ্রেস রেফারেন্স:
সরল পন্থা (এবং কেন তা পরিহার করা উচিত)
প্রচলিত পদ্ধতি: কোডের একটি বড় অংশ পেস্ট করা 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 লোড হয়।
- রক্ষণাবেক্ষণ থিমের মধ্যে কোড হারিয়ে যায়, সঠিকভাবে ভার্সন করা অসম্ভব, থিম পরিবর্তন করলে ভঙ্গুর হয়ে পড়ে।
সঠিক পদ্ধতি — ধাপে ধাপে নির্দেশিকা
আমরা একটি মিনি-প্লাগইন তৈরি করতে যাচ্ছি, যার মধ্যে থাকবে:
- একটি বুটস্ট্র্যাপ যা এলিমেন্টর সক্রিয় আছে কিনা তা পরীক্ষা করে।
- উইজেটের একটি বিশেষ বিভাগ,
- একটি কাস্টম উইজেট,
- একটি শর্তসাপেক্ষ সম্পদ লোড,
- একটি উন্নত ফিল্টার/রেজিস্টার প্রদর্শনের জন্য একটি ঐচ্ছিক “ডাইনামিক ট্যাগ” ভ্যারিয়েন্ট।
ধাপ ১ — প্লাগইনটি তৈরি করুন
এই ফোল্ডারটি তৈরি করুন: wp-content/plugins/bpcab-elementor-hooks/
তারপর এই ফাইলটি: wp-content/plugins/bpcab-elementor-hooks/bpcab-elementor-hooks.php
ধাপ ২ — বুটস্ট্র্যাপ ও এলিমেন্টর যাচাইকরণ
আমরা আমাদের কোড সংযুক্ত করি plugins_loaded তারপর আমরা অপেক্ষা করি elementor/initমূল বিষয়টি হলো: প্লাগইন প্রস্তুত না হওয়া পর্যন্ত এলিমেন্টর ক্লাস কল করবেন না।
ধাপ ৩ — একটি ক্যাটাগরি ও একটি উইজেট সংরক্ষণ করুন
এলিমেন্টর বিশেষ অ্যাকশন প্রদান করে। বাস্তবে, এগুলো বেশ কয়েকটি সংস্করণ ধরে স্থিতিশীল রয়েছে:
elementor/elements/categories_registeredএকটি বিভাগ যোগ করতে,elementor/widgets/registerএকটি উইজেট সংরক্ষণ করতে।
আমি জোর দিচ্ছি: যথেচ্ছভাবে হুক ব্যবহার করা পরিহার করুন (যেমন init ou wp_loadedএলিমেন্টরকে স্পর্শ করতে গেলে সমস্যাটি খুব কমই উইজেটের কোড থেকে আসে, বরং এটি কার্যকর হওয়ার মুহূর্ত থেকে শুরু হয়।
ধাপ ৪ — সঠিক সময়ে CSS/JS লোড করুন
সম্পদ নথিভুক্ত করা হয় এর মাধ্যমে elementor/frontend/after_register_styles / elementor/frontend/after_register_scriptsতারপর আমরা সারিবদ্ধ শুধুমাত্র যদি উইজেটটি প্রকৃতপক্ষে রেন্ডার করা হয়।
ধাপ ৫ — (ঐচ্ছিক) একটি ডাইনামিক ট্যাগ যোগ করুন
আপনি যদি এলিমেন্টর প্রো ব্যবহার করেন (অথবা আপনার স্ট্যাক যদি ডাইনামিক ট্যাগ সমর্থন করে), তাহলে শর্টকোডের চেয়ে কাস্টম ট্যাগ প্রায়শই বেশি পরিচ্ছন্ন হয়। আপনি ডেটা প্রকাশ করেন, এবং এলিমেন্টর তার 'ডাইনামিক' কন্ট্রোলগুলোতে ডেটা ইনজেকশনের কাজটি করে দেয়।
সম্পূর্ণ কোড
নিচের সবকিছু কপি করে পেস্ট করুন। প্লাগইনটি স্বয়ংসম্পূর্ণ, এবং আপনি পরে উইজেট যোগ করতে পারবেন।
ফাইল ১ — 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();
ফাইল ২ — 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>';
}
}
ফাইল ৩ — 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);
}
}
ফাইল ৪ — 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;
}
ফাইল ৫ — 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.
})();
কোডের ব্যাখ্যা
১) কেন একটি প্লাগইন (functions.php নয়)?
একটি প্লাগইন আপনাকে একটি সুস্পষ্ট জীবনচক্র, সক্রিয়করণ/নিষ্ক্রিয়করণ, ভার্সনিং এবং আপনার ক্লাসগুলির জন্য একটি স্থিতিশীল অবস্থান প্রদান করে। আমি প্রায়শই দেখেছি যে Avada/Divi সাইট আপডেট করার সময় থিমের একটি ছোট কোড স্নিপেট অদৃশ্য হয়ে যায় বা বেমানান হয়ে পড়ে।
২) মূল বিষয়: হুকগুলোর সময়
plugins_loadedওয়ার্ডপ্রেস প্লাগইনগুলো লোড করে দিয়েছে। আমরা পরীক্ষা করে দেখতে পারি এলিমেন্টর আছে কি না।elementor/initএলিমেন্টর তার প্রধান কন্টেইনারটি চালু করেছে। এখানেই আপনি আপনার এলিমেন্টর হুকগুলো যোগ করবেন।elementor/widgets/registerআপনি উইজেট ম্যানেজারটি গ্রহণ করেন এবং আপনার ক্লাসগুলো সংরক্ষণ করেন।elementor/elements/categories_registeredআপনি বিল্ডারের UI-তে দৃশ্যমান একটি ক্যাটাগরি ঘোষণা করেন।
এই বিশ্লেষণটি প্রচলিত বাগগুলো এড়িয়ে চলে: “Class 'ElementorPlugin' not found” অথবা “Collection register() on null”।
৩) শর্তসাপেক্ষে সম্পদ বোঝাই করা
দুজন get_style_depends() / get_script_depends() এর ব্যবহার কম। অথচ, এলিমেন্টর যখন আপনার উইজেট রেন্ডার করে, শুধু তখনই আপনার অ্যাসেটগুলো লোড করার এটি অন্যতম সেরা উপায়।
নেপথ্যে: এলিমেন্টর পেজের উইজেটগুলোর ডিপেন্ডেন্সি সংগ্রহ করে এবং সংশ্লিষ্ট হ্যান্ডেলগুলো কোয়েরি করে। আপনাকে শুধু... wp_register_style() / wp_register_script() সঠিক সময়ে.
৪) নিরাপদ রেন্ডারিং: স্যানিটাইজেশন + এস্কেপিং
- প্রবেশ এলিমেন্টর ডাটাবেসে ভ্যালু সংরক্ষণ করে। প্রেক্ষাপট অনুযায়ী আপনাকে সেগুলো পরিষ্করণ করতে হতে পারে।
- হামলার :
esc_html()পাঠ্যের জন্য,wp_kses_post()যদি আপনি সীমিত HTML-এর অনুমতি দেন।
আমি যে ফাঁদটি সবচেয়ে বেশি দেখি: সোজা বেরিয়ে যাওয়া $settings['text'] ব্যতীত wp_kses_post() কারণ ইনি অ্যাডমিন। একাধিক লেখকের সাইটে এটি একটি XSS ঝুঁকি হয়ে দাঁড়ায়।
৫) ডাইনামিক ট্যাগ: কেন এটি উপকারী
ডাইনামিক ট্যাগ এলিমেন্টর ফিল্ডে শর্টকোডের প্রয়োজনীয়তা দূর করে। আপনি ডেটা (ইউজার মেটা, অপশন, এসিএফ ফিল্ড) প্রকাশ করেন এবং ব্যবহারকারী ইউআই থেকে ট্যাগটি নির্বাচন করেন। ৩০টি উইজেটে শর্টকোড পেস্ট করার চেয়ে এটি অনেক বেশি রক্ষণাবেক্ষণযোগ্য।
বিভিন্ন রূপ এবং ব্যবহারের ক্ষেত্র
বিকল্প ১ — “লক করা” মানগুলো বাধ্যতামূলক করা (গ্রাহকের জন্য কম বিকল্প)
আপনি যদি গ্রাহককে নির্দিষ্ট কিছু অপশন পরিবর্তন করা থেকে বিরত রাখতে চান, তাহলে আপনি:
- নিয়ন্ত্রণ প্রকাশ করবেন না (না
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>';
বিকল্প ২ — একটি ইউআরএল কন্ট্রোল যোগ করুন এবং একটি ক্লিন লিঙ্ক তৈরি করুন
একটি ক্লিকযোগ্য ব্যাজ CTA সব সময় প্রদর্শিত হয়। এলিমেন্টর একটি URL কন্ট্রোল প্রদান করে, যাতে 'ওপেন ইন আ নিউ ট্যাব' এবং 'নোফলো' অপশন রয়েছে।
// 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 (নিরাপত্তা)।
ভ্যারিয়েন্ট ৩ — শুধুমাত্র নির্দিষ্ট কিছু পেজে অ্যাসেট লোড করুন (আরও কঠোর)
আপনার যদি একটি জটিল স্ক্রিপ্ট থাকে, তাহলে আপনি উইজেট নির্ভরতাকে একটি ওয়ার্ডপ্রেস শর্তের সাথে একত্রিত করতে পারেন। উদাহরণস্বরূপ: শুধুমাত্র পৃষ্ঠাগুলিতে (অন্য কোথাও নয়) প্রবন্ধ):
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
- উপরের প্লাগইনটি কোনো থিমের উপর নির্ভর না করে এলিমেন্টরের সাথে একীভূত হয়।
- আপনি যদি এলিমেন্টর (থিম বিল্ডার) টেমপ্লেট ব্যবহার করেন, তাহলে উইজেটটি সব জায়গায় উপলব্ধ থাকে।
- সম্পদগুলো শর্তসাপেক্ষ: যা অত্যন্ত ব্যস্ত সাইটগুলোর জন্য একটি ভালো দিক।
দিভি ৫
Divi 5 Elementor API ব্যবহার করে না। আপনার উইজেটটি Divi-তে দেখা যাবে না, এবং এটি স্বাভাবিক।
আপনার লক্ষ্য যদি ডিভি পেজগুলিতে একই কম্পোনেন্ট পুনরায় ব্যবহার করা হয়, তাহলে আমি একটি "বিল্ডার-অ্যাগনস্টিক" কৌশলের পরামর্শ দিই:
- একটি ওয়ার্ডপ্রেস শর্টকোড তৈরি করুন (অথবা আরও ভালো: একটি গুটেনবার্গ ব্লক),
- তারপর একটি কোড/শর্টকোড মডিউলের মাধ্যমে এটিকে ডিভিতে সন্নিবেশ করুন,
- এবং Elementor উপস্থিত থাকলে সেটিকে একটি “UI ওভারলে” হিসেবে রাখুন।
আমার অভিজ্ঞতায়, একাধিক নির্মাতার পার্ক থাকলে এটাই একমাত্র কার্যকর পদ্ধতি।
আভাদা (ফিউশন বিল্ডার)
একই যুক্তি প্রযোজ্য: Avada, Elementor উইজেট ব্যবহার করবে না। তবে, সাইটটির কিছু পৃষ্ঠায় Elementor ব্যবহৃত হলেও আপনার প্লাগইনটি কার্যকর থাকবে।
Avada-র ক্ষেত্রেও সবচেয়ে পরিচ্ছন্ন প্যাটার্নটি হলো: প্রথমে শর্টকোড বা ব্লক, তারপর Fusion Builder-এ “Code Block” / “Shortcode” এলিমেন্ট।
ইনস্টলেশন-পরবর্তী পরীক্ষা
- প্লাগইনটি সক্রিয় করুন এক্সটেনশানগুলি.
- এলিমেন্টর দিয়ে একটি পৃষ্ঠা খুলুন।
- উইজেট প্যানেলে, ক্যাটাগরিটি খুঁজুন। বিপিসিএবি তারপর উইজেটটি ব্যাজ (বিপিসিএবি).
- এটি পৃষ্ঠায় রাখুন, শিরোনাম/লেখা/রং সম্পাদনা করুন এবং প্রকাশ করুন।
- সামনের দিকে, পৃষ্ঠাটি পরিদর্শন করুন: আপনি দেখতে পাবেন
bpcab-badge.cssলোড হয়েছে (এবং যেসব পেজে উইজেটটি ব্যবহার করা হয় না, সেগুলোতে নয়)।
দ্রুত রোগ নির্ণয় চার্ট
| লক্ষণ | সম্ভাব্য কারণ | প্রতিপাদন | সমাধান |
|---|---|---|---|
| BPCAB বিভাগটি প্রদর্শিত হয় না। | হুকটি কখনো কার্যকর হয়নি (এলিমেন্টর লোড হয়নি) | যাচাই করুন যে ELEMENTOR_VERSION সংজ্ঞায়িত করা হয়েছে, এবং এলিমেন্টর সক্রিয় আছে |
এলিমেন্টর সক্রিয় করুন, দ্বন্দ্ব/mu-plugins পরীক্ষা করুন। |
| মারাত্মক ত্রুটি “Class ElementorWidget_Base খুঁজে পাওয়া যায়নি” | উইজেট ফাইলটি খুব তাড়াতাড়ি লোড করা হয়েছে / এলিমেন্টর নিষ্ক্রিয় আছে | পিএইচপি লগ ও স্ট্যাক ট্রেস দেখুন | শুধুমাত্র উইজেটটি প্রয়োজন elementor/widgets/register après elementor/init |
| CSS/JS লোড হয়নি | অনিবন্ধিত হ্যান্ডেল বা ত্রুটিপূর্ণ রেজিস্ট্রেশন হুক | পরিদর্শন করা wp_head / wp_footer + কনসোল |
চেক after_register_styles/scripts et get_style_depends() |
| উইজেটটি দেখা যাচ্ছে, কিন্তু স্টাইলগুলো ঠিক নেই। | ক্যাশিং (প্লাগইন/সিডিএন) অথবা আগ্রাসী মিনিফিকেশন | ক্যাশে নিষ্ক্রিয় করুন, CDN পরিষ্কার করুন, প্রাইভেট ব্রাউজিং মোডে পরীক্ষা করুন | ক্যাশে/মিনিফাই থেকে ফাইল বাদ দিন, সংস্করণ আপডেট করুন |
| ডাইনামিক ট্যাগ খুঁজে পাওয়া যায়নি | ফিচারটি উপলব্ধ নয় (কনফিগারেশন/প্রো-এর উপর নির্ভর করে) অথবা হুকটি ট্রিগার হয়নি | একটি টেক্সট ফিল্ডে “ডাইনামিক” প্যানেলটি আছে কিনা তা পরীক্ষা করুন। | প্রয়োজনে এলিমেন্টর প্রো ইনস্টল/অ্যাক্টিভেট করুন, অথবা ট্যাগ সেকশনটি সরিয়ে দিন। |
যদি সেটা কাজ না করে
- সংস্করণগুলি নিশ্চিত করুন 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” অনুসন্ধান করুন। - সাময়িকভাবে অক্ষম করুন স্নিপেট প্লাগইন। আমি ইতিমধ্যেই একটি পুরোনো এলিমেন্টর টিউটোরিয়ালের একটি স্নিপেট দেখেছি, যেখানে একই নামের একটি ক্লাস ডিক্লেয়ার করে একটি মারাত্মক কনফ্লিক্ট তৈরি করা হয়েছিল।
- ক্যাশগুলি পরিষ্কার করুন প্লাগইন ক্যাশে, সার্ভার ক্যাশে, সিডিএন, ব্রাউজার ক্যাশে। এলিমেন্টরে, অ্যাগ্রেসিভ ক্যাশিং অনুপস্থিত অ্যাসেটগুলোও ধরে রাখতে পারে।
- এলিমেন্টর CSS পুনরায় তৈরি করুন (যদি আপনার সাইট CSS জেনারেশন অপশনটি ব্যবহার করে)। এলিমেন্টরে, সাধারণত টুলস/পারফরম্যান্স সেটিংসে একটি রিজেনারেশন অ্যাকশন থাকে।
- একটি নিরপেক্ষ থিম দিয়ে চেষ্টা করে দেখুন (অস্থায়ী): টোয়েন্টি টোয়েন্টি-* অথবা একটি লাইটওয়েট থিম। একটি থিম স্ক্রিপ্ট/স্টাইল ডি-রেজিস্টার করতে পারে।
সাধারণ ফাঁদ এবং ভুলগুলি
| এরর | কারণ | সমাধান |
|---|---|---|
| কোডটি ভুল ফাইলে পেস্ট করা হয়েছে। | যোগ করা হয়েছে functions.php প্লাগইনের পরিবর্তে |
একটি প্লাগইন তৈরি করুন, সেটির ভার্সন তৈরি করুন এবং যথাযথভাবে সক্রিয়/নিষ্ক্রিয় করুন। |
| পার্স ত্রুটি: সিনট্যাক্স ত্রুটি | সেমিকোলন অনুপস্থিত, অতিরিক্ত কোঁকড়া বন্ধনী, অসম্পূর্ণ কপি-পেস্ট | লগে নির্দেশিত লাইনটি পর্যালোচনা করুন, PHP ফরম্যাটিং সহ একটি IDE ব্যবহার করুন। |
| হুক এলিমেন্টর অনুপযুক্ত | এর ব্যবহার init / wp_loaded একটি উইজেট সংরক্ষণ করতে |
ব্যবহার elementor/init তারপর elementor/widgets/register |
| ElementorPlugin ক্লাসটি খুঁজে পাওয়া যায়নি। | আপনার কোডের পরে এলিমেন্টর নিষ্ক্রিয় বা লোড করা হয়। | চেক defined('ELEMENTOR_VERSION') এবং এর আগে কখনো Elementor-কে কল করবেন না elementor/init |
| CSS/JS লোড হয়নি | ভুল হ্যান্ডেল, ভুল হুক, অথবা ক্যাশে/মিনিফিকেশন | সংরক্ষণ করুন after_register_styles/scriptsএর মাধ্যমে নির্ভরতা ঘোষণা করুন get_*_depends()ক্যাশে পরিষ্কার করুন |
| ক্লাসের নামের দ্বন্দ্ব | দুটি প্লাগইন ঘোষণা করে BPCAB_Widget_Badge (অথবা একটি ভুলভাবে কনফিগার করা অটোলোডার) |
শিল্পায়নের ক্ষেত্রে সর্বদা প্রিফিক্স ও নেমস্পেস ব্যবহার করুন। |
| অ্যাকশন এবং ফিল্টারের মধ্যে বিভ্রান্তি | আপনি একটি স্টকে "ফিরে" আসার চেষ্টা করছেন | ক্রিয়া: পার্শ্ব প্রতিক্রিয়া। ফিল্টার: একটি মান ফেরত দেয়। ব্যবহৃত হুকটি পর্যালোচনা করুন। |
| উৎপাদনে সরাসরি পরীক্ষা | কোনো স্টেজিং নেই, কোনো ব্যাকআপ নেই | স্টেজিং + ব্যাকআপ + রোলব্যাক প্ল্যান (প্রয়োজনে FTP এর মাধ্যমে প্লাগইন নিষ্ক্রিয়করণ) |
| অসঙ্গত স্থায়ী লিঙ্ক/টেমপ্লেট | আপনি রেন্ডার করা টেমপ্লেট (থিম বিল্ডার) থেকে ভিন্ন একটি টেমপ্লেটে পরীক্ষা করছেন। | প্রকৃতপক্ষে কোন এলিমেন্টর টেমপ্লেটটি প্রয়োগ করা হয়েছে তা যাচাই করুন এবং ক্যাশে পরিষ্কার করুন। |
নিরাপত্তা, কর্মক্ষমতা এবং রক্ষণাবেক্ষণের পরামর্শ
নিরাপত্তা
- পদ্ধতিগতভাবে পালানো এইচটিএমএল-এ যা কিছু আউটপুট হয়, তা অবশ্যই প্রসঙ্গ অনুযায়ী এস্কেপ করতে হবে (
esc_html,esc_attr,esc_url,wp_kses_postতথ্যসূত্র : ওয়ার্ডপ্রেস: ডেটা যাচাইকরণ. - কোন “ফ্রি এইচটিএমএল” বিকল্প নেই নন-অ্যাডমিন রোলের জন্য। একাধিক লেখকের সাইটে, এটি একটি XSS ভেক্টর।
- উইজেটের মাধ্যমে কোনো PHP এক্সিকিউশন হবে না বিষয়টা স্পষ্ট মনে হলেও, আমি এর মধ্যেই কিছু জোড়াতালি দেওয়া 'কোড উইজেট' দেখেছি।
সম্পাদন
- শর্তাধীন সম্পদ মাধ্যমে
get_style_depends()/get_script_depends()এটাই হলো প্রচেষ্টা ও প্রাপ্তির সর্বোত্তম অনুপাত। - লুপ অনুরোধ এড়িয়ে চলুন মধ্যে
render()আপনার যদি ডেটা (পোস্ট, মেটা) লোড করার প্রয়োজন হয়, তবে তা ক্যাশ করুন (ট্রানজিয়েন্ট/অবজেক্ট ক্যাশ) অথবা অপ্টিমাইজড কোয়েরির মাধ্যমে প্রস্তুত করুন। - ন্যূনতম CSS উইজেট হলো একটি ছোট ফাইল। আপনার কাছে ২০টি থাকলে, সেগুলোকে বুদ্ধিমত্তার সাথে গ্রুপ করুন (কিন্তু শর্তসাপেক্ষতা বজায় রাখুন)।
রক্ষণাবেক্ষণ
- সংস্করণ প্লাগইনটি (Git) ব্যবহার করুন এবং আপনার রিলিজগুলোতে ট্যাগ যুক্ত করুন। যখন Elementor কোনো API পরিবর্তন করবে, তখন আপনি জানতে পারবেন কোনটি ডেপ্লয় করতে হবে।
- “পুরানো” টিউটোরিয়ালগুলি এড়িয়ে চলুন যেগুলোতে পুরোনো হুক ব্যবহার করা হয়েছে। আপনি যদি ২০২১-২০২৩ সালের কোনো স্নিপেট পুনরায় ব্যবহার করেন, তবে নিশ্চিত করুন যে এটি বর্তমান এলিমেন্টর এবং ওয়ার্ডপ্রেস ৬.৯.৪-এর সাথে সামঞ্জস্যপূর্ণ।
- একটি বিকল্প কৌশল প্রস্তুত করুন যদি এলিমেন্টর নিষ্ক্রিয় থাকে, তাহলে আপনার প্লাগইনটি মারাত্মক কোনো সমস্যা ছাড়াই “কিছুই করবে না”।
সম্পদ
- ওয়ার্ডপ্রেস প্লাগইন ডেভেলপার হ্যান্ডবুক
- ওয়ার্ডপ্রেস ননসেস
- ওয়ার্ডপ্রেস এস্কেপিং (নিরাপত্তা)
- wp_register_style()
- wp_register_script()
- WordPress.org-এ এলিমেন্টর
- ওয়ার্ডপ্রেস কোর (গিটহাব)
- ওয়ার্ডপ্রেস কোর ট্র্যাক
- পিএইচপি ম্যানুয়াল
FAQ
এই কোডটি কি ওয়ার্ডপ্রেস ৬.৯.৪-এর সাথে কাজ করে?
হ্যাঁ: প্লাগইনটি ওয়ার্ডপ্রেসের প্রচলিত নিয়মকানুন (হুকস, এনকিউ) অনুসরণ করে এবং পিএইচপি ৮.১+ এর জন্য তৈরি। মূল সামঞ্জস্যতার সমস্যাটি হলো এলিমেন্টরের সংস্করণ (এটি হালনাগাদ রাখুন)।
স্নিপেটস প্লাগইন ব্যবহার করছেন না কেন?
দ্রুত পরীক্ষার জন্য এটা ঠিক আছে। কিন্তু পুনরায় ব্যবহারযোগ্য এলিমেন্টর উইজেটের জন্য একটি আসল প্লাগইন বেশি নির্ভরযোগ্য: নিয়ন্ত্রিত লোডিং, গোছানো ফাইল, ভার্সনিং এবং কোনো সমস্যা হলে পরিষ্কারভাবে নিষ্ক্রিয় করার সুবিধা।
আমার উইজেটটি দেখা যাচ্ছে, কিন্তু এটি সঠিক ক্যাটাগরিতে নেই।
যাচাই করুন যে get_categories() ঘুরে দাঁড়ান ['bpcab']এবং বিভাগটি এর মাধ্যমে নিবন্ধিত হয় elementor/elements/categories_registered.
আমি কীভাবে একাধিক উইজেট যোগ করব?
আরও ফাইল যোগ করুন includes/widgets/ এবং সেগুলি সংরক্ষণ করুন register_widgets()একটি ফাইল = একটি ক্লাস।
প্রয়োজন না থাকলে আমি কীভাবে JS লোড করা এড়াতে পারি?
মুছে ফেলুন get_script_depends() অথবা একটি খালি অ্যারে ফেরত দিন। যতটা সম্ভব জাভাস্ক্রিপ্ট ছাড়া উইজেটটিকে কার্যকরী রাখুন।
আমরা কি অটোলোডার (কম্পোজার) ব্যবহার করতে পারি?
হ্যাঁ, বিশেষ করে যদি আপনার ১০টির বেশি উইজেট থাকে। ওয়ার্ডপ্রেসের ক্ষেত্রে, চূড়ান্ত সাইটে কম্পোজার ব্যবহারে জোর না করার ব্যাপারে সতর্ক থাকুন। একটি প্রচলিত পদ্ধতি হলো প্লাগইনের মধ্যে একটি PSR-4 অটোলোডার অন্তর্ভুক্ত করা।
কেন ব্যবহার করবেন wp_kses_post() পাঠ্যটির জন্য?
কারণ এলিমেন্টর অনুমতি দিলে (অথবা ব্যবহারকারী কন্টেন্ট পেস্ট করলে) একটি টেক্সটএরিয়াতে HTML থাকতে পারে। wp_kses_post() এটি একটি নিরাপদ সাবসেটের সুযোগ দেয়, যা একটি র ইকো-র ক্ষেত্রে সম্ভব নয়।
ডাইনামিক ট্যাগটি প্রদর্শিত হচ্ছে না: এটা কি স্বাভাবিক?
এটি আপনার এলিমেন্টর কনফিগারেশনের উপর নির্ভর করে। আপনার ফিল্ডগুলোর জন্য “ডাইনামিক” UI উপলব্ধ আছে কিনা তা পরীক্ষা করুন। যদি আপনার সাইট ডাইনামিক ট্যাগ সমর্থন না করে, তাহলে অংশটি সরিয়ে দিন। elementor/dynamic_tags/register এবং সংশ্লিষ্ট ফাইল।
এডিটরটি নষ্ট না করে আমি কীভাবে সঠিকভাবে পরীক্ষা করতে পারি?
স্টেজিং মোডে পরীক্ষা করুন, লগিং চালু করুন এবং একটি ন্যূনতম উইজেট (রেন্ডার করা + একটি কন্ট্রোল) দিয়ে শুরু করুন। এক এক করে কন্ট্রোল যোগ করুন। এলিমেন্টরের ত্রুটিগুলো প্রায়শই UI-তে দেখা যায় না, কিন্তু কনসোল এবং PHP লগে দৃশ্যমান হয়।
এটি কি Divi/Avada চাইল্ড থিমের সাথে সামঞ্জস্যপূর্ণ?
হ্যাঁ, কারণ এটি একটি প্লাগইন। তবে, উইজেটটি শুধুমাত্র এলিমেন্টর-এ দেখা যাবে। ডিভি/আভাডা-র ক্ষেত্রে, যদি আপনি এমন একটি কম্পোনেন্ট চান যা বিভিন্ন বিল্ডারের মধ্যে শেয়ার করা যায়, তাহলে একটি শর্টকোড বা ব্লক ব্যবহার করুন।