ASP.NET ist gar nicht so schlecht, behauptet sogar Zeev Suraski. Doch keine Sorge, in diesem Artikel soll keiner bekehrt werden. Ganz im Gegenteil: Es ist möglich, in .NET geschriebene Komponenten auch von PHP aus zu verwenden.
Lange Zeit war nicht klar, das hinter dem ominösen „.NET“ stecken sollte, das Microsoft im Jahr 2001 erstmals vorgestellt hat. Mittlerweile ist das Konzept bekannt: Hauptkomponente von .NET ist das .NET Framework, eine umfangreiche Klassenbibliothek mit Funktionalitäten für fast jede erdenkliche Anwendung. .NET-Programme können auf diese Klassenbibliothek zugreifen und deren Funktionen verwenden.
Allerdings gibt es schon hier einen gewissen Nachteil: Diese Klassenbibliothek muss beim Client natürlich vorhanden sein, damit sie von .NET-Programmen verwendet werden kann. Konsequenz: Zur Ausführung von .NET-Software ist das .NET Framework erforderlich. Immerhin ist das kostenlos und mittlerweile sogar über Windows Update erhältlich (als optionale Komponente).
Interessant ist die .NET-Technologie allemal. Sogar einige bekannte und bekennende PHP-Entwickler wie Sterling Hughes finden die Technologie an sich sehr durchdacht. Doch wie eben jeder Blog-Eintrag zeigt, geht es zunächst nicht um die Entscheidung, welche Technologie geeigneter ist, sondern auf welches Betriebssystem gesetzt wird. Und .NET hat zurzeit noch den großen Vorteil, dass es nur unter Windows läuft. Es gibt zwar Projekte wie Mono [1] und dotGNU [2], doch diese hinken natürlich immer dem hinterher, was Microsoft veröffentlicht.
Setzt man also auf Uinx/Linux, ist PHP eine feine Wahl. Unter Windows sollte man sich einmal (ASP).NET ansehen; eine Netcraft-Studie aus dem Oktober 2003 zeigt aber auch, dass PHP unter Windows erstaunlich stark ist [3].
In diesem Artikel zeigen wir das Beste aus beiden Welten: Programmieren in PHP, aber unter Rückgriff auf .NET-Funktionalität. Eine Einschränkung gleich zu Beginn: Die Erweiterung hat noch einige Bugs und Eigenheiten, doch Wez Furlong, der Entwickler der Erweiterung, freut sich über jede Hilfe.
Zur Verwendung der - im Übrigen als experimentell gekennzeichneten - .NET-Erweiterung von PHP benötigen Sie zunächst einmal Windows samt .NET Framework. Kleiner Trost: Sie müssen nicht die php.ini anpassen, denn auf Windows-Systemen ist die .NET-Erweiterung automatisch aktiv; phpinfo() gibt hier die entsprechende Auskunft. Suchen Sie nach com_dotnet und dann den Eintrag .NET support.
.NET unter PHP
Das schöne an der .NET-Erweiterung von PHP ist, dass es nur eine Methode gibt. Der Einsatz ist also sehr einfach, denn es gibt dazu eine Klasse namens DOTNET. Deren Konstruktor benötigt (neben dem Klassennamen) lediglich den Namen der Assembly. Der Begriff Assembly bezeichnet unter .NET ein Gebilde, das Ressourcen (beispielsweise Bibliotheken), Versionierungsinformationen, Namensraum und Zugriffskontrolle beinhaltet. Hier ein einfaches Anwendungsbeispiel: Die Klasse System.Random wird initialisiert:
<?php
$zufall = new DOTNET('mscorlib', 'System.Random');
?>
Also ist mscorlib der Name der Assembly, System.Random ist der gewünschte Klassenname. Den Namen der Assembly können Sie der Dokumentation des .NET Framework entnehmen (ist unter anderem im .NET Framework SDK mit dabei - eine über 100 MB große Variante des .NET Framework mit viel Dokumentation und Zusatztools [4]). Es gibt auch noch einen zweiten Weg: Für ASP.NET gibt es unter [5] einen kostenlosen Editor. Dieser enthält in derselben Programmgruppe wie die IDE eine Anwendung namens ClassBrowser. In dieser sind alle Klassen des .NET Framework aufgelistet, inklusive Assembly-Infos.

