Skip to content

Kõik WordPressist, veebiarendusest — ja mitte ainult

🛠️ Kohandatud Elementori vidinad: täistsükkel pluginast juhtelementideni

🛠️ Kohandatud Elementori vidinad: täistsükkel pluginast juhtelementideni

Teemavärskendus lõhkus kohandatud ploki, mis kuvas avalehel pakkumisi. Kõlab tuttavalt? Kood elab failis functions.php, stiilid on laiali paisatud failis style.css ja JS-i töötleja on naelutatud faili footer.php külge. Vaheta teemat või tee suurem Elementori uuendus ja pead kõik selle nullist uuesti kokku panema.

Probleem pole selles, et „kood on halb". Probleem on selles, et see elab vales kohas. Teemasse topitud kohandatud muudatused on sellega püsivalt seotud: teisele saidile ülekandmine on võimatu, vigade silumine on piinarikas ja varade tingimuslik laadimine puudub.

Õige lähenemine on pakendada kohandatud vidin eraldi pluginana. Just seda soovitab ametlik Elementori dokumentatsioon igasuguste mittetriviaalsete kohanduste puhul. Koodi isoleeritus, teemasõltumatus, korralik versioonihaldus ja JS-i laadimine ainult vidinat sisaldavatel lehtedel. Selles juhendis kogu tsükkel: pluginastruktuurist kuni töötava vidinani koos reaalajas toimetamisega, praegusel Elementori API-l (3.x/4.x).

Koodiredaktorid arvutiekraanil

💡 Kiirülevaade:

  • Registreeri vidina jaoks eraldi plugin, isoleeri kood teemast lõplikult.
  • Ehita põhiklass koos ühilduvuskontrollidega: Elementor aktiivne, versioon mitte madalam kui 3.5, PHP alates 7.4.
  • Loo vidinaklass: laienda Widget_Base, defineeri register_controls() ja renderdusmeetod.
  • Ühenda reaalajas tekstiredaktor add_inline_editing_attributes() ja Backbone'i malli kaudu.
  • Lisa kohandatud väljad: pildivalija meediateegist, rippmenüüd, nupugrupid, tüpograafia.
  • Haagi JavaScripti töötleja elementor/frontend/init külge, mis on igasuguse kliendiloogika sisenemispunkt.

Pluginastruktuur ja põhiklass

Loome plugina Elementor Awesomesauce. Minimaalne failistruktuur:

1elementor-awesomesauce/
2├── elementor-awesomesauce.php ← entry point
3├── plugin.php ← plugin singleton class
4├── widgets/
5│ └── awesomesauce.php ← widget class
6└── assets/
7 └── js/
8 └── awesomesauce.js ← frontend JS handler

Peamine pluginifail, standardne WordPressi päis pluss laaduriklass koos ühilduvuskontrollidega. See on täpselt see struktuur, mida kirjeldatakse Elementori esimese lisamooduli juhendis. Allolev kood töötab Elementor 3.5+ ja Elementor 4.x versioonides: meetodid ilma iganenud _ eesliiteta, konstandid kaasaegsete PHP versioonide jaoks.

Lisa see kood faili elementor-awesomesauce.php. Fail peaks asuma kaustas /wp-content/plugins/elementor-awesomesauce/. Enne aktiveerimist tee täielik saidi varukoopia.

