WordPress: Klassenbasiertes Funktions-Plugin

Im Web findet man an vielen Stellen Code-Schnipsel für WordPress, so ja auch in diesem Blog. Der Rat lautet dann allgemein, diese in die functions.php des Themes zu packen. Das macht allerdings gar nicht immer Sinn, es ist nur oft das einfachste, was auch unerfahrene User verstehen. Da aber auch der Umgang mit einem eigenen Plugin nicht wirklich schwierig ist, möchte ich das in Zukunft als bevorzugte Variante empfehlen und dazu hier ein Beispiel posten, das jeder als Grundlage für ein eigenes Plugin nehmen kann.

Kurz zu den Hintergründen: Man sollte generell bei jedem Code-Schnipsel kurz überlegen, was er tut. Ändert er konkret einen Aspekt des Themes, dann ist er in der functions.php richtig aufgehoben, schließlich ist diese ja Teil des Themes. Oft will man aber auch generell etwas am Verhalten von WordPress ändern, was völlig unabhängig vom Theme ist. Dann gehört der Code eher in ein Plugin. Fragen sollte man sich bei der Entscheidung immer, ob man die Änderung so auch noch verwenden wollen würde, wenn man das Theme wechselt.

Ein eigenes Plugin hat zudem den Vorteil, das es bei Updates des Themes nicht überschrieben wird. Wenn man sich selber ein Custom Theme bastelt oder ein Child-Theme nutzt, ist das natürlich kein Problem. Aber wer etwa das Standard-Theme Twenty Eleven ändert und dann ein halbes Jahr später im Stress ein angezeigtes Update für Twenty Eleven automatisch installiert, der hat hoffentlich ein Backup der Theme-Dateien angelegt. 😉

Ein eigenes Plugin also. Ist das nicht total schwierig, ein Plugin zu erstellen? Nein, es sind nur wenige Zeilen PHP-Code nötig. Prinzipiell reicht es, eine PHP-Datei mit einem eindeutigen Namen im wp-content/plugins-Ordner abzulegen und sie mit einem PHP-Kommentar in einem gewissen Format beginnen zu lassen. Man muss das Plugin dann natürlich auch aktivieren, sonst tut es nichts. Bei Multisite-Installationen sollte man sich überlegen, ob man das Plugin für alle Blogs aktiviert, nur auf einzelnen Blogs oder pro Blog ein eigenes Funktions-Plugin anlegt.

So, und damit ohne weitere Vorrede zum Plugin:

<?php
/*
Plugin Name: My Functions
Description: Adds functionality that doesn't belong into a theme's function.php.
Version: 0.1
Author: You
License: GPL2 (or later)
*/

/*  
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/**
 * Define a class to encapsulate the functions.
 */
class MyFunctions {
  
  //--------------------------------------------------------------------------
  // constructor
  //--------------------------------------------------------------------------
  
  /**
   * Creates a MyFunctions instance and registers all necessary hooks and
   * filters.
   */
  public function __construct() {
    // example: write a comment what the hook is for
    //add_filter('filter_name', array(&$this, 'function_name'));
  }
  
  
  //--------------------------------------------------------------------------
  // functions
  //--------------------------------------------------------------------------
  
  //public function function_name() {
  //  
  //}

}

// instantiate the class to actually do something
new MyFunctions();

Hinweis: Das Plugin nutzt eine Klasse zur Kapselung der Funktionalität. Ihr braucht also PHP 5 dazu, aber es arbeitet sowieso niemand mehr ernsthaft mit PHP 4, richtig? 🙂

Wie funktioniert das nun? Das Plugin definiert eine Klasse MyFunctions und legt darunter eine Instanz dieser Klasse an, damit der Code in der Klasse auch ausgeführt wird. Auf der Instanz werden keine Funktionen aufgerufen, aber der Konstruktor sorgt dafür, dass alle Funktionen an den richtigen Filter- oder Action-Hook gehängt werden. Der obige Code enthält ein auskommentiertes Beispiel für einen Filter und darunter die Methode, die bei diesem Filter aufgerufen wird.

Das Schöne an der Klasse: Man muss sich um Namenskollisionen keine Sorgen machen (außer bei der Klasse selber, ändert den Namen ruhig zu etwas individuellerem, dann aber auch bei der Instantiierung ganz unten). In der functions.php kann man z.B. nicht einfach eine Funktion namens wp_trim_excerpt anlegen, weil es diese Funktion in WordPress schon gibt. Das gibt gleich einen Fehler und ggf. eine weiße Seite statt der Website. Innerhalb der Klasse kann man sich namenstechnisch dagegen austoben, und ich würde sogar dazu raten, die Methoden einfach gleich so zu nennen wie die Filter/Actions, für die sie gedacht sind. Das macht das ganze etwas übersichtlicher.

Noch ein Hinweis: Die Filter/Action-Aufrufe im Konstruktor der Klasse müsst ihr in einem Punkt anpassen verglichen mit den allermeisten Code-Schnipseln, die man im Web findet. Da ihr eine Klasse nutzt, müsst ihr die Instanz mitgeben. Wenn ihr also irgendwo den Hinweis findet, eine Funktion so hier aufzurufen:

add_filter('wp_trim_excerpt', 'mein_prefix_wp_trim_excerpt');

Dann müsste das für dieses Plugin so aussehen:

add_filter('wp_trim_excerpt', array(&$this, 'wp_trim_excerpt'));

Hier wird einfach mit &$this die Instanz mitgegeben, und um das machen zu können muss beides noch in ein Array. Alles in allem machbar. Im Sinne robusterer WordPress-Seiten wäre es also schön, wenn in Zukunft mehr Code-Schnipsel in einem solchen Plugin landen würden – aber eben auch nur diejenigen, die dort reingehören.

P.S.: Die Idee zu diesem Beitrag kam natürlich nicht einfach von irgendwo, über Plugins statt der functions.php wird in der Community schon länger geredet. Stellvertretend hier ein Link zu einem Beitrag von Justin Tadlock, der alle Argumente sehr schön zusammenfasst. Sein Beispiel-Plugin ist allerdings nicht klassenbasiert, und wenn dann wollte ich es schon richtig machen. WordPress enthält wirklich schon genug Funktionssuppe. 😉

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Bitte beachte die Kommentarregeln: 1) Kein Spam, und bitte höflich bleiben. 2) Ins Namensfeld gehört ein Name. Gerne ein Pseudonym, aber bitte keine Keywords. 3) Keine kommerziellen Links, außer es hat Bezug zum Beitrag. mehr Details...

So, noch mal kurz drüber schauen und dann nichts wie ab damit. Vielen Dank fürs Kommentieren! :-)