Skip to content

Kõik WordPressist, veebiarendusest — ja mitte ainult

🛠 Kuidas luua vidina pluginat WordPressile: samm-sammuline juhend

🛠 Kuidas luua vidina pluginat WordPressile: samm-sammuline juhend

💡 Kuidas ehitada WordPressi vidina pistikprogrammi

  • Loo kaust my-widget-plugin kataloogi wp-content/plugins/ sisse ja fail my-widget-plugin.php koos pistikprogrammi päisega, seejärel aktiveeri see administraatori paneelis
  • Deklareeri klass, mis laiendab klassi WP_Widget, ning kirjuta üle meetodid __construct(), form(), update() ja widget()
  • Registreeri vidin funktsiooniga register_widget() konksul widgets_init, et WordPress näeks seda nimekirjas
  • Meetodis form() kuva seadete väljad; meetodis update() puhasta ja salvesta andmed funktsiooni sanitize_text_field() abil
  • Meetodis widget() väljasta sisu avalikus vaates, põgenedes väärtused funktsioonidega esc_html() ja wp_kses_post()

1. Samm: pistikprogrammi põhja loomine

Vidin WordPressis ei ole lihtsalt üks rida failis functions.php. Kui soovid, et seaded säiliksid, administraatori vorm töötaks ja vidin ise jääks ellu järgmise teema uuenduse ajal, pead selle pakendama pistikprogrammina. See isoleerib koodi ja muudab vidina sõltumatuks igast teemavahetusest.

Alusta tühjast kaustast. Liigu kataloogi wp-content/plugins/ ja loo kataloog nimega my-widget-plugin. Selle sees loo fail nimega my-widget-plugin.php. See on fail, mida WordPress loeb aktiveerimisel esimesena. Ava fail ja lisa standardne pistikprogrammi päis:

1<?php
2/*
3Plugin Name: My Widget Plugin
4Plugin URI: https://www.wpexplorer.com/create-widget-plugin-wordpress/
5Description: Adds a customizable widget with text, textarea, checkbox, and dropdown.
6Version: 1.0
7Author: AJ Clarke
8Author URI: https://www.wpexplorer.com/
9License: GPL2
10*/

Salvesta fail. Nüüd mine WordPressi administraatori paneeli → Plugins. Kui pistikprogramm ilmub nimekirja, on põhi valmis. Klõpsa „Aktiveeri". See ei tee veel midagi kasulikku; me oleme ainult teatanud selle olemasolust. Kuid WordPress juba teab, et see pistikprogramm on olemas ja on valmis selle koodi käivitama. See on oluline põhimõte: kõigepealt registreerimine, seejärel loogika.

Kuidas pistikprogramm sisemiselt töötab, millised konksud aktiveerimisel käivituvad ja kuidas WordPress sinu faili leiab, on kõik käsitletud ülaltoodud videos. Liigume nüüd kõige huvitavama osa juurde: vidina klass.

2. Samm: vidina registreerimine WP_Widget kaudu

WordPress pakub sisseehitatud klassi nimega WP_Widget; see on olnud tuuma osa alates versioonist 2.8 ja jääb aluseks kõigile kohandatud vidinatele. Sa ei pea salvestamise loogikat, väljade genereerimist ega registreerimist nullist kirjutama: lihtsalt laienda klassi ja kirjuta üle neli meetodit.

Lisa see kood oma faili my-widget-plugin.php kohe pärast pistikprogrammi päist, enne sulgevat ?>:

1// Widget class
2class My_Custom_Widget extends WP_Widget {
3
4 public function __construct() {
5 parent::__construct(
6 'my_custom_widget',
7 __( 'My Custom Widget', 'text_domain' ),
8 array(
9 'customize_selective_refresh' => true,
10 )
11 );
12 }
13
14 public function form( $instance ) {
15 /* ... admin form ... */
16 }
17
18 public function update( $new_instance, $old_instance ) {
19 /* ... saving settings ... */
20 }
21
22 public function widget( $args, $instance ) {
23 /* ... frontend output ... */
24 }
25}
26
27// Widget registration
28function my_register_custom_widget() {
29 register_widget( 'My_Custom_Widget' );
30}
31add_action( 'widgets_init', 'my_register_custom_widget' );