1<?php
2/**
3 * Plugin Name: Elementor Awesomesauce
4 * Description: Custom Elementor widget with live editing of text, images and styles.
5 * Plugin URI: https://techblog.sdstudio.top/
6 * Version: 1.0.0
7 * Author: TechBlog SD Studio
8 * Text Domain: elementor-awesomesauce
9 */
10
11if ( ! defined( 'ABSPATH' ) ) exit;
12
13final class Elementor_Awesomesauce {
14
15 const VERSION = '1.0.0';
16 const MINIMUM_ELEMENTOR_VERSION = '3.5.0';
17 const MINIMUM_PHP_VERSION = '7.4';
18
19 public function __construct() {
20 add_action( 'init', array( $this, 'i18n' ) );
21 add_action( 'plugins_loaded', array( $this, 'init' ) );
22 }
23
24 public function i18n() {
25 load_plugin_textdomain( 'elementor-awesomesauce' );
26 }
27
28 public function init() {
29 if ( ! did_action( 'elementor/loaded' ) ) {
30 add_action( 'admin_notices', array( $this, 'admin_notice_missing_main_plugin' ) );
31 return;
32 }
33
34 if ( ! version_compare( ELEMENTOR_VERSION, self::MINIMUM_ELEMENTOR_VERSION, '>=' ) ) {
35 add_action( 'admin_notices', array( $this, 'admin_notice_minimum_elementor_version' ) );
36 return;
37 }
38
39 if ( version_compare( PHP_VERSION, self::MINIMUM_PHP_VERSION, '<' ) ) {
40 add_action( 'admin_notices', array( $this, 'admin_notice_minimum_php_version' ) );
41 return;
42 }
43
44 require_once( 'plugin.php' );
45 }
46
47 public function admin_notice_missing_main_plugin() {
48 if ( isset( $_GET['activate'] ) ) {
49 unset( $_GET['activate'] );
50 }
51 $message = sprintf(
52 esc_html__( '"%1$s" requires "%2$s" to be installed and activated.', 'elementor-awesomesauce' ),
53 '<strong>' . esc_html__( 'Elementor Awesomesauce', 'elementor-awesomesauce' ) . '</strong>',
54 '<strong>' . esc_html__( 'Elementor', 'elementor-awesomesauce' ) . '</strong>'
55 );
56 printf( '<p>%1$s</p>', $message );
57 }
58
59 public function admin_notice_minimum_elementor_version() {
60 if ( isset( $_GET['activate'] ) ) {
61 unset( $_GET['activate'] );
62 }
63 $message = sprintf(
64 esc_html__( '"%1$s" requires "%2$s" version %3$s or greater.', 'elementor-awesomesauce' ),
65 '<strong>' . esc_html__( 'Elementor Awesomesauce', 'elementor-awesomesauce' ) . '</strong>',
66 '<strong>' . esc_html__( 'Elementor', 'elementor-awesomesauce' ) . '</strong>',
67 self::MINIMUM_ELEMENTOR_VERSION
68 );
69 printf( '<p>%1$s</p>', $message );
70 }
71
72 public function admin_notice_minimum_php_version() {
73 if ( isset( $_GET['activate'] ) ) {
74 unset( $_GET['activate'] );
75 }
76 $message = sprintf(
77 esc_html__( '"%1$s" requires "%2$s" version %3$s or greater.', 'elementor-awesomesauce' ),
78 '<strong>' . esc_html__( 'Elementor Awesomesauce', 'elementor-awesomesauce' ) . '</strong>',
79 '<strong>' . esc_html__( 'PHP', 'elementor-awesomesauce' ) . '</strong>',
80 self::MINIMUM_PHP_VERSION
81 );
82 printf( '<p>%1$s</p>', $message );
83 }
84}
85
86new Elementor_Awesomesauce();

Mis siin oluline on. Konstant MINIMUM_ELEMENTOR_VERSION, 3.5.0. Sellest versioonist alates hakkasid kehtima uued konventsioonid konksude ja meetodite nimetamiseks ilma _ eesliiteta. Elementor 4.x (praegune versioon 2026. aasta juuni seisuga) puhul töötab see sama kood muudatusteta, vidinate API 4.x-s ei katkenud. PHP, minimaalselt 7.4, kuid praktikas on 8.x juba de facto standard. Klass on deklareeritud kui final: see on sisenemispunkt, sellest ei ole vaja pärida.

Pluginaklass: singleton ja vidina registreerimine