Abb. 1: Der ClassBrowser verrät: System.Random liegt in mscorlib
Aber zurück zur Programmierung: Der Rückgabewert von new DOTNET() verhält sich wie die .NET-Klasse. Es stehen alle Methoden und Eigenschaften zur Verfügung. Bei der Zufallsklasse ist es beispielsweise so, dass die Methode Next() eine neue (nächste) Zufallszahl ermittelt. Hier ein kurzes Listing, das drei Zufallszahlen erzeugt und ausgibt:
<?php
$zufall = new DOTNET('mscorlib', 'System.Random');
$zufallszahl[] = $zufall->Next();
$zufallszahl[] = $zufall->Next();
$zufallszahl[] = $zufall->Next();
echo implode(' ', $zufallszahl);
?>

Abb. 2: Drei Zufallszahlen - mit .NET
Grenzen (und Umwege)
Wie Abbildung 2 zeigt erhalten Sie drei Zahlen, meist neun- oder zehnstellig. Das liegt daran, dass Next() einen positiven 32-Bit-Integer-Wert zurückliefert, also eine Zahl von 0 bis 2147483647. Es gibt einen Ausweg in .NET: Sie können Next() als Parameter mitgeben:
- Eine Obergrenze (die Untergrenze ist automatisch 0)
- Eine Unter- und eine Obergrenze
Leider stößt hier PHP an seine Grenzen, weil Überladung nicht möglich ist. Das bedeutet, dass bei gleichnamigen Methoden immer die erste verwendet wird. Wenn Sie also versuchen, in dem Skript zufall.php einem Aufruf von Next() einen oder zwei Parameter zu geben, erhalten Sie eine Fehlermeldung (Abb. 3).

Abb. 3: Es gibt leider keine Überladung
Das macht es schon etwas schwieriger, eine Zufallszahl aus einem bestimmten Bereich zu ermitteln. Sie müssen also den Wert (zwangsweise zwischen 0 und 2147483647) auf ihren gewünschten Bereich skalieren. Dazu später mehr!
Zuvor noch ein weiteres Beispiel. Unter System.Collections bietet .NET eine Reihe von Kollektionen an, also Formen von Arrays und Listen: ArrayList, Hashtable, Queue, Stack und einige mehr. Auch dies können Sie mit .NET verwenden. Wir zeigen das am Beispiel einer
ArrayList, also einem Array, in das Sie beliebige Objekte ablegen können. Da alle .NET-Sprachen typisiert sind, ist das in der Tat ein funktionaler Vorteil gegenüber herkömmlichen Arrays, denn die akzeptieren (in .NET) jeweils nur einen Datentyp für alle Elemente. Die folgenden Methoden und Eigenschaften sind wichtig:
- Die Methode Add() fügt ein Element in die Liste ein
- Die Eigenschaft Count gibt an, wie viele Elemente sich im Array befinden
- Die Eigenschaft Item liefert ein Element des Arrays zurück; sein Index wird in runden Klammern angegeben
- Sort() sortiert die Elemente im Array
Das folgende Listing erzeugt eine ArrayList, füllt sie mit Werten, sortiert diese und gibt sie per for-Schleife aus, unter Verwendung der vier vorgestellten Methoden bzw. Eigenschaften:
<?php
$liste = new DOTNET('mscorlib', 'System.Collections.ArrayList');
$liste->Add(31);
$liste->Add(23);
$liste->Add(42);
$liste->Sort();
for ($i = 0; $i < $liste->Count; $i++) {
echo $liste->Item($i) . ' ';
}
?>
Anwendungsbeispiel
Nach der ganzen Theorie folgt die Praxis. Wir zeigen ein kleines Anwendungsbeispiel, das die zuvor gezeigten Listings in einen Zusammenhang bringt.
Mit .NET können Sie Zufallszahlen erzeugen und Werte in einem Array ablegen. Da liegt die Idee nahe, beides zu kombinieren: Per Zufallsklassen ziehen wir sechs (verschiedene) Zahlen von 1 bis 49, sortieren sie und geben sie aus.
Das größte Hindernis ist wohl die Ermittlung einer Zufallszahl von 49. Erinnern Sie sich: Die Methode Next() von System.Random liefert eine Zahl zwischen 0 und 2147483647. Wenn Sie diesen Wert durch 2147483648 teilen, erhalten Sie eine Zahl zwischen 0 (einschließlich) und 1 (ausschließlich). Multiplizieren Sie diesen Wert mit 49, erhalten Sie einen Wert zwischen 0 (einschließlich) und 49 (ausschließlich). Der Aufruf von intval() wandelt dies in eine ganze Zahl um. Sie erhalten also eine Integer-Zahl von 0 bis 48, jeweils einschließlich. Addieren Sie noch 1 dazu, und schon haben Sie eine Lottozahl von 1 bis 49. Das ist jetzt relativ aufwendig gewesen, aber einmal „Gehirnschmalz“ investiert, und Sie können den Code immer wieder verwenden:
$zufall = new DOTNET('mscorlib', 'System.Random');
$zufallszahl = $zufall->Next();
$zufallszahl = intval(49 * $zufallszahl / 2147483648) + 1;
Vor dem Schreiben in das Array müssen Sie überprüfen, ob die Zahl bereits einmal gezogen worden ist - es sollen ja sechs verschiedene Lottozahlen ermittelt werden. Das kann .NET - die
ArrayList kennt die Methode Contains(), die in etwa mit der PHP-Funktion in_array() vergleichbar ist.
$zahlen = new DOTNET('mscorlib', 'System.Collections.ArrayList');
if (!$zahlen->Contains($zufallszahl)) {
$zahlen->Add($zufallszahl);
}
Der Rest ist nicht weiter aufwendig. Per while-Schleife fügen wir so lange Zufallszahlen in das Array ein, bis dessen Eigenschaft Count den Wert
6 hat. Nach einer Sortierung mit Sort() durchlaufen wir das Array und geben alle Zahlen wieder aus. Listing 1 zeigt das komplette Listing.
Listing 1
<?php
$zahlen = new DOTNET('mscorlib', 'System.Collections.ArrayList');
$zufall = new DOTNET('mscorlib', 'System.Random');
while ($zahlen->Count < 6) {
$zufallszahl = $zufall->Next();
$zufallszahl = intval(49 * $zufallszahl / 2147483648) + 1;
if (!$zahlen->Contains($zufallszahl)) {
$zahlen->Add($zufallszahl);
}
}
$zahlen->Sort();
for ($i = 0; $i < $zahlen->Count; $i++) {
echo $zahlen->Item($i) . " ";
}
?>