Vaatame üle, mis siin toimub. Klass My_Custom_Widget laiendab klassi WP_Widget, mis annab sulle valmismeetodid nagu get_field_id() ja get_field_name() vormivälja atribuutide genereerimiseks. Konstruktoris anname ülemklassile kaasa kolm asja: unikaalse vidina ID (väikesed ladina tähed, tühikuteta, my_custom_widget), selle inimloetava nime (funktsioon __() muudab selle tõlgitavaks) ja valikute massiivi. Parameeter customize_selective_refresh => true võimaldab vidinal kohandajas värskendada ilma kogu lehte uuesti laadimata, väike detail, mis säästab seadistamise ajal palju peavalu.

Funktsioon my_register_custom_widget() kutsub konksul widgets_init välja register_widget(). Nii saab WordPress sinu vidinast teada. Ilma selle reata ei ilmu administraatori paneelis midagi.

Nüüd täidame meetodid form(), update() ja widget() päris loogikaga.

3. Samm: vidina vormi loomine administraatori paneelis

Vorm on see, mida administraator näeb vidinat külgribale lohistades. See koosneb väljadest: tekstisisestused, rippmenüüd, märkeruudud. Iga väli peab suutma oma väärtust salvestada ja kuvada praegust väärtust uuesti avamisel.

3.1. Funktsioon form() ja sisestusväljad

Lisa see kood oma klassi meetodisse form(). See loob viis välja: pealkirja, tekstisisestuse, tekstiala, märkeruudu ja rippmenüü.

1public function form( $instance ) {
2
3 $defaults = array(
4 'title' => '',
5 'text' => '',
6 'textarea' => '',
7 'checkbox' => '',
8 'select' => '',
9 );
10
11 $args = wp_parse_args( (array) $instance, $defaults );
12 $title = $args['title'];
13 $text = $args['text'];
14 $textarea = $args['textarea'];
15 $checkbox = $args['checkbox'];
16 $select = $args['select'];
17 ?>
18
19 <p>
20 <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
21 <?php _e( 'Widget Title', 'text_domain' ); ?>
22 </label>
23 <input class="widefat"
24 id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
25 name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
26 type="text"
27 value="<?php echo esc_attr( $title ); ?>" />
28 </p>
29
30 <p>
31 <label for="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>">
32 <?php _e( 'Text:', 'text_domain' ); ?>
33 </label>
34 <input class="widefat"
35 id="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>"
36 name="<?php echo esc_attr( $this->get_field_name( 'text' ) ); ?>"
37 type="text"
38 value="<?php echo esc_attr( $text ); ?>" />
39 </p>
40
41 <p>
42 <label for="<?php echo esc_attr( $this->get_field_id( 'textarea' ) ); ?>">
43 <?php _e( 'Textarea:', 'text_domain' ); ?>
44 </label>
45 <textarea class="widefat"
46 id="<?php echo esc_attr( $this->get_field_id( 'textarea' ) ); ?>"
47 name="<?php echo esc_attr( $this->get_field_name( 'textarea' ) ); ?>"><?php
48 echo wp_kses_post( $textarea );
49 ?></textarea>
50 </p>
51
52 <p>
53 <input id="<?php echo esc_attr( $this->get_field_id( 'checkbox' ) ); ?>"
54 name="<?php echo esc_attr( $this->get_field_name( 'checkbox' ) ); ?>"
55 type="checkbox"
56 value="1"
57 <?php checked( '1', $checkbox ); ?> />
58 <label for="<?php echo esc_attr( $this->get_field_id( 'checkbox' ) ); ?>">
59 <?php _e( 'Show additional block', 'text_domain' ); ?>
60 </label>
61 </p>
62
63 <p>
64 <label for="<?php echo $this->get_field_id( 'select' ); ?>">
65 <?php _e( 'Display variant', 'text_domain' ); ?>
66 </label>
67 <select name="<?php echo $this->get_field_name( 'select' ); ?>"
68 id="<?php echo $this->get_field_id( 'select' ); ?>"
69 class="widefat">
70 <?php
71 $options = array(
72 '' => __( '— Select —', 'text_domain' ),
73 'option_1' => __( 'Option 1', 'text_domain' ),
74 'option_2' => __( 'Option 2', 'text_domain' ),
75 'option_3' => __( 'Option 3', 'text_domain' ),
76 );
77 foreach ( $options as $key => $name ) {
78 printf(
79 '<option value="%s" %s>%s</option>',
80 esc_attr( $key ),
81 selected( $select, $key, false ),
82 esc_html( $name )
83 );
84 }
85 ?>
86 </select>
87 </p>
88
89<?php }