Fail plugin.php, singleton, mis laadib JS-varasid ja registreerib vidina konksu elementor/widgets/register kaudu. See on peamine muudatus võrreldes vanade juhenditega: konks elementor/widgets/widgets_registered kuulutati iganenuks alates versioonist 3.5.0, meetod register_widget_type() asendati meetodiga register().

1<?php
2namespace ElementorAwesomesauce;
3
4use Elementor\Plugin as ElementorPlugin;
5
6class Plugin {
7
8 private static $_instance = null;
9
10 public static function instance() {
11 if ( is_null( self::$_instance ) ) {
12 self::$_instance = new self();
13 }
14 return self::$_instance;
15 }
16
17 public function widget_scripts() {
18 wp_register_script(
19 'elementor-awesomesauce',
20 plugins_url( '/assets/js/awesomesauce.js', __FILE__ ),
21 [ 'jquery' ],
22 false,
23 true
24 );
25 }
26
27 private function include_widgets_files() {
28 require_once( __DIR__ . '/widgets/awesomesauce.php' );
29 }
30
31 public function register_widgets( $widgets_manager ) {
32 $this->include_widgets_files();
33 $widgets_manager->register( new \ElementorAwesomesauceWidgets\Awesomesauce() );
34 }
35
36 public function __construct() {
37 add_action( 'elementor/frontend/after_register_scripts', [ $this, 'widget_scripts' ] );
38 add_action( 'elementor/widgets/register', [ $this, 'register_widgets' ] );
39 }
40}
41
42Plugin::instance();

Märkus: register_widgets aktsepteerib parameetrit $widgets_manager. Uues konksus antakse haldur otse kaasa, mitte ei hangita läbi ElementorPlugin::instance()->widgets_manager. Puhtam ja ilma lisaimportimiseta.

Vidinaklass: pärilus, juhtelemendid ja renderdus

Fail widgets/awesomesauce.php, plugina süda. Laienda Widget_Base, defineeri nimi, pealkiri, ikoon ja kategooria. Meetod register_controls() lisab kolm tekstivälja: üherealine, mitmerealine ja WYSIWYG. Meetod render() väljastab märgendi esiküljel ja content_template() defineerib Backbone'i malli reaalajas eelvaate jaoks redaktoris.

1<?php
2namespace ElementorAwesomesauceWidgets;
3
4use Elementor\Widget_Base;
5use Elementor\Controls_Manager;
6
7if ( ! defined( 'ABSPATH' ) ) exit;
8
9class Awesomesauce extends Widget_Base {
10
11 public function get_name() {
12 return 'awesomesauce';
13 }
14
15 public function get_title() {
16 return __( 'Awesomesauce', 'elementor-awesomesauce' );
17 }
18
19 public function get_icon() {
20 return 'eicon-pencil';
21 }
22
23 public function get_categories() {
24 return [ 'general' ];
25 }
26
27 public function get_keywords() {
28 return [ 'awesomesauce', 'custom', 'demo' ];
29 }
30
31 protected function register_controls() {
32 $this->start_controls_section(
33 'section_content',
34 [
35 'label' => __( 'Content', 'elementor-awesomesauce' ),
36 ]
37 );
38
39 $this->add_control(
40 'title',
41 [
42 'label' => __( 'Title', 'elementor-awesomesauce' ),
43 'type' => Controls_Manager::TEXT,
44 'default' => __( 'Title', 'elementor-awesomesauce' ),
45 ]
46 );
47
48 $this->add_control(
49 'description',
50 [
51 'label' => __( 'Description', 'elementor-awesomesauce' ),
52 'type' => Controls_Manager::TEXTAREA,
53 'default' => __( 'Description', 'elementor-awesomesauce' ),
54 ]
55 );
56
57 $this->add_control(
58 'content',
59 [
60 'label' => __( 'Content', 'elementor-awesomesauce' ),
61 'type' => Controls_Manager::WYSIWYG,
62 'default' => __( 'Content', 'elementor-awesomesauce' ),
63 ]
64 );
65
66 $this->end_controls_section();
67 }
68
69 protected function render() {
70 $settings = $this->get_settings_for_display();
71
72 $this->add_inline_editing_attributes( 'title', 'none' );
73 $this->add_inline_editing_attributes( 'description', 'basic' );
74 $this->add_inline_editing_attributes( 'content', 'advanced' );
75 ?>
76 <div class="elementor-awesomesauce">
77 <h2 <?php $this->print_render_attribute_string( 'title' ); ?>>
78 <?php $this->print_unescaped_setting( 'title' ); ?>
79 </h2>
80 <div <?php $this->print_render_attribute_string( 'description' ); ?>>
81 <?php $this->print_unescaped_setting( 'description' ); ?>
82 </div>
83 <div <?php $this->print_render_attribute_string( 'content' ); ?>>
84 <?php $this->print_unescaped_setting( 'content' ); ?>
85 </div>
86 </div>
87 <?php
88 }
89
90 protected function content_template() {
91 ?>
92 <#
93 view.addInlineEditingAttributes( 'title', 'none' );
94 view.addInlineEditingAttributes( 'description', 'basic' );
95 view.addInlineEditingAttributes( 'content', 'advanced' );
96 #>
97 <div class="elementor-awesomesauce">
98 <h2 {{{ view.getRenderAttributeString( 'title' ) }}}>{{{ settings.title }}}</h2>
99 <div {{{ view.getRenderAttributeString( 'description' ) }}}>{{{ settings.description }}}</div>
100 <div {{{ view.getRenderAttributeString( 'content' ) }}}>{{{ settings.content }}}</div>
101 </div>
102 <?php
103 }
104}

