Die Widgetklasse

Durch die Widget-API von WordPress ist schon eine gewisse Grundstruktur im PHP-Code für das neue Widget vorgegeben. Das ist recht praktisch, denn so muss man lediglich die Widget-Klasse von WordPress erweitern und sich nicht alles komplett neu aus den Fingern saugen. In diesem kleinen Beispiel, möchte ich nun zeigen, wie man ein simples Textwidget erstellt. Also ein Widget, dem man einen Titel und einen Freitext mitgeben kann.

Zunächst wird eine PHP-Datei erstellt, welche den schönen Namen “my-sidebar-widget.php” trägt. In diese Datei kommt der gesamte Code des Widgets – welches ich phantasievoller Weise auch “My Sidebar Widget” getauft habe – hinein.

Als erste Amtshandlung wird die Klasse WP-Widget erweitert.

1
2
// Klassenaufruf
class My_Sidebar_Widget extends WP_Widget {}

Dies führt dazu, dass bei Aufruf des Widgets alles über die Widget-API von WordPress läuft und somit auch alles richtig in WordPress eingebunden wird.

Im nächsten Schritt werden die “Standardfunktionen” erstellt. Also der Konstruktor der Klasse, das Formular mit den Einstellungen, die Updatefunktion um die Einstellungen zu speichern und die eigentliche Widgetfunktion zur Ausgabe des Widgets im Frontend.

1
2
3
4
5
// Grundfunktionen
public function __construct() {}
public function form($instance) {}
public function update($new_instance, $old_instance) {}
public function widget($args, $instance) {}

Dies sind auch die vier Funktionen, welche ihre Gegenstücke in der Widget-API erweitern. Oder einfacher ausgedrückt, diese werden unbedingt gebraucht.

Der Konstruktor

Dieser enthält alle wichtigen Befehle zur Initialisierung des Widgets. Also den Widgetnamen, eine Kurzbeschreibung, eventuelle Hinweise zur Übersetzung der Texte.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Konstruktor
public function __construct() {
    $this->var_sTextdomain = 'my-sidebar-widget';

    /**
     * Übersetzungsfunktion für das Widget aktivieren.
     * Die Sprachdateien liegen im Ordner "l10n" innerhalb des Widgets.
     */

    if(function_exists('load_plugin_textdomain')) {
        load_plugin_textdomain($this->var_sTextdomain, PLUGINDIR . '/' . dirname(plugin_basename(__FILE__)) . '/l10n', dirname(plugin_basename(__FILE__)) . '/l10n');
    }

    $widget_options = array(
        'classname' => 'my_sidebar_widget',
        'description' => __('A little demonstration on programming a wordpress widget.', $this->var_sTextdomain)
    );

    $control_options = array();

    $this->WP_Widget('my_sidebar_widget', __('My Sidebar Widget', $this->var_sTextdomain), $widget_options, $control_options);
} // END function __construct()

Wie hier zu erkennen ist, wird bereits die Textdomain für die Überstzung definiert und WordPress informiert, wo die Übersetzungsdateien liegen. Auch werden hier die Widgetoptionen und die Kontrolloptionen an die Widget-API übergeben. Zu den Kontrolloptionen muss gesagt sein, dass dieses Array im Allgemeinen leer bleiben kann, es sei denn, man braucht mehr als 250 Pixel Breite für die Widgeteinstellungen. In diesem Fall:

1
$control_options = array('width' => 400);

Die Werte des Arrays “$widget_options” sind eigentlich fast selbsterklärend. Classname setzt den Namen der CSS-Klasse und Description ist die Kurzbeschreibung des Widgets, welche in der Widgetübersicht zu sehen ist.

Für eine Breite von 400 Pixel.

Das Widgetformular