Pööra tähelepanu kahele asjale. Esiteks, me asendasime iganenud funktsiooni extract() otsese massiivipöördumisega. extract() on juba ammu WordPressi kodeerimisstandarditest välja arvatud; see loob muutujad massiivi võtmete nimega, mis on ebaturvaline ja muudab silumise raskemaks. Teiseks, iga väljundväärtus lastakse läbi funktsiooni esc_attr(), wp_kses_post() või esc_html(). See ei ole paranoia: andmed andmebaasist võivad tulla ükskõik kust ja puhastamine on kohustuslik.

3.2. Funktsioon update() salvestamiseks

Meetodit update() kutsutakse välja, kui vidina vormis klõpsatakse nuppu „Salvesta". Selle ülesanne on iga väli valideerida ja tagastada puhastatud massiiv andmebaasi kirjutamiseks.

1public function update( $new_instance, $old_instance ) {
2 $instance = $old_instance;
3
4 $instance['title'] = isset( $new_instance['title'] )
5 ? sanitize_text_field( $new_instance['title'] ) : '';
6 $instance['text'] = isset( $new_instance['text'] )
7 ? sanitize_text_field( $new_instance['text'] ) : '';
8 $instance['textarea'] = isset( $new_instance['textarea'] )
9 ? wp_kses_post( $new_instance['textarea'] ) : '';
10 $instance['checkbox'] = isset( $new_instance['checkbox'] ) ? 1 : false;
11 $instance['select'] = isset( $new_instance['select'] )
12 ? sanitize_text_field( $new_instance['select'] ) : '';
13
14 return $instance;
15}

Siin kasutame sanitize_text_field() asemel wp_strip_all_tags(), sest see normaliseerib ka tühikud, eemaldab nähtamatud kontrollmärgid ja teisendab stringi turvaliseks UTF-8-ks. See on põhjalikum puhastus. wp_strip_all_tags() jätab „toore" teksti koos kõigi tühikuartefaktidega. Tekstivormi väljade puhul vali alati sanitize_text_field().

Tekstiala säilitab wp_kses_post(): see lubab põhilist HTML-i (lingid, rasvane tekst, loendid), kuid eemaldab skriptid. Märkeruut tagastab 1 või false, mis on andmebaasis loetav ja ühemõtteline.

4. Samm: vidina kuvamine avalikus vaates

Funktsioon widget() on see, mida külastaja näeb. See saab kaks parameetrit: $args (vidina ümbris, sildid enne ja pärast pealkirja ning külgriba) ja $instance (selle konkreetse eksemplari salvestatud seaded).