Mis on muutunud võrreldes aegunud juhenditega. Meetodid register_controls() ja content_template() kirjutatakse ilma _ eesliiteta, see on muudatus alates Elementor 3.1-st. render() väljundis kasuta print_render_attribute_string() ja print_unescaped_setting() otse echo asemel, see on kaasaegne lähenemine, mida soovitatakse alates Elementor 3.x-st ja mis töötab 4.x-s. Ikoon asendati fa fa-pencil-ilt (Font Awesome 4, eemaldatud tuumikust) eicon-pencil-iga Elementori enda komplektist.

Kohandatud väljad: meedia, valikud, tüpograafia

Tekstiväljad ei piira võimalusi. Vaatleme nelja juhtelemendi tüüpi, mis katavad enamiku reaalseid stsenaariume.

Meediaväli

Controls_Manager::MEDIA lisab standardse pildivaliku WordPressi meediateegist. Utils::get_placeholder_image_src() meetod töötab praegustes versioonides ja pakub halli kohatäidet, kui pilti pole valitud.

1$this->add_control(
2 'mask_image',
3 [
4 'label' => __( 'Mask Image', 'elementor-awesomesauce' ),
5 'type' => Controls_Manager::MEDIA,
6 'default' => [
7 'url' => \Elementor\Utils::get_placeholder_image_src(),
8 ],
9 ]
10);

Ripploend

Controls_Manager::SELECT, valik eelnevalt määratud väärtustest. Allpool on näide pealkirja HTML-sildi kohta:

1$this->add_control(
2 'title_tag',
3 [
4 'label' => __( 'Title HTML Tag', 'elementor-awesomesauce' ),
5 'type' => Controls_Manager::SELECT,
6 'default' => 'h2',
7 'options' => [
8 'h1' => 'H1',
9 'h2' => 'H2',
10 'h3' => 'H3',
11 'h4' => 'H4',
12 ],
13 ]
14);

Nupugrupp

Controls_Manager::CHOOSE kuvab visuaalseks valikuks ikoonide rea. Ikoonid, ainult eicon-* komplektist, mitte fa fa-*:

