Wie verwende ich WordPress Metaboxen in eigenen Plugins
codestyling | 22. Februar 2009 | 00:19
Mit dem Erscheinen der WordPress Version 2.7 wurden im Backend die Metaboxen geändert und können nun beliebig angeordnet oder auch ausgeblendet werden. Dies macht das Arbeiten mit dem Backend deutlich einfacher.
Jedoch wurde die nötigen Funktionen bisher nicht ausreichend dokumentiert, damit man das in eigenen Plugins verwenden kann. Ich versuche hiermit ein wenig Licht ins Dunkel zu bekommen, beschreibe die Funktionen ein wenig und stelle ein Beispiel-Plugin als Demonstration zum Download bereit.
Voraussetzungen
In meinen Ausführungen befasse ich mich nur mit WordPress ab Version 2.7, für ältere Versionen ist diese Beschreibung ungeeignet, denn die alten Versionen kennen diese Funktionen nicht in dieser Art.
Man könnte das zwar halbwegs kompatibel programmieren, das habe ich mir wegen der Übersichlichkeit aber gespart. Auch die gettext Fähigkeit des Demo-Plugins habe ich weggelassen, da dieses zum Artikel gehörende Plugin nur ein How To darstellt.
Funktionsbeschreibungen
Betrachten wir mal als Einstieg nötigen Funktionen, die WordPress bereitstellt. Hier die Definitionen:
| PHP | |
1 2 3 4 5 | function add_meta_box($id, $title, $callback, $page, $context = 'advanced', $priority = 'default') function do_meta_boxes($page, $context, $object) |
| timing: 0.080s | |
Funktion: add_meta_box
Die Funktion add_meta_box(…) wird dazu verwendet, WordPress mitzuteilen, das man eine eigene Metabox bereitstellen möchte.
Der Parameter $id ist eine eindeutige Kennung der jeweiligen Metabox.
Mit $title gibt man an, was man als Titel in der Kopfzeile der Box haben möchte, es empfiehlt sich hier gettext basierten Text zu verwenden, damit sich die besser in anderen Sprachen übersetzen lässt.
Der Wert $callback erwartet eine Funktion, die von WordPress aufgerufen werden soll, wenn der Inhalt der Box ausgegeben werden soll.
Der Parameter $page beschreibt die Seite, in der die neue Box erscheinen soll. Somit kann man auch in fremden Plugin-Seiten Boxen einblenden lassen, wenn man deren verwendeten Parameter kennt.
Der Parameter $context wird verwendet, um Boxen nur in einem bestimmen Context ausgeben zu lassen. Meist wird diese zu Unterscheidung zwischen Content-Boxen und Sidebar-Boxen verwendet.
Mit Hilfe von $priority hat man die Möglichkeit, in begrenztem Maße auf die Reihenfolge der Boxen im entsprechenden Container zu reagieren. Zur Verfügung stehen: ‘high’, ‘core’, ‘default’, ‘low’.
Funktion: do_meta_boxes
Wenn man die Funktion do_meta_boxes(…) aufruft, führt das zur Ausgabe aller Metaboxen, die auf die angebenen Parameter passen und bisher registriert wurden. Der Parameter $object steht frei zur Verfügung, wenn man eigene Metabox-Seiten programmiert und ermöglicht die Weitergabe von Daten an die Callback Funktion, die den Inhalt der Box erstellen und ausgeben soll.
Callback Funktionen für Boxen-Inhalte
| PHP | |
1 2 3 4 5 6 7 8 9 10 11 | <?php function on_contentbox_1_content($data) { sort($data); ?> <p> The given parameter at <b>sorted</b> order are: <em><?php echo implode(' | ', $data); ?></em> </p> <?php } ?> |
| timing: 0.064s | |
Im Beispiel wird als $object ein Array ($data Parameter) mit Strings übergeben, die dann in der Box ausgewertet werden können. Es steht jedem Programmierer frei, was er an die Callback für die Box-Inhalte weitergibt.
In der Seite “Artikel schreiben” zum Beispiel ist diese Objekt der Artikel als PHP Objekt selbst ($post).
Metabox Registrierung - der Zeitpunkt spielt eine Rolle
Man kann die Metaboxen zu 2 verschiedenen Zeitpunkten registrieren:
- wenn WordPress bekannt gibt, die Plugin-Seite laden zu wollen
- während der Ausgabe des Plugin Seiteninhalts
Der Unterschied des Zeitpunktes bestimmt, ob man die entsprechende Metabox über das Screen Options Menü ausblenden kann oder nicht. Boxen, die registriert werden während der Lade-Anforderung kann man auch bei Bedarf ausblenden. Wenn man die Box im 2. Falle erst während der Seitenausgabe - aber vor dem Aufruf von do_meta_boxes(…) - registriert, kann man diese Box nicht mehr ausblenden, sie ist immer auf der Seite verfügbar.
Man muss sich mit diesen Mechanismus nicht befassen, WordPress selbst sorgt dafür, das Metaboxen in dem Reiter Screen Options aufgenommen werden.
Javascript wird für Drag/Drop und Ausblenden benötigt
Wenn man bis hierher alles implementiert hat, wundert man sich, warum die Boxen nicht verschoben werden können, warum sich WordPress nicht merkt, welche davon ausgeblendet wurde und welche zugeklappt wurde. Dies liegt daran, daß man dafür natürlich noch für ein wenig Javascript Magic braucht und dafür sorgen muß.
| PHP | |
1 2 3 4 | wp_enqueue_script('common'); wp_enqueue_script('wp-lists'); wp_enqueue_script('postbox'); |
| timing: 0.049s | |
Die o.g. Scripts müssen aufgenommen werden, damit das prinzipiell funktionieren kann. Allerdings muß man auch eine Initialisierung vornehmen, die meist in der Seite per inline Javascript geschieht:
| Javascript | |
1 2 3 4 5 6 7 8 9 10 11 | <script type="text/javascript"> //<![CDATA[ jQuery(document).ready( function($) { // close postboxes that should be closed $('.if-js-closed').removeClass('if-js-closed').addClass('closed'); // postboxes setup postboxes.add_postbox_toggles('<?php echo $this->pagehook; ?>'); }); //]]> </script> |
| timing: 0.007s | |
Screenshots des Beispiel-Plugins
Damit man sich das besser vorstellen und nachvollziehen kann, habe ich mal 2 Screenshots gemacht und diese hier verlinkt. Es zeigt die Demo-Plugin Seite mit und ohne eingeblendeter Screen Options Konfiguration:

Update: Anpassung an neues Box Modell in WordPress 2.8
Mit der kommenden Version 2.8 hat WordPress ein wenig die Funktionsweise der Metaboxen verändert und das System um Spaltenbezüge erweitert. Zur Verdeutlichung folgt nun ein Screenshot, der die neuen Möglichkeiten in der Einstellung demonstriert:

Dies macht es notwendig, darauf auch einzugehen, denn ohne diese zusätzliche Behandlung zeigt WordPress 2.8 keine rechte Sidebar für die Boxen an. Man benötigt als erstes einen neuen Filter:
| PHP | |
1 2 3 4 5 6 7 8 9 | add_filter('screen_layout_columns', array(&$this, 'on_screen_layout_columns'), 10, 2); ... //for WordPress 2.8 we have to tell, that we support 2 columns ! function on_screen_layout_columns($columns, $screen) { if ($screen == $this->pagehook) { $columns[$this->pagehook] = 2; } return $columns; } |
| timing: 0.050s | |
Innerhalb der Filteraufrufes muß man in das Array die Anzahl der unterstützten Spalten (in dem Falle 2 - Inhalt und rechte Sidebar) übergeben. Damit ist es aber noch nicht getan. Bei der Ausgabe der Metaboxen muß nun auf den aktuell eingestellten Wert Rücksicht genommen werden und eine zusätzliche HTML class Angabe in Abhängigkeit der aktuellen Spaltenanzahl geschrieben werden:
| PHP | |
1 2 3 | global $screen_layout_columns; ... <div id="poststuff" class="metabox-holder<?php echo 2 == $screen_layout_columns ? ' has-right-sidebar' : ''; ?>"> |
| timing: 0.048s | |
Nach diesen Anpassungen funktioniert das nun mit WordPress unter 2.7 und 2.8 ohne Probleme. Der unten angegebene Download ist bereits angepasst und im Quelltext dokumentiert.
Download des Beispiel-Plugins
Basierend auf den hier gemachten Beschreibungen habe ich zum besseren Verständnis das Ganze auch nochmal in ein Demo-Plugin verpackt, das einen Überblick geben soll, wie man das verwendet. Der Code ist GPL und kann benutzt werden frei nach eigenen Wünschen.
Wer diese Arbeit honorieren möchte, kann mich gern als Quelle in seinem Plugin erwähnen oder verlinken, ganz nach Belieben.
Hier das Demo-Plugin als Download: howto-metabox-plugin.zip (783 downloads)