In dieser Funktion wird das Formular des Widgets erstellt.  Also der Teil, in dem dann später der Titel und der Freitext dieses kleinen Demowidgets eingegeben werden kann.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Formular
public function form($instance) {
    /**
     * Standardwerte
     *
     * @var array
     */

    $instance = wp_parse_args((array) $instance, array(
        'my-widget-title' => '',
        'my-widget-text' => ''
    ));

    // Titel
    echo '<p style="border-bottom: 1px solid #DFDFDF;"><strong>' . __('Title', $this->var_sTextdomain) . '</strong></p>';
    echo '<p><input id="' . $this->get_field_id('my-widget-title') . '" name="' . $this->get_field_name('my-widget-title') . '" type="text" value="' . $instance['my-widget-title'] . '" /></p>';
    echo '<p style="clear:both;"></p>';

    // Textfeld
    echo '<p style="border-bottom: 1px solid #DFDFDF;"><strong>' . __('Textarea:', $this->var_sTextdomain) . '</strong></p>';
    echo '<p><span style="display:inline-block;">' . __('Write some text here ...', $this->var_sTextdomain) . '</span><textarea style="width:100%;" id="' . $this->get_field_id('my-widget-text') . '" rows="10" name="' . $this->get_field_name('my-widget-text') . '">' . $instance['my-widget-text'] . '</textarea></p>';
    echo '<p style="clear:both;"></p>';
} // END function form($instance)

Das Array $instance enthält hier die Werte aus der Datenbank, sofern diese gesetzt sind. Sollte für ein Feld noch kein Wert gesetzt sein, so werden mit wp_parse_args die Standardwerte in das Array eingefügt. Zum PHP-Code dieser Funktion verliere ich nicht viele Worte, ich gehe einfach mal davon aus, dass zu erkennen ist, dass hier ein HTML-Formular erstellt wird in welches die Werte aus der Datenbank eingefügt werden.

Speichern der Einstellungen

Hier werden nun die Eingaben aus dem Formular übernommen, geprüft und gespeichert.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Speichern
public function update($new_instance, $old_instance) {
            $instance = $old_instance;

    /**
     * Standrdwerte setzen
     *
     * @var array
     */

    $new_instance = wp_parse_args((array) $new_instance, array(
        'my-widget-title' => '',
        'my-widget-text' => ''
    ));

    /**
     * Einstellungen, welche über das Formular kommen auf ihre Richtigkeit hin prüfen.
     * Somit wird sicher gestellt, dass kein Schadcode eingeschleust werden kann.
     *
     * @var array
     */

    $instance['my-widget-title'] = (string) strip_tags($new_instance['my-widget-title']);
    $instance['my-widget-text'] = (string) strip_tags($new_instance['my-widget-text']);

    /**
     * Array mit den Einstellungen an die verarbeitende Funktion zurückliefern.
     * Diese liegt in der Klasse WP_Widget und speichert nun die Optionen
     * in der Datenbank.
     */

    return $instance;
} // END function update($new_instance, $old_instance)

Auch hier können wieder Standardwerte definiert werden, welche gespeichert werden, sollte eines der Formularfelder nichts enthalten. Dies kann zur Fehlerreduzierung durchaus nützlich sein.

Ausgabe des Widgets

In dieser Funktion wird die Ausgabe des Widgets gesteuert. Also was soll wann und wie ausgegeben werden.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Ausgabe
public function widget($args, $instance) {
    extract($args);

    echo $before_widget;

    $title = (empty($instance['my-widget-title'])) ? '' : apply_filters('my_widget_title', $instance['my-widget-title']);

    if(!empty($title)) {
        echo $before_title . $title . $after_title;
    } // END if(!empty($title))

    echo $this->my_widget_html_output($instance);
    echo $after_widget;
} // END function widget($args, $instance)
My Sidebar Widget Ausgabe

My Sidebar Widget Ausgabe

Wie hier zu sehen ist, bevorzuge ich für die Ausgabe des eigentlichen Inhalts des Widgets eine eigene Funktion, da ich persönlich dieses Vorgehen übersichtlicher finde und somit in dieser Funktion lediglich den “Rahmen” des Widgets erstellen lasse. Aber dies kann letztlich jeder für sich selbst entscheiden.

Und wenn man nun auch etwas Text und einen Titel im Backend in den Widgeteinstellungen eingegeben hat, könnte das Widget im Frontend so oder so ähnlich aussehen.

Widget initialisieren

Natürlich muss das Widget selbst noch initialisiert werden, denn sonst wei0t die Widget-API nichts von diesem Widget.

1
add_action('widgets_init', create_function('', 'return register_widget("My_Sidebar_Widget");'));

Durch diese Initialisierung wird das Widget an die Widget-API übergeben. Die Konstruktorfunktionen werden automatisch gestartet und das Widget wird mit den dort hinterlegten Optionen in WordPress eingebunden.

Gesamter PHP-Code