1$this->add_control(
2 'text_align',
3 [
4 'label' => __( 'Alignment', 'elementor-awesomesauce' ),
5 'type' => Controls_Manager::CHOOSE,
6 'options' => [
7 'left' => [
8 'title' => __( 'Left', 'elementor-awesomesauce' ),
9 'icon' => 'eicon-text-align-left',
10 ],
11 'center' => [
12 'title' => __( 'Center', 'elementor-awesomesauce' ),
13 'icon' => 'eicon-text-align-center',
14 ],
15 'right' => [
16 'title' => __( 'Right', 'elementor-awesomesauce' ),
17 'icon' => 'eicon-text-align-right',
18 ],
19 ],
20 'default' => 'center',
21 'toggle' => true,
22 ]
23);

Tüpograafia grupijuhtelemendi kaudu

Tüpograafia grupijuhtelement pakub täiskomplekti: font, suurus, tähevahe, paksus, kõik koos responsiivsete murdepunktidega. Täpsemalt Group_Control_Typography dokumentatsioonis. Võtmepunkt: Scheme_Typography on alates Elementor 3.x-st aegunud, ära seda kasuta. Selle asemel kas lingi globaalsete stiilidega või jäta scheme võti täielikult välja.

1use Elementor\Group_Control_Typography;
2
3$this->add_group_control(
4 Group_Control_Typography::get_type(),
5 [
6 'name' => 'content_typography',
7 'label' => __( 'Typography', 'elementor-awesomesauce' ),
8 'selector' => '{{WRAPPER}} .elementor-awesomesauce',
9 'fields_options' => [
10 'letter_spacing' => [
11 'range' => [
12 'min' => 0,
13 'max' => 100,
14 ],
15 ],
16 ],
17 ]
18);

Miks plugin, mitte functions.php

Kohandatud vidin teemas töötab. Kuid ainult seni, kuni teemat vahetad. Eraldi pluginaga saad kolm olulist eelist:

  • Tingimuslik laadimine. Elementor kutsub widget_scripts välja ainult siis, kui vidin on lehel tegelikult kuvatud, mitte kogu saidi ulatuses. Kümnete vidinatega projektide puhul on see märgatav kokkuhoid HTTP-päringutes.
  • Isolatsioon. PHP loogika, CSS ja JS ei segune teemaga. Vea leidmine ja parandamine võtab minuteid, mitte tunde functions.php 2000 rea sees tuhnides.
  • Ülekantavus. Aktiveeri plugin teisel saidil ja vidin töötab. Pole vaja kopeerimist ja käsitsi teede muutmist.
Arendaja kahe monitoriga laua taga

Video: otseesitlus tühjast pluginast töötava vidinani

Teooria on hea, kuid koodi tegevuses nägemine on kiirem. Selles 30-minutilises juhendis läbib autor kogu protsessi: tühjast kaustast kuni juhtelementide ja renderdusega vidinani.

⁉️🤔 Korduma kippuvad küsimused

Miks vidin Elementori paneelis ei ilmu?

Esmalt kontrolli registreerimise konksu. Alates Elementor 3.5-st kasutatakse elementor/widgets/register (mitte elementor/widgets/widgets_registered, see on aegunud). Teiseks: register_controls() meetod peab olema ilma _ eesliiteta. Kolmandaks: get_categories() peab tagastama massiivi olemasoleva kategooriaga, 'general' töötab alati. Neljandaks: tühjenda WordPressi vahemälu pärast plugina aktiveerimist.

Mis vahe on print_render_attribute_string() ja otsese echo vahel render() meetodis?

print_render_attribute_string() rakendab automaatselt atribuutide filtreid, sealhulgas inline editing ja Elementori andmeatribuute. Otsene echo neid andmeid ei paku, inline editing lihtsalt ei aktiveeru. Seadete väärtuste väljastamiseks kasuta print_unescaped_setting(), see käsitleb korrektselt escapingut kontrollerite sees.

Kas saab hakkama ilma eraldi JS-failita?