1public function widget( $args, $instance ) {
2
3 $title = isset( $instance['title'] )
4 ? apply_filters( 'widget_title', $instance['title'] ) : '';
5 $text = isset( $instance['text'] ) ? $instance['text'] : '';
6 $textarea = isset( $instance['textarea'] ) ? $instance['textarea'] : '';
7 $select = isset( $instance['select'] ) ? $instance['select'] : '';
8 $checkbox = ! empty( $instance['checkbox'] ) ? $instance['checkbox'] : false;
9
10 echo $args['before_widget'];
11
12 echo '<div class="widget-text wp_widget_plugin_box">';
13
14 if ( $title ) {
15 echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
16 }
17
18 if ( $text ) {
19 echo '<p>' . esc_html( $text ) . '</p>';
20 }
21
22 if ( $textarea ) {
23 echo '<div class="widget-textarea">' . wp_kses_post( $textarea ) . '</div>';
24 }
25
26 if ( $select ) {
27 echo '<p class="widget-select">' . esc_html( $select ) . '</p>';
28 }
29
30 if ( $checkbox ) {
31 echo '<p class="widget-checkbox-result">' . esc_html__( 'Additional block activated', 'text_domain' ) . '</p>';
32 }
33
34 echo '</div>';
35
36 echo $args['after_widget'];
37}

Võtmepunkt siin: me asendasime extract( $args ) otsese pöördumisega $args['before_widget'] kaudu. Põhjus on sama: extract() on iganenud ja ebaturvaline. Samuti mähkisime väljundi funktsiooni esc_html() kõikjal, kus on oodata tavalist teksti (pealkiri, tekstistring, valiku väärtus). Tekstiala kuvatakse läbi wp_kses_post(), nii et kui administraator sisestas lingi või rasvase teksti, siis need säilivad.

CSS klass wp_widget_plugin_box võimaldab sul plokki teema stiililehest stiilida. Võid selle julgelt ümber nimetada, veendu vaid, et klass on unikaalne ega lähe vastuollu teema klassidega.

Pistikprogrammi täielik kood

Paneme kõik kokku. Siin on täielik fail my-widget-plugin.php, kopeerimiseks ja aktiveerimiseks valmis:

1<?php
2/*
3Plugin Name: My Widget Plugin
4Plugin URI: https://www.wpexplorer.com/create-widget-plugin-wordpress/
5Description: Adds a customizable widget with text, textarea, checkbox, and dropdown.
6Version: 1.0
7Author: AJ Clarke
8Author URI: https://www.wpexplorer.com/
9License: GPL2
10*/
11
12class My_Custom_Widget extends WP_Widget {
13
14 public function __construct() {
15 parent::__construct(
16 'my_custom_widget',
17 __( 'My Custom Widget', 'text_domain' ),
18 array( 'customize_selective_refresh' => true )
19 );
20 }
21
22 public function form( $instance ) {
23 $defaults = array(
24 'title' => '', 'text' => '', 'textarea' => '',
25 'checkbox' => '', 'select' => ''
26 );
27 $args = wp_parse_args( (array) $instance, $defaults );
28 $title = $args['title'];
29 $text = $args['text'];
30 $textarea = $args['textarea'];
31 $checkbox = $args['checkbox'];
32 $select = $args['select'];
33 ?>
34 <p>
35 <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
36 <?php _e( 'Widget Title', 'text_domain' ); ?>
37 </label>
38 <input class="widefat"
39 id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
40 name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
41 type="text" value="<?php echo esc_attr( $title ); ?>" />
42 </p>
43 <p>
44 <label for="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>">
45 <?php _e( 'Text:', 'text_domain' ); ?>
46 </label>
47 <input class="widefat"
48 id="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>"
49 name="<?php echo esc_attr( $this->get_field_name( 'text' ) ); ?>"
50 type="text" value="<?php echo esc_attr( $text ); ?>" />
51 </p>
52 <p>
53 <label for="<?php echo esc_attr( $this->get_field_id( 'textarea' ) ); ?>">
54 <?php _e( 'Textarea:', 'text_domain' ); ?>
55 </label>
56 <textarea class="widefat"
57 id="<?php echo esc_attr( $this->get_field_id( 'textarea' ) ); ?>"
58 name="<?php echo esc_attr( $this->get_field_name( 'textarea' ) ); ?>"><?php
59 echo wp_kses_post( $textarea );
60 ?></textarea>
61 </p>
62 <p>
63 <input id="<?php echo esc_attr( $this->get_field_id( 'checkbox' ) ); ?>"
64 name="<?php echo esc_attr( $this->get_field_name( 'checkbox' ) ); ?>"
65 type="checkbox" value="1" <?php checked( '1', $checkbox ); ?> />
66 <label for="<?php echo esc_attr( $this->get_field_id( 'checkbox' ) ); ?>">
67 <?php _e( 'Show additional block', 'text_domain' ); ?>
68 </label>
69 </p>
70 <p>
71 <label for="<?php echo $this->get_field_id( 'select' ); ?>">
72 <?php _e( 'Display variant', 'text_domain' ); ?>
73 </label>
74 <select name="<?php echo $this->get_field_name( 'select' ); ?>"
75 id="<?php echo $this->get_field_id( 'select' ); ?>" class="widefat">
76 <?php
77 $options = array(
78 '' => __( '— Select —', 'text_domain' ),
79 'option_1' => __( 'Option 1', 'text_domain' ),
80 'option_2' => __( 'Option 2', 'text_domain' ),
81 'option_3' => __( 'Option 3', 'text_domain' ),
82 );
83 foreach ( $options as $key => $name ) {
84 printf(
85 '<option value="%s" %s>%s</option>',
86 esc_attr( $key ),
87 selected( $select, $key, false ),
88 esc_html( $name )
89 );
90 }
91 ?>
92 </select>
93 </p>
94 <?php
95 }
96
97 public function update( $new_instance, $old_instance ) {
98 $instance = $old_instance;
99 $instance['title'] = isset( $new_instance['title'] )
100 ? sanitize_text_field( $new_instance['title'] ) : '';
101 $instance['text'] = isset( $new_instance['text'] )
102 ? sanitize_text_field( $new_instance['text'] ) : '';
103 $instance['textarea'] = isset( $new_instance['textarea'] )
104 ? wp_kses_post( $new_instance['textarea'] ) : '';
105 $instance['checkbox'] = isset( $new_instance['checkbox'] ) ? 1 : false;
106 $instance['select'] = isset( $new_instance['select'] )
107 ? sanitize_text_field( $new_instance['select'] ) : '';
108 return $instance;
109 }
110
111 public function widget( $args, $instance ) {
112 $title = isset( $instance['title'] )
113 ? apply_filters( 'widget_title', $instance['title'] ) : '';
114 $text = isset( $instance['text'] ) ? $instance['text'] : '';
115 $textarea = isset( $instance['textarea'] ) ? $instance['textarea'] : '';
116 $select = isset( $instance['select'] ) ? $instance['select'] : '';
117 $checkbox = ! empty( $instance['checkbox'] ) ? $instance['checkbox'] : false;
118
119 echo $args['before_widget'];
120 echo '<div class="widget-text wp_widget_plugin_box">';
121
122 if ( $title ) {
123 echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
124 }
125 if ( $text ) {
126 echo '<p>' . esc_html( $text ) . '</p>';
127 }
128 if ( $textarea ) {
129 echo '<div class="widget-textarea">' . wp_kses_post( $textarea ) . '</div>';
130 }
131 if ( $select ) {
132 echo '<p class="widget-select">' . esc_html( $select ) . '</p>';
133 }
134 if ( $checkbox ) {
135 echo '<p class="widget-checkbox-result">'
136 . esc_html__( 'Additional block activated', 'text_domain' ) . '</p>';
137 }
138
139 echo '</div>';
140 echo $args['after_widget'];
141 }
142}
143
144function my_register_custom_widget() {
145 register_widget( 'My_Custom_Widget' );
146}
147add_action( 'widgets_init', 'my_register_custom_widget' );

Aseta see fail kataloogi wp-content/plugins/my-widget-plugin/, aktiveeri pistikprogramm ja lohista vidin läbi Välimus → Vidinad mõnele külgribale. Täida väljad, salvesta ja kontrolli oma saiti.

