Trenne Logik von der Ausgabe, mittels Hooks in WordPress

Die Zeiten ändern sich.

Dieser Beitrag scheint älter als 12 Jahre zu sein – eine lange Zeit im Internet. Der Inhalt ist vielleicht veraltet.

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!

Warum WordPress kein MVC-Pattern konsequent verfolgt?

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 ;
}
?>

Gastbeitrag

Rene Reimann Avatar
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è.

Von Frank Bültge

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.