Und um die Verwirrung nicht zu groß werden zu lassen, hier nochmal der gesamte PHP-Code des Beispielwidgets.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
<?php
/**
 * Plugin Name: My Sidebar Widget
 * Plugin URI: http://ppfeufer.de/wordpress-grundstruktur-eines-sidebarwidgets/
 * Description: Ein simples Sidebarwidget um zu zeigen, wie Widgets bei WordPress aufgebaut sind.
 * Version: 0.1
 * Author: H.-Peter Pfeufer
 * Author URI: http://ppfeufer.de
 */

if(!class_exists('My_Sidebar_Widget')) {
    /**
     * Class My_Sidebar_Widget
     *
     * Diese Klasse ist die Grundstruktur eines WordPress-Widgets, wie es
     * über die Widgetseite unter Design in einen der Widgetbereiche des Themes
     * eingefügt werden kann.
     *
     * Gezeigt wird hier ein simples Textwidget.
     * Eingabe von HTML ist hier im Text nicht möglich,
     * die Formatierung des Textes erfolgt automatisch via wpautop();
     *
     * @author ppfeufer
     */

    class My_Sidebar_Widget extends WP_Widget {
        private $var_sTextdomain; // Textdomain für die Übersetzungen des Widgets

        /**
         * Konstruktorfunktion (PHP4).
         *
         * Diese Funktion muss den gleichen Namen haben, wie das Klasse des Widgets.
         * Somit wird diese Funktion direkt nach dem Initialisieren der Klasse
         * aufgerufen und ausgeführt. Da dies der Konstuktor für PHP4 ist wird durch diesen
         * direkt die Konstruktorfunktion für PHP5 aufgerufen.
         *
         * @see My_Sidebar_Widget::__construct()
         */

        public function My_Sidebar_Widget() {
            My_Sidebar_Widget::__construct();
        } // END function My_Sidebar_Widget()

        /**
         * Konstruktorfunktion (PHP5).
         *
         * @param array $widget_options Optional Passed to wp_register_sidebar_widget()
         *   - description: shown on the configuration page
         *   - classname
         * @param array $control_options Optional Passed to wp_register_widget_control()
         *   - width: required if more than 250px
         *   - height: currently not used but may be needed in the future
         */

        public function __construct() {
            $this->var_sTextdomain = 'my-sidebar-widget';

            /**
             * Übersetzungsfunktion für das Widget aktivieren.
             * Die Sprachdateien liegen im Ordner "l10n" innerhalb des Widgets.
             */

            if(function_exists('load_plugin_textdomain')) {
                load_plugin_textdomain($this->var_sTextdomain, PLUGINDIR . '/' . dirname(plugin_basename(__FILE__)) . '/l10n', dirname(plugin_basename(__FILE__)) . '/l10n');
            }

            $widget_options = array(
                'classname' => 'my_sidebar_widget',
                'description' => __('A little demonstration on programming a wordpress widget.', $this->var_sTextdomain)
            );

            $control_options = array();

            $this->WP_Widget('my_sidebar_widget', __('My Sidebar Widget', $this->var_sTextdomain), $widget_options, $control_options);
        } // END function __construct()

        /**
         * Widgetformular.
         * Der Einstellungsbereich des Widgets.
         *
         * @see WP_Widget::form()
         */

        public function form($instance) {
            /**
             * Standardwerte
             *
             * @var array
             */

            $instance = wp_parse_args((array) $instance, array(
                'my-widget-title' => '',
                'my-widget-text' => ''
            ));

            // Titel
            echo '<p style="border-bottom: 1px solid #DFDFDF;"><strong>' . __('Title', $this->var_sTextdomain) . '</strong></p>';
            echo '<p><input id="' . $this->get_field_id('my-widget-title') . '" name="' . $this->get_field_name('my-widget-title') . '" type="text" value="' . $instance['my-widget-title'] . '" /></p>';
            echo '<p style="clear:both;"></p>';

            // Textfeld
            echo '<p style="border-bottom: 1px solid #DFDFDF;"><strong>' . __('Textarea:', $this->var_sTextdomain) . '</strong></p>';
            echo '<p><span style="display:inline-block;">' . __('Write some text here ...', $this->var_sTextdomain) . '</span><textarea style="width:100%;" id="' . $this->get_field_id('my-widget-text') . '" rows="10" name="' . $this->get_field_name('my-widget-text') . '">' . $instance['my-widget-text'] . '</textarea></p>';
            echo '<p style="clear:both;"></p>';
        } // END function form($instance)

        /**
         * Widgeteinstellungen in die Datenbank schreiben.
         *
         * @see WP_Widget::update()
         */

        public function update($new_instance, $old_instance) {
            $instance = $old_instance;

            /**
             * Standrdwerte setzen
             *
             * @var array
             */

            $new_instance = wp_parse_args((array) $new_instance, array(
                'my-widget-title' => '',
                'my-widget-text' => ''
            ));

            /**
             * Einstellungen, welche über das Formular kommen auf ihre Richtigkeit hin prüfen.
             * Somit wird sicher gestellt, dass kein Schadcode eingeschleust werden kann.
             *
             * @var array
             */

            $instance['my-widget-title'] = (string) strip_tags($new_instance['my-widget-title']);
            $instance['my-widget-text'] = (string) strip_tags($new_instance['my-widget-text']);

            /**
             * Array mit den Einstellungen an die verarbeitende Funktion zurückliefern.
             * Diese liegt in der Klasse WP_Widget und speichert nun die Optionen
             * in der Datenbank.
             */

            return $instance;
        } // END function update($new_instance, $old_instance)

        /**
         * Ausgabe des Widgets im Frontend.
         *
         * @see WP_Widget::widget()
         */

        public function widget($args, $instance) {
            extract($args);

            echo $before_widget;

            $title = (empty($instance['my-widget-title'])) ? '' : apply_filters('my_widget_title', $instance['my-widget-title']);

            if(!empty($title)) {
                echo $before_title . $title . $after_title;
            } // END if(!empty($title))

            echo $this->my_widget_html_output($instance);
            echo $after_widget;
        } // END function widget($args, $instance)

        /**
         * HTML des Widgets
         *
         * @param array $args
         */

        private function my_widget_html_output($args = array()) {
            /**
             * Widgetausgabe
             * Hier wird nun das HTML für das Widget erstellt
             */

            $var_sWidetHTML = wpautop($args['my-widget-text'], true);

            return $var_sWidetHTML;
        } // private function my_widget_html_output($args = array())
    } // END class My_Sidebar_Widget extends WP_Widget

    /**
     * Widget initialisieren.
     */

    add_action('widgets_init', create_function('', 'return register_widget("My_Sidebar_Widget");'));
} // END if(!class_exists('My_Sidebar_Widget'))