Valmis kood on saadaval ka GitHubis: wpexplorer/my-widget-plugin, kus saad seda võrrelda originaalse 2017. aasta versiooniga ja näha täpselt, mida me muutsime.

⁉️🤔 Korduma kippuvad küsimused

Miks panna vidin pistikprogrammi, kui saab lihtsalt koodi lisada teema faili functions.php?

Kood failis functions.php on seotud aktiivse teemaga. Vaheta teemat ja vidin kaob. Pistikprogramm töötab teemast sõltumatult. Lisaks saab pistikprogrammi erinevatel saitidel valikuliselt aktiveerida, samas kui teema koodi ei saa. Kui vidin lahendab ärivajadust (näiteks konkreetse paigutusega tellimisvormi kuvamine), kuulub see pistikprogrammi.

Miks on sanitize_text_field() parem kui wp_strip_all_tags()?

sanitize_text_field() ei eemalda lihtsalt HTML-silte; see normaliseerib ka tühikud, eemaldab nähtamatud kontrollmärgid ja teisendab stringi UTF-8-ks. See on põhjalikum puhastus. wp_strip_all_tags() jätab „toore" teksti koos kõigi tühikuartefaktidega. Tekstivormi väljade puhul vali alati sanitize_text_field().

Miks te asendasite extract() otsese massiivipöördumisega?

Funktsioon extract() on WordPressi kodeerimisstandarditest välja arvatud alates versioonist 4.3. See loob kohalikus skoobis muutujad massiivi võtmete nimega; kui võti kattub olemasoleva muutujaga, kirjutad selle üle ja saad raskesti leitava vea. Otsene pöördumine nagu $args['before_widget'] on loetav ja turvaline.

Kas ma pean toetama plokkvidinaid (Gutenberg)?

Klassikaline WP_Widget töötab plokipõhiste külgribadega tagasiühilduvuse kaudu: WordPress mähib selle automaatselt pärandvidina plokki. See on enamiku stsenaariumide jaoks piisav. Kui soovid luua tõeliselt natiivseid plokke, vaata Block Editor Handbook, millel on eraldi API. Kuid WP_Widget-iga alustamine on lihtsam: kood on lühem, silumine kiirem ja see töötab kõigis WordPressi versioonides ilma täiendavate ühilduvuspistikprogrammideta.

Kuidas siluda vidinat, mis ei ilmu administraatori paneelis?

Kontrolli kolme asja. Esiteks: kas konks widgets_init käivitus? Lisa registreerimisfunktsiooni error_log( 'Widget registered' ) ja kontrolli logisid. Teiseks: kas konstruktoris on fataalne viga? Luba failis wp-config.php WP_DEBUG. Kolmandaks: kas klassi nimi funktsioonis register_widget() ühtib klassi nimega, mis laiendab WP_Widget? Üksainus kirjaviga ja vidin ei ilmu.

Mis saab edasi: mallist oma vidinani

Oleme ehitanud töötava pistikprogrammi viie väljatüübiga. See ei ole valmistoode; see on põhi. Võta see oma aluseks ja kohanda seda oma vajadustele. Vajad tellimisvormi vidinat? Asenda tekstiväljad e-posti ja nimeväljadega ning lisa meetodis widget() meiliteenuse API kutse. Vajad plokki kampaaniate ja bänneritega? Laadi pildid meedia üleslaadija kaudu ja kuva need oma märgendis. Mehaanika on alati sama: form() joonistab väljad, update() salvestab need, widget() kuvab väljundi.

Alusta väikeselt: kopeeri ülaltoodud täielik kood, aktiveeri see testsaidil ja katseta seadetega. Kui oled aru saanud, kuidas andmed vormist avalikku vaatesse liiguvad, hakka lisama oma välju. Ja kui vidin jookseb kokku valge ekraaniga, mine tagasi 2. sammu juurde ja kontrolli konstruktorit.