PHP Typesafe Enum & Propel

Dieser Beitrag beschreibt kurz und knapp, wie meine Typesafe Enum-Klasse zusammen mit dem ORM Propel funktioniert. Mehr über Typesafe Enum und Enumerations in PHP finden Sie hier: Typesafe Enum

Use case:

Typesafe Enum datatypes in propel objects, mapped to SQL ENUM type.

Example in Propel (schema.xml):

<column name="title_casus" sqlType="ENUM('N','M','F')"
    phpType="Casus" required="false" description="Kasus"/>

Example Enum Type:

Enum::define('CasusEnum', 'N','M','F');

Required Data Wrapper:

/**
 * Wrapper class that allows multiple instances, needed by propel
 * 
 * @author Fabian Schmengler <fschmengler@sgh-it.eu>
 * @copyright © 2010 SGH informationstechnologie UG
 */

class Casus
{
	private $casusEnum;

	public function __construct($casusString)
	{
		if (method_exists('CasusEnum', $casusString)) {
			$this->casusEnum = call_user_func(array('CasusEnum', $casusString));
		} else {
			$this->casusEnum = null;
		}
	}
	public function __tostring()
	{
		return (string)$this->casusEnum;
	}
	public static function __set_state(array $properties)
	{
		return (string)$properties['casusEnum'];
	}
}

Note to myself: diese Wrapper-Geschichte könnte noch ausgebaut werden, so etwas wie Enum::getInstance($string) wollte ich eh mal in TypesafeEnum integrieren, warum nicht auch gleich einen mit-generierten Wrapper (der natürlich auch noch eine getEnum() Methode bekommt)

Smarty Method chaining

Ich musste mich mal wieder mit Smarty herumschlagen und habe eine Weile gebraucht um folgendes zu begreifen:

Method chaining in Smarty 2.x ist NICHT MÖGLICH. Genaugenommen bleibt {$object->getFoo()->getBar()} immer leer. Der Smarty-Parser nimmt den Ausdruck komplett auseinander, verarbeitet Objekte jedoch nur eine Ebene tief. In dem Fall ist also ein hässliches {assign var=_foo value=$object->getFoo()}{$_foo->getBar()} nötig. Dies gilt überall, wo das Objekt als Template-Variable genutzt wird.

RESTful Web Applications mit PHP und HTML

Wer sich beim erstellen einer Web-Applikation am REST Prinzip orientieren will und dies nicht nur für Webservices sondern auch fürs User-Interface benutzen will, stößt ganz schnell an die Grenzen von HTML-Formularen, die in den meisten Browsern nämlich nur GET und POST als Methode erlauben – alles andere, also auch PUT und DELETE wird standardmäßig als GET aufgefasst.

Das ist aber kein Grund aufzugeben, Ruby on Rails macht es vor:
How do forms with PUT or DELETE methods work?

CakePHP benutzt den selben Hack (oh Wunder ;-)), wie man hier und hier sieht.

Konkret werden dabei abhängig von $_POST['method'] die Umgebungsvariablen $_SERVER['REQUEST_METHOD'] bzw. $_ENV['REQUEST_METHOD']überschrieben, auf die Daten wird dann mittels $_REQUEST zugegriffen, genau wie bei echten PUT oder DELETE Requests.

Somit können Web-Browser die selbe API wie andere Clients benutzen und es wird ein einheitlicher Standard für URLs unterstützt.

PEAR Installer updaten

Ich habe mir kürzlich Zend Server CE eingerichtet, die mitgelieferte go-pear.bat installierte mir darin PEAR in der Version 1.7.2 – dumm nur dass z.B. PHPUnit die Version 1.8 erfordert.

Merke: Es bringt nichts, sich go-pear.php von pear.php.net neu herunterzuladen und PEAR damit neu zu installieren, ein einfaches


pear upgrade-all

dagegen tut Wunder 🙂

PHP 5.2 Abstract Singletons: “abstract public static function” issue

Ein Problem über das ich schon häufiger gestolpert bin ist folgendes: Man will aus irgeneinem Grund eine abstrakte Singleton-Klasse definieren, sprich alle abgeleiteten Klassen sollen nur jeweils einmal instanziert werden.

In PHP 5.3 dank late static binding sehr einfach lösbar: Beispiel

In vorherigen Versionen ist es auf diese Weise nicht lösbar, die naive Herangehensweise wäre daher so etwas:

abstract class AbstractSingleton
{
	protected function __construct() { }
	private function __clone() { }
	abstract public static function getInstance();
}
class ConcreteSingleton extends AbstractSingleton
{
	private static $instance;
	public static function getInstance()
	{
		if (empty(self::$instance)) {
			self::$instance = new ConcreteSingleton();
		}
		return self::$instance;
	}
}

was jedoch seit PHP 5.2 berechtigerweise einen E_STRICT Fehler wegen “abstract static” wirft.
Continue reading “PHP 5.2 Abstract Singletons: “abstract public static function” issue”

PHP Fatal Error Handler

Codeschnipsel inspiriert von diesem Artikel:

fatalerrorhandler.php

<?php
// report all but fatal errors 
error_reporting((E_ALL | E_STRICT) ^ (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR));

// fatal error handler as shutdown function
register_shutdown_function('fatalErrorHandler'); 

function fatalErrorHandler() {
	$error = error_get_last();
	if ($error['type'] & (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
		echo '<h1>Fatal Error, shutting down...</h1>';
		echo '<pre>' . var_export($error,true) . '</pre>';
	} else {
		echo 'Regular Shutdown, no fatal errors.';
	}
}

test1.php

<?php
require 'fatalerrorhandler.php';

// Fatal Error (E_ERROR)
unknown_function_call();

test2.php

<?php
require 'fatalerrorhandler.php';

// E_USER_ERROR
trigger_error('...', E_USER_ERROR);

test3.php

<?php
require 'fatalerrorhandler.php';

// Notice (E_NOTICE)
echo $unknown_var;