Michael
22.02.2009 | 18:48Ich nutze 2.7.x ja schon ein paar Tage, aber das man die boxen verschieben kann, ist mir heute nur zufällig aufgefallen, also eigentlich war es eher ein Versehen.
Antworten »
Sergej Müller
22.02.2009 | 20:23Ich liebe deinen strukturierten und kommentierten Code, Heiko.
Ende 2008 hatte ich kurz überlegt, die superlange Liste mit wpSEO-Optionen in solche Boxen mithilfe dieser Technik zu verpacken. Hatte mich aber dagegen entschieden, da ich für ältere WordPress-Versionen eine Sonderbehandlung einführen müsste. Habe mich für eine statische Lösung entschieden, die vom optischen her identisch ist.
Antworten »
codestyling
22.02.2009 | 20:37Die gesonderte Behandlung für ältere Versionen mache normalerweise durch eine compatibility.php, die das Plugin nur dann lädt, wenn es feststellt, dass die Version kleiner als benötigt ist. Damit kann ich immer aktuell entwickeln und sorge dann nur per Datei Load für Kompatibilität. Das spart Nerven, erlaubt bessere Code Strukturierung und kann als 2. Schritt in der Entwicklung nachgeschoben werden. (Hab bisher die Abwärtskompatibilität immer erst im 1. Update erst nachgelegt, wenn nötig).
Antworten »
Sergej Müller
23.02.2009 | 10:23Bei auf Grund neu entwickelten Plugins macht es durchaus Sinn, nach deinem Vorschlag zu gehen. Bei bestehenden müsste man mehr umbauen. Mit der Zeit will ich mein Plugin sowieso neu aufsetzen, da werden dann solche Dinge berücksichtigt.
Danke dir für den Artikel.
Antworten »
Tom
30.06.2009 | 11:35Fuktioniert! Danke für die Erklärungen und Beispiele!
Antworten »
ocean90
11.08.2009 | 18:47Vielen Dank, sowas habe ich gesucht und nun bei dir gefunden.
Danke für das tolle Beispiel, damit versteh sogar ich es.
Gruß
Antworten »
ocean90
30.08.2009 | 17:03Hi,
auch wenn man andere Kommentar noch nicht freigeschaltet wurde, wollte ich mal fragen, wie das Gerüst aussehen muss, wenn man das Dashboard nachbauen möchte, also auch 4 Spalten nutzen möchte?
Danke im Vorraus.
Gruß
Antworten »
Jürgen Schulze
08.07.2010 | 16:56Danke für die Meta-Box-Tipss.
Ich selbst benutze Meta-Boxen nicht nur bei den Settings, sondern auch in “Post” oder “Page”.
Einfach ein $page=’post’ und fertig.
Jürgen
Antworten »