PHP Iterator, IteratorAggregate mit current(), next() etc. nutzen

Einige Anmerkungen zu PHP Traversables

Iteration mit Funktionen

Traversables können mit foreach iteriert werden, jedoch nicht im allgemeinen mit Array-Iterations Funktionen wie reset() und next().

Iterator Objekte können auch auch mit folgenden Funktionen verwendet werden:

  • current()
  • next()
  • prev()
  • reset()
  • end()

Achtung: Es ist zwar möglich, allen diesen Funktionen IteratorAggregate Objekte zu übergeben (wie auch jedes andere Objekt), die Iterator-Funktionalität wird dabei aber nicht genutzt, sondern es wird über die Attribute des Objekts iteriert.

Das selbe gilt für Iterator Objekte mit each()! Dieses sollte generell nicht für Objekte benutzt werden, da hilft weder ArrayAccess noch Iterator. Es funktioniert im allgemeinen nie wie erwünscht.

Überprüfung von unbekannter Variable auf Iterierbarkeit mit foreach

$a implements Traversable || is_array($a);
  • Traversable ist vor Iterator zu bevorzugen da auch IteratorAggregate und andere interne Iteratoren damit erkannt werden.
  • Arrays sind keine Traversables, da keine Objekte

Will man allerdings volle Flexibilität genügt:

is_object($a) || is_array($a)
  • PHP kann beliebige Objekte als Iterator benutzen und iteriert dabei über die öffentlichen Attribute!

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)