Abb. 4: 6 aus 49 mit .NET
PEAR und .NET
In PEAR gibt es keine Klasse zur Ansteuerung der .NET-Erweiterung von PHP 5, allerdings hat Sterling Hughes für PECL eine Extension geschrieben, das die Open-Source-Variante von .NET, Mono, ansprechen kann. Sie benötigen dazu Mono selbst [1] sowie die aktuellste Version der Mono-Erweiterung von der Projekt-Homepage [6].
Entpacken Sie das tgz-Archiv in das ext-Verzeichnis des PHP-5-Quellcodes und konfigurieren Sie PHP neu:
./buildconf
./configure --with-mono
Nach einiger Zeit ist der Kompilierungsprozess fertig und Sie können mit der Mono-Erweiterung fast genauso arbeiten wie mit der .NET-Erweiterung von PHP. Sie können sich sogar den Assemblynamen sparen und müssen beim Konstruktor lediglich den Klassennamen angeben:
<?php
$zufall = new Mono('System.Random');
$zufallszahl[] = $zufall->Next();
$zufallszahl[] = $zufall->Next();
$zufallszahl[] = $zufall->Next();
echo implode(' ', $zufallszahl);
?>
Weitere Informationen über die Mono-Erweiterung inklusive einiger Beispiele gibt es auf der zugehörigen Website von Sterling Hughes [7].
Einschränkungen
Die .NET-Extension von PHP 5 ist sehr praktisch, um bestehende .NET-Business-Logic gut in PHP integrieren zu können. Doch leider ist die Erweiterung noch nicht komplett ausgereift. Auf manchen Systemen will die Installation gar nicht erst funktionieren, bei manchen Listings kommen merkwürdige Fehlermeldungen à la „zu wenig Speicher“, und Dokumentation gibt es dazu relativ wenig. Also: Eine sehr interessante Spielwiese, aber (noch) nicht massenkompatibel.
Christian Wenz ist Autor, Trainer und Berater mit Schwerpunkt Webtechnologien. In seiner Serie "x ohne x" zeigt er regelmäßig, wie PHP ungeahnte Fähigkeiten entwickeln kann. Der Autor verweis auf das Buch "PHP 5 Kompendium", das er zusammen mit Tobias Hauser geschrieben hat, in dem Sie mehr zu diesem Thema erfahren können. Er bloggt unter www.hauser-wenz.de/blog/.
Links