Kategorien Kategorien: PHP

PHP Enum – einfach mal ganz schwierig

Variablen können in einigen Programmiersprachen vom Type ENUM sein. In PHP leider nicht.

Die SPLEnum-Klasse lasse ich mal weg

Wenn eine Variable vom Type ENUM ist, dann kann Sie vorher definierte Werte annehmen – und nur diese. Z.B. könnte man so Farben definieren. Mein Auto gibt es nur in Schwarz, Gelb und Grün. Somit muss ich beim Programmieren immer darauf achten, dass meine Variable „$myCarColor“ nur diese Werte annehmen kann. Wäre sie als ENUM definiert, so würde PHP automatisch dafür sorgen, das dort nichts anders drin stehen kann.

Das gibt es aber (noch) nicht so richtig in PHP. Also müssen wir uns selbst etwas überlegen.

Die einfachste Möglichkeit ist, eine Art „Liste“ bereit zu stellen, die die entsprechenden Werte bereit stellt, und diese in Form von Klassenkonstanten zu verpacken:


/**
 * Class EColor
 */
class EColor {

	const BLACK  = 1;
	const YELLOW = 2;
	const GREEN  = 4;

}

// Usage:

setColorExampleFunction( EColor::BLACK ); // EColor::Black = 1

Im Beispiel wird der Wert 1 (für die Farbe BLACK stehend) an eine beliebige Funktion übergeben. Das ist zwar ein Schritt in die richtige Richtung, da man sich nicht die Zahlen merken muss, sondern einfach die Variable nehmen kann, aber es gibt noch (mindestens) ein Problem: Die Funktion erwartet eine Variable vom Type INTEGER – keine Farbe. Ich könnte auch den Wert 3 oder 5 übergeben – das wäre aber keine Farbe (weil der Wert nicht existiert). Gut wäre, wenn wir einen TypeHint in der Funktion angeben könnten und somit sicherstellen können, das wir das bekommen, was wir wollen.

Folgendes Beispiel geht da ein paar Schritte weiter:


/**
 * Class MyColor_reflection
 */
class MyColor {

	const BLACK  = 1;
	const YELLOW = 2;
	const GREEN  = 4;

	private $currentColor;
	private $colors = [];

	/**
	 * MyColor constructor.
	 */
	public function __construct() {

		$this->setColors();

		$this->setBlack();
	}

	public function setBlack() {

		$this->setSomeColor( 'BLACK', self::BLACK );
	}

	public function setYellow() {

		$this->setSomeColor( 'YELLOW', self::YELLOW );
	}

	public function setGreen() {

		$this->setSomeColor( 'GREEN', self::GREEN );
	}

	public function getCurrentColor() {

		return $this->currentColor;

	}


	/**
	 * @param string $name
	 * @param int    $value
	 */
	protected function setSomeColor( $name, $value ) {

		$this->currentColor          = [];
		$this->currentColor[ $name ] = $value;

	}

	protected function setColors() {

		$reflectionClass = new ReflectionClass( $this );
		$constants       = $reflectionClass->getConstants();

		foreach ( $constants as $key => $value ) {
			$this->colors[ $key ] = $value;
		}

	}

}

// Usage:
$myColor = new MyColor();
$myColor->setYellow();

$currentColor = $myColor->getCurrentColor();

$currentColorName  = key( $currentColor );          // YELLOW
$currentColorValue = current( $currentColor );      // 2


function setColorWithHintExampleFunction(MyColor $color){
	// Some code ...
}

setColorWithHintReflectionExampleFunction( $myColor );

Jetzt können wir sicher sein, dass der Funktion wirklich nur definierte Werte übergeben werden. Außerdem kann man sowohl die Farbe entweder als Zahl oder als String bekommen.

ABER:

Das ist viel Schreibarbeit und auch an mindestens einer Stelle doppelt zu warten (nicht wirklich DRY):

Konstanten werden einmal oberhalb des Konstruktors definiert. Der gleiche Konstantenname muss aber auch in der entsprechenden Methode vorhanden sein. Man könnte das noch etwas verbessern, aber das Grundproblem würde bleiben: es ist nicht DRY.

Problematischer ist, dass der umgekehrte Weg (aus einer Zahl oder einem String diese Klasse erstellen) schwierig ist.

Es sollte eine Möglichkeit geben, aus entweder String oder Zahl die Klasse mit entsprechenden Wert zurück zu bekommen.

Das ist dann aber ein Thema fürs nächste mal.

Autor: admin

Programmierer (Web) und Musiker

Schreibe einen Kommentar