Das Widget darf gerne hergenommen werden, um eigene Ideen umzusetzen. Ich würde mich freuen, wenn ihr mich wissen lasst, was ihr denn so daraus gemacht habt.

Ich habe das Ganze auch hier mal als Plugin zum Download zusammengeschnürt.

Artikel / Seite weiterempfehlen

5 Meinungen zu “WordPress: Grundstruktur eines Sidebarwidgets

  1. Sehr schön erklärt. Wollte eh mal ein eigenes Widget programmieren. Vielleicht klappt es ja damit. Auf jeden Fall habe ich jetzt gerade Lust darauf bekommen, es mal auszuprobieren.

  2. Danke für den deutliche und klar geschriebene Beitrag. Obwohl ich erst seit etwa einer Woche meine Webseite neu gestaltet habe, muss ich demnächst unbedingt probieren, selbst einen Widget zu erstellen. Im Moment nämlich habe ich die Inhalte, die (fast) auf jeder Seite im Sidebar sichtbar sein solle, immer als HTML-Code in das bestehende Text/HTML-Widget hineingeschrieben – was natürlich nicht so elegant ist.

  3. Sehr schön geschrieben, muss man neidlos anerkennen und auch mal danke für die Arbeit sagen. Ich freue mich immer, für meine Blogs noch Tipps zu kriegen. Die Widgets waren, ausser den Standards natürlich, bisher noch Neuland für mich, aber bei dem nächsten neuen Projekt, werde ich mal etwas experimentieren.

  4. Wow, super informativer und guter Artikel von dir. Hut ab. Auch wenn ich noch relativ neu mit dem Thema WordPress bin. Wird bestimmt später auch mal ein Thema bei mir sein, dann werde ich sicher auf deinen Artikel zurückgreifen, danke.

  5. Hallo,

    danke für die klasse Anleitung. Ich habe noch ein Problem, dass ich html-Code im Textfeld bräuchte. Was muss ich ändern/anpassen?
    Danke Michael

Hinterlasse eine Antwort

Ihre Email-Adresse wird nicht veröffentlicht. Pflichtfelder sind durch * markiert.

Sie können folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>