Für Menschen · Seien Sie begeistert und Sie werden begeistern !
Sobald innerhalb einer Funktion HTML für die Ausgabe definiert wird, muss das HTML von der Logik getrennt werden! In diesem Fall wird die Funktion doppelt definiert. Eine Funktion enthält ausschließlich Logiken und gibt Werten nur als return zurück. Die zweite Funktion enthält dann HTML, Prüflogik, Schleifen oder Hooks und gibt Werte als echo aus. Ok die Schlaueren werden jetzt sagen ey MVC, ich sage völlig richtig, aber WordPress verfolgt kein Konsequentes MVC-Pattern!
Betrachteten wir WordPress auf eine beschränkte Sichtweise, kann man ein MVC-Pattern erkennen. Durch die Trennung der Themes (view) vom Core (Model) wird der Eindruck erweckt WordPress verfolgt ein MVC-Pattern. Aber dieses Muster ist nur im Fontend zu finden. Schauen wir allerdings etwas genauer hin sehen wir das es keine solche Logik für den Adminbereich gibt. Also muss die View für den Adminbereich irgendwo im Core verankert sein. Wir können auch feststellen das im Core selbst lose SQL-Query innerhalb von PHP zu finden ist. Gut, eine allgemeine Trennung von Ansicht und Logik ist nicht gleich MVC. Ein MVC-Pattern geht prinzipiell von einer Art objektorientierten Programmier-Paradigma aus, in WordPress sind diese auch vereinzelt zu finden, aber wir finden viel mehr prozedurale Programmier-Paradigmen als objektorientierte. Fazit WordPress selbst verfolgt kein MVC-Pattern, aber es ist durchaus möglich MVC-Prinziepien, wie im folgernden an zuwenden.
function get_some_foo() {
$my_foo = 'This is Foo!';
return $my_foo;
}
function some_foo() {
$foo = get_some_foo();
echo $foo;
}
Warum ist das Sinnvoll? Wir wollen das die Funktion some_foo() eine vordefinierte Ausgaben zurückliefert. In einem anderen Template wollen wir aber das vordefinierte Verhalten der Funktion some_foo() verändern. Um nun beiden Anforderungen effektiv abzubilden, werden zwei Funktionen definiert. Die erste Funktion besteht einzig aus der elementaren Logik und gibt nur Werte als return zurück, ihr wird immer ein get_… vorangestellt. Die zweite Funktion enthält vordefinierte Darstellungsinformationen, das wiederum können HTML, Prüflogik, Schleifen oder ein Hook sein.
function get_some_foo() {
$foo_bar_array = array( 'Foo', 'Bar', 'FooBar', 'BarFoo' );
$foo_bar_array = apply_filters( 'some_foo_array', $foo_bar_array );
return $foo_bar_array ;
}
function some_foo() {
$foo_list = '<ul>';
foreach( get_some_foo() as $foo_key => $foo_value ){
$foo_list .= '<li>' . $foo_value . '</li>';
}
$foo_list .= '</ul>';
echo apply_filters( 'some_foo', $foo_list );
}
Im vorherigen Beispiel wird in jeder der beiden Funktionen mit der Funktion apply_filters() die möglichkeiten geschaffen, zurückgeliferte Werte später beliebig zu verändern. Eine Manipulation kann dann über die so definierten Hooks some_foo_arra oder some_foo erfolgen. Hier noch ein Beispiel, wie eine möglich Manipulation mit den beiden defineirten Hooks aussehen kann.
Im nächsten Code-Beispiel werden wir ein Array $foo_bar_array und das HTML von der Ausgbe Verändern. Dazu werden die beiden Hooks some_foo_array und some_foo, die mit apply_filters( 'some_foo' ... festgelegt wurden genutzt. Mit der Funktion add_filter() werden Filterfunktionen zur Weiterverarbeitung in der globalen Variable $wp_filter registriert.
function get_my_some_foo( $foo_bar_array ) {
$foo_bar_array[ count( $foo_bar_array ) + 1 ] = 'FuuBoo';
return $foo_bar_array ;
}
function my_some_foo( $foo_list ) {
$foo_list = str_replace( 'ul', 'ol', $foo_list );
return $foo_list;
}
add_filter( 'some_foo_array', 'get_my_some_foo');
add_filter( 'some_foo', 'my_some_foo');
// do not forget, call some_foo()
some_foo();
Schauen wir uns noch kurz an was das ganze nun bewirkt. Was some_foo() ohne Manipulieren ausgibt sehen wir im folgenden Beispiel.
function get_some_foo() {
$foo_bar_array = array( 'Foo', 'Bar', 'FooBar', 'BarFoo' );
$foo_bar_array = apply_filters( 'some_foo_array', $foo_bar_array );
return $foo_bar_array ;
}
function some_foo() {
$foo_list = '<ul>';
foreach(get_some_foo() as $foo_key => $foo_value){
$foo_list .= '<li>' . $foo_value . '</li>';
}
$foo_list .= '</ul>';
echo apply_filters( 'some_foo', $foo_list );
}
?>
//Ausgabe
<ul>
<li>Foo</li>
<li>Bar</li>
<li>FooBar</li>
<li>BarFoo</li>
</ul>
Im nächsten Beispiel nutzen wir die in den Funktionen definierten Hooks some_foo_array und some_foo um dem Array ein weiteres Element hinzuzufügen und aus der ungeordneten Liste eine geordnete Liste zu machen.
function get_my_some_foo( $foo_bar_array ) {
$foo_bar_array[ count( $foo_bar_array ) + 1 ] = 'FuuBoo';
return $foo_bar_array ;
}
function my_some_foo( $foo_list ) {
$foo_list = str_replace( 'ul', 'ol', $foo_list );
return $foo_list;
}
// register Hooks in the stack ($wp_filter)
add_filter( 'some_foo_array', 'get_my_some_foo');
add_filter( 'some_foo', 'my_some_foo');
?>
//output
<ol>
<li>Foo</li>
<li>Bar</li>
<li>FooBar</li>
<li>BarFoo</li>
<li>FuuBoo</li>
</ol>
Wie Läuft das jetzt mit dem add_filter und apply_filters im Programmfluss ab?
Jeder Hook der ausgeführt werden soll wird mit add_filter oder add_action in der globalen Variable $wp_filter registriert. Wird nun im Programmablauf die Funktion apply_filters() aufgerufen wird anhand der übergeben Parameter die passende Filter-Funktion in der $wp_filter gesucht, wenn dieser mit add_filter dort registiert ist, wird die passende Funktion ausgeführt. Jetzt werden Werte Manipuliert und dann zurück an apply_filters übergeben.
Nehmen wir unser Beispiel von oben, dann sieht das wie folgt aus.
<?php
// the default function
function get_some_foo() {
$foo_bar_array = array( 'Foo', 'Bar', 'FooBar', 'BarFoo' );
$foo_bar_array = apply_filters( 'some_foo_array', $foo_bar_array );
return $foo_bar_array ;
}
// the filter function
function get_my_some_foo( $foo_bar_array ) {
$foo_bar_array[ count( $foo_bar_array ) + 1 ] = 'FuuBoo';
return $foo_bar_array ;
}
// register function in $wp_filter
add_filter( 'some_foo_array', 'get_my_some_foo' );
?>
Ohne Hook-Funktionalität würde das Ganze wie folgt aussehen. Wir haben hier zwar wesentlich weniger Code aber dieser ist dafür nicht flexibel oder wiederverwendbar.
<?php
//Das ist unsere default Funktion
function get_some_foo() {
$foo_bar_array = array( 'Foo', 'Bar', 'FooBar', 'BarFoo' );
$foo_bar_array[ count( $foo_bar_array ) + 1 ] = 'FuuBoo';
return $foo_bar_array ;
}
?>

Dieser Beitrag ist aus der Feder von Renè Reimann - die-pixler.de und ist ein Beitrag zum Adventskalender auf wpengineer.com zum Thema WordPress.
Vielen Dank auch hier nochmal von meiner Seite an Renè.
bueltge.de [by:ltge.de] wird von Frank Bültge geführt, administriert und gestaltet. Alle Inhalte sind persönlich von mir ausgewählt und erstellt, nach bestem Gewissen und Können, was die Möglichkeit von Fehlern nicht ausschließt.
Das Weblog wird angetrieben von WordPress und aktuell gibt es 980 Beiträge, 18722 Kommentare in 14 Kategorien und 464 Tags.
Das Blog wird liebevoll mit xHTML & CSS in Handarbeit gestaltet. Erstellt mit ♥ zum Befüllen und Erhalten.
Design und Code ist unter Copyright
© 2001 - 2012 bueltge.de [by:ltge.de]
12. Dezember 2011 um 21:29
Argh. Ich sitze hier gerade zähneknirschend und mit den Füßen scharrend. Leider habe ich auch nicht so viel Zeit, werde bei Gelegenheit noch mal was dazu schreiben.
Kurz:
add_action() und add_filter() haben nur wenig mit MVC zu tun. Es sind Event-Listener.
add_action( 'if_happened_this', 'do_this' );und
add_filter( 'if_this_is_set', 'change_it_to_this' );Also wenn eine Funktion ausgeführt wird oder eine Variable gesetzt wird (Ereignis), dann kann man mit den Listenern darauf reagieren.
MVC setzt man eher mit
call_user_func()um. Im Model werden die Daten festgelegt/geholt/berechnet (modelliert), im View werden sie ausgegeben und der Controller entscheidet welche Funktion zur Modellierung bzw. Ausgabe der Daten verwendet wird. Ich habe das mal hier in einem kleinen Code zusammengefasst.Jetzt kommen die Event-Listener do_action() und apply_filters() ins Spiel. Den Models (get_some_foo() und get_some_bar() ) könnte man Filter verpassen, den Views (some_view() und some_storage() ) einen do_action.
Viel wichtiger ist aber der Controller. Denn er ist ja quasi Herrscher und entscheidet alles. Er bestimmt wo die Daten her kommen (welches Modell verwendet wird) und wie sie ausgegeben werden (welcher View). Den Arrays für get_what und do_what verpasst man also einen apply_filters. Möchte ich nun die Daten nicht als ungeordnete Liste sondern als z.B. Definitions-Liste ausgeben, schreibe ich einen neuen View und übergebe dem Controller meinen neuen View. Gleiches gilt für die Models. Anstatt fest einprogrammierte Daten zu verwenden, könnte ich sie auch aus einer Datei oder Datenbank lesen. Ich müsste dazu nur ein neues Modell schreiben und dem Controller dieses bekannt geben.
Wie effektiv MVC sein kann, zeigt sich am Nav-Menu von WordPress. Es gibt zahlreiche Tutorials und Code-Snippets wie man das HTML des Nav-Menus von WP beeinflussen kann. Würde WP einem MVC-Pattern folgen, wäre es eine ganz einfache Sache. Man würde für das Nav-Menu einen neuen View schreiben und dem WP-Controller (den es leider nicht gibt) bescheid geben das man einen neuen View hat und das dieser bitte schön zu verwenden ist.
(Dieser Kommentar wurde unter Zeitdruck geschrieben und ist auch mit Rechtschreib- und Grammatikfehler gültig)
17. Dezember 2011 um 00:53
@Renè und Ralf: Danke für den hilfreichen Artikel bzw. Kommentar. Habe gerade erst begonenn mich in die MVC-Thematik und die entsprechende (sinnvolle) Umsetzung in php einzulesen und da kommen eure Beiträge wie gerufen
22. Dezember 2011 um 11:20
Ohje.
Mal ganz ehrlich, liest sowas heute niemand mehr Korrektur?
Nach den ersten beiden Absätzen ist mir die Lust gründlich vergangen. Thematisch ein rel. interessantes Thema. Aber in der hier präsentierten Form leider nicht zu gebrauchen. Das macht einfach keinen Spaß weiter zu lesen.
Von grammatikalischen Grundregeln mal abgesehen (die kann man nicht alle aufzählen), aber es heißt "Pattern" oder "pattern", nicht jedoch "Patter". Die Funktion heißt apply_filters() und nicht applay_filters(), usw.
22. Dezember 2011 um 21:19
@christoph: du hast recht, schnell die Kleinigkeiten gefixt; die Zeit reicht aktuell kaum, so dass ich nur diagonal lese.
11. Januar 2012 um 20:52
WordPress hat von Haus aus so viele praktische Hooks, in die man sich hineinhaken könnte. Das Probem ist nur, dass ich die als mittelguter WordPress-Programmierer nicht alle kenne. Wie findet ihr die denn, außer per Zufall durch ein Tutorial? Der Codex gibt bei vielen Hooks gar nichts her.
12. Januar 2012 um 16:46
@Daniel: ich finde die Hooks mittels Plugin Debug Objects oder durch lesen im Code des Core.
2. März 2012 um 14:18
... vor 5 Jahren konnte ich noch selber an WordPress rumschrauben und genau das erreichen, was ich erreichen wollte. Heute bin ich überfordert. Das ist ein wenig schade, aber wohl nicht zu ändern.
7. März 2012 um 11:07
@ Georg
Das kann ich gut verstehen, denn mir geht es leider genauso. Mir fehlt bedauerlicherweise auch die Zeit, mich noch mal komplett einzufinden. Doch dafür gibt es ja diesen Blog, der uns auf dem neusten Stand hält.
13. März 2012 um 22:12
@Daniel
Ich schließ mich Frank an, Hooks lassen sich allein durch Core lesen finden.
In der Regel reicht die Vermutung das ein Hook in einer bestimmten Datei sein könnte, dann muss nur noch nach apply_filters oder do_action gesucht werden und rückwärts lesen. Klingt kompliziert ist aber ganz einfach.