Jah, kui vidin renderdab ainult PHP märgendit ilma interaktiivsuseta. Kuid niipea kui ilmuvad sliderid, animatsioonid, AJAX-laadimine või igasugune kliendipoolne dünaamika, on JS kohustuslik. Isegi minimaalne handler (nagu ülaltoodud näites) annab sisenemispunkti tulevase loogika jaoks, ilma et peaks hiljem registreerimist ümber kirjutama.

Kas nimeruum on pluginas kohustuslik?

Formaalselt ei ole. Kuid ilma nimeruumita riskid klassinimede konfliktiga mõne teise plugina või teemaga, nimed nagu Plugin või Widget pole kaugeltki unikaalsed. Tootmiskeskkonnas on see kohustuslik. Prefiks ElementorAwesomesauceWidgets tagab praktiliselt unikaalsuse.

Kuidas uuendada vana vidinat, mis on kirjutatud aegunud juhendite järgi?

Migratsiooniplaan on kirjeldatud Elementori ametlikus aegumiste juhendis: (1) nimeta ümber _ eesliitega meetodid, _register_controls()register_controls(), _content_template()content_template(); (2) asenda konks elementor/widgets/register vastu ja registreerimismeetod $manager->register() vastu; (3) asenda fa fa-* ikoonid eicon-* vastu, eemalda Scheme_Typography. Pärast muudatusi tõsta MINIMUM_ELEMENTOR_VERSION praegusele versioonile ja testi vidinat kolmel tasandil: redaktori paneel, live preview, frontend.

Mida teha vanade vidinatega: migratsiooniplaan praegusele API-le

Kui sul on juba kohandatud vidinaid, mis on kirjutatud 2019-2021 juhendite järgi, ära satu paanikasse. Elementor säilitab tagasiühilduvuse aegumise handleritega kuni 8 põhiversiooni ulatuses. Kuid parem on kood uuendada nüüd, enne kui aegumisteated muutuvad fataalseteks vigadeks.

Migratsiooni kontrollnimekiri:

  • **Meetodid ilma _: kõikjal, kus näed _register_controls ja _content_template, eemalda eesliide.
  • Registreerimise konks: elementor/widgets/widgets_registeredelementor/widgets/register.
  • Registreerimismeetod: $manager->register_widget_type()$manager->register().
  • Ikoonid: fa fa-*eicon-* (Elementori loomulik komplekt) või dashicons-* (WordPressi komplekt).
  • Tüpograafia: Scheme_Typography → kas globaalsed stiilid läbi 'global' => [...] või otseväärtused ilma scheme võtmeta.

Pärast muudatusi testi vidinat kolmel tasandil: kas kontrollerite paneel avaneb redaktoris, kas live preview töötab (Backbone mall), kas frontend renderdub vigadeta. Ja pea meeles kuivkäivitust enne tootmiskeskkonda paigaldamist: Elementor jätab katkised kontrollerid vaikimisi vahele ilma tervet lehte kokku jooksutamata, seega visuaalne kontroll on kohustuslik.

Vana kood functions.php-s või plugin nullist: mida valida

Kui alustad uut projekti, siis ainult plugin. Ühtegi argumenti functions.php "poolt" pole enam alles: isegi 20-realise mikrovidina puhul tasub plugina struktuur end ära juba esimese teemauuendusega.

Kui sul on juba töötav kood teemas, eralda see pluginasse järgmise refaktoreerimise käigus. Protsess on lihtne: loo kaust ja plugina põhifail vastavalt ülaltoodud struktuurile, liiguta vidina klass widgets/ kausta, seadista registreerimine läbi elementor/widgets/register ja testi staging-keskkonnas. Praktikas võtab see tüüpilise vidina puhul 15-20 minutit.

Alusta selle juhendi baasklassist, kopeeri põhifail ja plugin.php skelett, asenda vidina nimi enda omaga. Ja kui küsimusi tekib, vaata Widgets sektsiooni saidil developers.elementor.com: see katab meedia renderdamist, kordusväljadega töötamist ja väljundi optimeerimist.