Einfacher PHP Objekt Cache – APCu einrichtung

Viele kennen vielleicht den APC Cache von PHP noch. Dieser wurde zum Cachen von PHP Skripten und als Objekt Cache genutzt. Heute übernimmt allerdings der Opcode Cache die Aufgabe des Cachens von PHP Skripten und würde sich daher mit APC in Gehege kommen. Daher wurde der Objekt Cache (Userland Cache) aus APC herausgelöst und als APCu herausgebracht.

Ich verwende APCu gerne als Objekt Cache da es sich so leicht einrichten lässt und kein extra Dienst notwendig ist.

Für die Einrichtung benötigt man die zu seiner PHP Version passende dll. Diese findet man hier. Aus dem ZIP Archiv benötigen wir nur die php_apcu.dll, diese Kopiere ich mir in dem „extras“ Ordner der sich im PHP Verzeichnis befindet.

Dan müssen wir die php.ini bearbeiten und die dll als Extension in der [PHP] Section hinzufügen:

extension=C:/php/extras/php_apcu.dll

Dann müssen wir noch eine Section wie folgt erstellen:

[apcu]
apc.enable_cli = on
apc.enabled = on
apc.writable = "C:/Temp/"

Dies reicht um APCu zu aktivieren. Der Webserver sollte einmal neu gestartet werden.

Damit man den Cache überhaut nutzen kann muss man ihn im CMS aktivieren. Das geht in WordPress indem man eine object-cache.php Datei im wp-content ablegt. In WordPress kann man direkt einen Geschwindigkeitsunterschied merken auch wenn noch nicht viel im Blog ist.

Um zu sehen was im Cache ist kann man sich die Datei auf dem Webserver ablegen und Aufrufen.

Den APCu Cache wird man bei Standard Shard Hosting nicht finden da der Cache immer für alle auf dem Server gilt und es somit ein Sicherheitsrisiko darstellt. Bei Mittwald kann man allerdings APCu in den Managet Server Paketen bekommen.

Xdebug unter Windows einrichten

Xdebug verwende ich jetzt schon seit einiger Zeit, um PHP unter Windows zu Debuggen mit PHPStorm. Da ich schon einigen Leuten geholfen haben Xdebug einzurichten und zur Dokumentation meiner Einstellungen, schreibe ich dieses kleine Tutorial.

Voraussetzung ist hierfür ein lokal installierter Webserver mit PHP. Die Xdebug Konfiguration sollte nicht nur mit PHPStorm funktionieren (Dafür muss der „idekey“ entsprechend angepasst werden).

Für die Einrichtung benötigen wir die php_xdebug.dll die man hier passend zu seiner PHP Version herunterladen kann. Meistens wird dies die TS (ThradSafe) Version sein (Kann man auch daran erkennen wenn man PHP als Apache Module läuft). Die dll habe ich bei mir in das PHP Unterverzeichnis „extras“ entpackt.

Jetzt muss noch die „php.ini“ bearbeitet werden und um folgenden block ergänzt werden:

[XDebug]
zend_extension = "C:/php/extras/php_xdebug.dll"
xdebug.remote_enable = 1
xdebug.remote_port = 9000
xdebug.remote_connect_back = 0
xdebug.profiler_enable_trigger = 1
xdebug.profiler_enable = 0
xdebug.profiler_output_dir = "C:/Temp/profiler"
xdebug.idekey = PHPSTORM
xdebug.default_enable = 0
xdebug.scream = 1

Die Beschreibungen zu den Einstellungen findet man hier im Prinzip ist aber alles so eingestellt das Xdebug nur ausgeführt wird wenn es durch einen Cookie oder URL Parameter aktiviert wird. Ich benutze dazu in Chrome den Xdebug Helper. Dort wählt man in den Optionen auch nur Die IDEKey aus und kann dann noch einstellen bei welchen Domains das Tool in der Adressliste des Browsers angezeigt werden soll.

Wenn man PHP Scripte auf Kommandozeile Debuggen will muss man einen Eintrag in den Umgebungsvariablen von Windows hinzufügen. Dieser lautet:

Name: XDEBUG_CONFIG
Wert: remote_enable=1 remote_mode=req idekey=PHPSTORM

In PHPStorm muss man bevor man mit dem Debuggen beginnt nur noch den Knopf für „Start Listening for PHP Debug Connections“ drücken und seine Breakpoints setzen.

Happy Debugging

Standard WordPress Plugin Funktionen

Zwei der Funktionen/Methoden, die man in Zukunft wohl in allen meinen Plugins finden wird, sind:
Voraussetzung ist PHP 5.1.2 für die Autoload Funktion.

1. Zum Ermitteln von Plugin Daten, damit nicht immer alles per Constante definiert wird, um Namensraum freizuhalten:

<?php
public static function get_plugin_data( $get_data = FALSE ) {

	$plugin_data = wp_cache_get( 'plugin_data', 'pluginname' );
	if ( $plugin_data === FALSE || empty( $plugin_data[ 'Version' ] ) ) {
		$plugin_data               = get_file_data(
			__FILE__, array(
				'Name'        => 'Plugin Name',
				'PluginURI'   => 'Plugin URI',
				'Version'     => 'Version',
				'Description' => 'Description',
				'Author'      => 'Author',
				'AuthorURI'   => 'Author URI',
				'TextDomain'  => 'Text Domain',
				'DomainPath'  => 'Domain Path'
			), 'plugin'
		);
		$plugin_data[ 'BaseName' ] = plugin_basename( __FILE__ );
		$plugin_data[ 'Folder' ]   = dirname( plugin_basename( __FILE__ ) );
		$plugin_data[ 'URL' ]      = plugins_url( '', __FILE__ );
		if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
			$plugin_data[ 'JSVersion' ] = time();
		} else {
			$plugin_data[ 'JSVersion' ] = $plugin_data[ 'Version' ];
		}
		wp_cache_add( 'plugin_data', $plugin_data, 'pluginname' );
	}

	if ( ! $get_data ) {
		return $plugin_data;
	}

	return $plugin_data[ $get_data ];
}

2. Die Autoload Funktion von PHP zum automatischen Laden von Klassen, damit sie nur dann geladen werden, wenn sie auch benötigt werden. Das heißt, verwendet man ein „add_action“ wird die Klasse erst geladen, wenn wirklich ein „do_action“ erfolgt oder die Seitenklasse für einen Menüeintrag erst geladen wird, wenn der Menüpunkt tatsächlich aufgerufen wird. Voraussetzung ist, dass man das ganze Plugin klassenbasierend aufbaut. Das kann dann nicht nur Ressourcen sparen.

<?php
public function __construct() {
	//register autoloader
	spl_autoload_register( array( $this, 'autoloader' ) );
}

public static function autoloader( $class_name ) {
	//WordPress classes loader
	$wpclass='/class-'.strtolower(str_replace('_','-',$class_name)).'.php';
	if ( is_file(ABSPATH .'wp-admin'.DIRECTORY_SEPARATOR.'includes'.$wpclass) ) {
		require(ABSPATH .'wp-admin'.DIRECTORY_SEPARATOR.'includes'.$wpclass);
		return true;
	}
	if ( is_file(ABSPATH . WPINC . $wpclass) ) {
		require(ABSPATH . WPINC . $wpclass);
		return true;
	}

	//Plugin classes to load
	if ( strpos( $class_name,'PluginClass_') !== false ) {
		$class_load = dirname( __FILE__ ) . DIRECTORY_SEPARATOR.'inc'.DIRECTORY_SEPARATOR.'class-' . strtolower( str_replace( array( 'PluginClass_', '_' ), array( '', '-' ), $class_name ) ) . '.php';
		if ( is_file( $class_load ) ) {
			require($class_load);
			return true;
		}

	}
	return false;
}

Diese sollten sich innerhalb der Haupt Plugin Datei in einer Klasse befinden.

PHP Verzeichnis Übergabe prüfen

Ich muss in meinem Plugin für WordPress den ABSPATH übergeben, um eine eigene Ajax Behandlung zu haben.
Was meint ihr ist der Codeschnipsel dafür geeignet, um es möglicht sicher gegen Angriffe zu machen?

<?php
if ( is_file( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) . '/wp-load.php' ) ) {
	require_once( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) . '/wp-load.php' );
} else {
	$abspath = filter_input( INPUT_POST, 'ABSPATH', FILTER_SANITIZE_URL );
	$abspath = rtrim( realpath( $abspath ), '/' );
	if ( ! empty( $abspath ) && is_dir( $abspath . '/' ) && is_file( realpath( $abspath . '/wp-load.php' ) ) ) {
		require_once( $abspath . '/wp-load.php' );
	} else {
		die();
	}
}

Erläuterung:
Wenn der Plugins Ordner im Standard Verzeichnis ist oder zumindest in der selben Verzeichnis Tiefe muss die Übergabe nicht genutzt werden.
Sonst.
Das übergebene Verzeichnis vorfiltern (nur in URLs erlaubte Zeichen werden zugelassen)
mit ‚realpath()‘ alle ‚../‘,‘./‘ entfernen und prüfen, ob das Verzeichnis existiert.
Da ‚realpath()‘ auch das aktuelle Verzeichnis ausgibt nochmal Verzeichnis und Datei auf Existenz prüfen.
WP-load.php laden.