
🛠 Kuidas luua vidina pluginat WordPressile: samm-sammuline juhend
💡 Kuidas ehitada WordPressi vidina pistikprogrammi
- Loo kaust
my-widget-pluginkataloogiwp-content/plugins/sisse ja failmy-widget-plugin.phpkoos pistikprogrammi päisega, seejärel aktiveeri see administraatori paneelis - Deklareeri klass, mis laiendab klassi
WP_Widget, ning kirjuta üle meetodid__construct(),form(),update()jawidget() - Registreeri vidin funktsiooniga
register_widget()konksulwidgets_init, et WordPress näeks seda nimekirjas - Meetodis
form()kuva seadete väljad; meetodisupdate()puhasta ja salvesta andmed funktsioonisanitize_text_field()abil - Meetodis
widget()väljasta sisu avalikus vaates, põgenedes väärtused funktsioonidegaesc_html()jawp_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 /* 3 Plugin Name: My Widget Plugin 4 Plugin URI: https://www.wpexplorer.com/create-widget-plugin-wordpress/ 5 Description: Adds a customizable widget with text, textarea, checkbox, and dropdown. 6 Version: 1.0 7 Author: AJ Clarke 8 Author URI: https://www.wpexplorer.com/ 9 License: 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 2 class 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 28 function my_register_custom_widget() { 29 register_widget( 'My_Custom_Widget' ); 30 } 31 add_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üü.
1 public 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.
1 public 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).
1 public 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 /* 3 Plugin Name: My Widget Plugin 4 Plugin URI: https://www.wpexplorer.com/create-widget-plugin-wordpress/ 5 Description: Adds a customizable widget with text, textarea, checkbox, and dropdown. 6 Version: 1.0 7 Author: AJ Clarke 8 Author URI: https://www.wpexplorer.com/ 9 License: GPL2 10 */ 11 12 class 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 144 function my_register_custom_widget() { 145 register_widget( 'My_Custom_Widget' ); 146 } 147 add_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 alatisanitize_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_Widgettöö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. KuidWP_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_initkäivitus? Lisa registreerimisfunktsioonierror_log( 'Widget registered' )ja kontrolli logisid. Teiseks: kas konstruktoris on fataalne viga? Luba failis wp-config.phpWP_DEBUG. Kolmandaks: kas klassi nimi funktsioonisregister_widget()ühtib klassi nimega, mis laiendabWP_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.



