PHPFlüsterer

Tag: PHP (page 1 of 6)

Compile PHP and/or an extension under Win(x86)

This guide is based on the following official php.net Wiki Page. This guide covers the compile process of

  • PHP (>= 5.5)
  • a PHP-extension (Pecl)

under Windows with Microsoft Visual Studio Express 2012 for Windows Desktop. As result of this operation we will get binaries of PHP for Windows as well as an extension (php_*.dll). We will use the uprofiler extension (php_uprofiler.dll) as example.

Requirements

Before we start with the compile process we need the following software, libraries, tools and dependencies for this guide:

Preparation / Setup

Install Microsoft Visual Studio Express 2012 for Windows Desktop. We do not need any special configuration. Just install in default setup.

We need to create directory C:\php-sdk with the following command

mdkir C:\php-sdk

Afterwards

open VS2012 x86 Native Tools Command Prompt (it's available from the start menu) 

and execute the following commands

C:  
cd C:\php-sdk\    
bin\phpsdk_setvars.bat    
bin\phpsdk_buildtree.bat phpdev    

Extract the PHP sourcecode to C:\php-sdk\phpdev\vc11\x86\php-source-directory. As result of this operation you should have a win32 directory within the C:\php-sdk\phpdev\vc11\x86\php-source-directory directory (C:\php-sdk\phpdev\vc11\x86\php-source-directory\win32).

Extract the PHP build dependencies to C:\php-sdk\phpdev\vc11\x86. As result of this operation you should have a deps directory within the C:\php-sdk\phpdev\vc11\x86 directory (C:\php-sdk\phpdev\vc11\x86\deps).

Compile PHP

To compile PHP we need to change the directory to the path of your PHP source code

cd C:\php-sdk\phpdev\vc11\x86\php-source-directory

Afterwards we run

buildconf

to prepare everything. It makes the configure command available and provide it with the current available flags for compiling. To get an overview of the available build/compiler flags you can use the command

configure --help

Based on this information create your configure command like this:

configure --disable-all --enable-cli --enable-$remains

Note: The deps should include the libraries needed to build most the core extensions. However, some other extensions may need additional libraries, header files and helper apps. See libs, fetch the version you need and extract the archive into the deps directory.

After you have configured how you want to build PHP, you can run

nmake

If you want the resulting PHP builds and extensions to be zipped, after nmake also run

nmake snap

The compiled PHP is now available under C:\php-sdk\phpdev\vc11\x86\php-source-directory\Release_TS. If you ran nmake snap the zip file will also be here. If you compiled with –disable-zts the compiled PHP will be under C:\php-sdk\phpdev\vc11\x86\php-source-directory\Release.

Recompile after changes

If we want to compile PHP again – after we did some changes for example – we need to clean up old compiled binaries, objects, deps first. This is done with the following commands.

Change to PHP source directory

cd C:\php-sdk\phpdev\vc11\x86\php-source-directory

and call the cleanup command

nmake clean

If you need to update the configure script

buildconf --force

Afterwards create your makefile

configure --disable-all --enable-cli --enable-$remains

And now start compile again

nmake

Adding an extension (PECL and non-PECL)

Theoretically it doesn’t matter which type of extension you are about to compile. If it is not a PECL extension you will just need to do some extra steps. But in general the compile process is similar to a PECL extension. So for this example we are using the non-PECL extension uprofiler.

Navigate to the x86 directory:

cd C:\php-sdk\phpdev\vc11\x86

Create a directory named pecl:

mkdir C:\php-sdk\phpdev\vc11\x86\pecl

Extract the previously downloaded archive uprofiler-master.zip in some temporary directory and put the content of the contained extension directory into

C:\php-sdk\phpdev\vc11\x86\pecl\uprofiler-X.Y.Z

where x,y and z are the current major (x), minor (y) and release (z) number. If you have downloaded an extensions sourcecode archive directly from PECL you will always find an versioned directory after extracting the archive. Extensions from other sources often does not have an already versioned directory. So we just create one by our own. At the time writing this tutorial uprofiler‘s most recent version is 0.9.4 (Note: While it will say 0.10.5 when compiled!). So for this example we would create a directory

C:\php-sdk\phpdev\vc11\x86\pecl\uprofiler-0.9.4

Now change to PHP‘s source directory

cd C:\php-sdk\phpdev\vc11\x86\php-source-directory

and call

buildconf

afterwards execute

configure --help

The output should now contain a --enable-uprofiler option.
Configure PHP to compile nothing but the uprofiler extension.

configure --disable-all --enable-cli --enable-uprofiler=shared

Note: We need to compile it “shared” otherwise it will collide with already existing object _getrusage.

nmake

Test the binary with this command

php -m

to make sure uprofiler exists.

Utilities

Resource Hacker

This utility shows dependency information and other assembly information from a DLL. For instance, it shows which version of the Visual C++ Runtime the DLL was linked against.

We can get it here

WebSockets – Vom Client zum Server und zurück (Teil 1)

Dieser Artikel ist der Beginn einer kleinen Serie, die dir das Thema WebSockets und deren Einsatzmöglichkeiten ein wenig näher bringen soll. Bei WebSockets handelt es sich um eine der Neuerungen aus dem HTML5-Paket. WebSockets können ein mächtiges sowie einfach einzusetzendes Feature zugleich sein. Das die Möglichkeiten zum Einsatz vielfältig sind, steht wahrscheinlich außer Frage. Doch einfach einzusetzen? Diesen Eindruck könnte man haben, nachdem man sich die WebSocket-API Spezifikation durchgesehen hat und dabei das recht simple Interface näher betrachtet. Doch es sollte bei meinen Experimenten ganz anders kommen. Dieser Artikel soll dir helfen, nicht in die gleichen Fallen zu tappen wie ich, die folgenden Fragen beantworten:

  • Was sind WebSockets?
  • Wie setzt man WebSockets ein?
  • Was benötige ich um auf einen WebSocket zuzugreifen?
  • Wie sieht die Fallback-Variante für ältere Clients aus?
  • Wer nimmt die Daten entgegen bzw. wer antwortet mir?

und zusätzlich davor bewahren, unnötig viel Zeit bei der Abstimmung der beteiligten Komponenten zu verschwenden. Doch fangen wir vorne an …
 
 

Was ist ein WebSocket eigentlich?

Bevor wir tiefer in die Materie eintauchen, sollten wir vielleicht vorher mal kurz mit der Definition des WebSockets beginnen. Schauen wir doch dazu erstmal was Wikipedia uns verrät:

Das WebSocket-Protokoll ist ein auf TCP basierendes Netzwerkprotokoll, das entworfen wurde, um eine bidirektionale Verbindung zwischen einer Webanwendung und einem WebSocket-Server bzw. einem Web-Server, der auch WebSockets unterstützt, herzustellen.

Also haben wir es mit einer klassischen Socket-to-Socket Verbindung zu tun, so wie man sie auch von anderen Anwendungsfällen kennt. Beim Begriff WebSocket handelt es sich also mehr um ein Kunstwort als um eine vollständig neuartige Implementierung. Der eigentlich Socket wird lediglich durch ein paar Schichten abstrahiert und im Browser über eine API zur Verfügung gestellt. Von dort (Client) aus geht es zum Server (Server) der ebenfalls das WebSocket-Protokoll spricht. Mit diesem Server wird eine Verbindung aufgebaut. Das bedeutet, dass wir es mit mind. zwei Teilnehmern zu tun haben, dem Client und dem Server (WebSocket-Server / Webserver). Wir dürfen hier nur nicht eine entscheidende Komponente vergessen, die Middleware. Doch dazu kommen wir später. Kommen wir nun erst einmal zu Client und dem Server.
 
 

Client (Browser) support für WebSockets

Der aktuelle Status ist “working draft” in Version 17 und das Protokoll liegt in Version 13 vor. Details zur aktuellen Unterstützung durch die diversen Clients (Browser) können wir der folgenden Abbildung entnehmen:

WebSocket Unterstützung in Webbrowsern - Statistik von caniuse.com/WebSocket

WebSocket Unterstützung in Webbrowsern – Statistik von caniuse.com/WebSocket

Um im Browser via JavaScript auf das WebSocket-Interface zugreifen zu können, muss dieses ja in erster Linie existieren. Da wir aufgrund der vielfältigen Browser-Versionen nicht davon ausgehen können, dass jeder Client WebSockets unterstützt, kommen wir zur ersten Hürde die zu nehmen ist. Wir müssen also vor dem Zugriff wissen, ob der Client dieses Feature überhaupt unterstützt. Außerdem wollen wir via JavaScript auf die Schnittstelle zugreifen und eine akzeptable Fallback-Lösung haben. Bezüglich dieser Anforderungen war die Auswahl schon recht stark reduziert, zumal ich eine Lösung suchte, die zusätzlich auch noch auf jQuery basieren soll. Ich setze jQuery bei einer Vielzahl von Projekten ein und somit sollte hier nicht schon wieder eine vollständig neue Bibliothek eingesetzt werden müssen. Zusammengefasst haben folgende Voraussetzungen meine Entscheidung beeinflusst:

  • das Gewicht der Seite soll nicht unnötig steigen
  • das Gewicht der Seite soll nicht zu sehr steigen
  • aufrgunddessen möglichst auf eine auf jQuery-basierende Lösung zurückgegriffen wird
    (aufgrund der bestehenden XHR-Implementierung für die Fallback-Variante)
  • die Lösung muss stabil sein (reliable + rock solid)

und so blieb letztlich nur ein Kandidat übrig:

Alle anderen Lösungen haben entweder nicht korrekt funktioniert, oder hatten keine solide Fallback-Variante implementiert. Als Fallback-Variante wollte ich eine auf AJAX-long-polling basierende Lösung. Dieses Verfahren ist, jedenfalls zum aktuellen Zeitpunkt noch, der Standard für das kontinuierliche Beziehen von Daten vom Server. Bei diesem Verfahren wird über das XHR-Interface des Browsers in der Regel in fest definierten Abständen ein Request abgesetzt und die Antwort vom Server auf neue Inhalte geprüft und entsprechend weiter bearbeitet. Dieses Verfahren hat sich bewährt, da es einfach zu implementieren ist und fast alle gängigen JavaScript-Bibliotheken vereinfachte Schnittstellen zum XmlHttpRequest-Objektes des Browsers zur Verfügung stellen. Wenn du dich fragst, warum ich nicht auf eine fertige Endpunkt-zu-Endpunkt Implementierung wie z. B. Socket.io zurückgegriffen habe, zumal ich gleich bei der Gegenstelle (Server) auf Node.js eingehen werde, der sei darauf hingewiesen, dass der Trade-off einfach zu groß wäre mit einer Client-Bibliothek (socket.io.js) die unkomprimiert 63 KB und minified immer noch 32 KB schwer ist. Das widerspricht (leider) den o. g. Voraussetzungen.
 
 

Gegenstelle – der Socket-Server

Wie wir vom Client aus einen Request absetzen können, ist jetzt (zumindest theoretisch) schon mal geklärt. Doch wer nimmt unsere Anfrage entgegen und antwortet uns auf diese? Meine Recherchen haben eine Vielzahl an möglichen Lösungen zu Tage gebracht. Diese reichten von simpel, properitär und experimentell bis zu stabil und einsetzbar. Die Server-Software die ich mir angeschaut habe, möchte ich der Vollständigkeit halber hier mal aufführen:

Es gibt also eine Vielzahl an möglicher Server-Software die wir einsetzen könnten. Hier bin ich in die erste größere Falle gelaufen. Achte bei deiner Wahl des Socket-Servers unbedingt auf die Unterstützung der aktuellsten Protokoll-Version. Aus Gründen der Sicherheit wurde das Handshake-Verfahren im Laufe der Protokoll-Evolution entscheidend verändert, so daß eine augenscheinlich gut geschrieben Open-Source-Lösung in PHP mich aufgrund der alten Protokoll-Implementierung fast zum Verzweifeln gebracht hat. Nach ausgiebigem Debugging, Fehler finden und beseitige, sowie anschließend korrekter Implementierung des Handshakes musste ich feststellen, dass PHP in Verbindung mit dem Apachen in Version 2.x einfach nicht das richtige Werkzeug zu sein scheint. Es performte einfach nicht so, wie ich es mir vorgestellt hatte. Somit habe ich mich umorientieren müssen. Aufgrund der Artikel und Bücher die ich in den letzten Monaten gelesen habe sowie den Erfahrungen die ich mit Node.js sammeln konnte, habe ich mich dann für den Einsatz von Node.js in Verbindung mit dem Paket WebSocket-Node entschieden. Node.js ist äußerst performant, skaliert hervorragend und es gibt eine Vielzahl von Paketen mit denen Node.js erweitert werden kann. So stehen uns z. B. mit Cradle ein Paket zum Zugriff auf CouchDB oder mit node-mysql ein Paket zum Zugriff auf MySQL-Datenbanken zur Verfügung. Ich werde mich in diesem HowTo, beim Einsatz des Socket-Servers, allerdings auf die Auslieferung von Dummy-Daten beschränken. Eine Datenbank im Backend anzubinden ist dann allerdings nur noch ein kleiner Schritt. Dieser kann in der Regel auf Basis der Informationen und mit Hilfe der HowTo’s auf den jeweiligen Projektseiten realisiert werden.
 
 

Die URI-Schemen – wie ist die Adresse?

Die WebSocket-Protokoll-Spezifikation definiert zwei neue URI-Schemen, ws: für unverschlüsselte, und wss: für verschlüsselte Verbindungen.
 
 

Das Protokoll – welche Sprache sprechen wir?

Zu Beginn einer jeden Verbindung führen Server und Client einen sogenannten Handshake durch. Dieser ähnelt vom Aufbau her dem HTTP-Header und ist vollständig abwärtskompatibel zu diesem, was die Nutzung des Standard-HTTP-Ports “80” zugleich für normale HTTP-Kommunikation als auch für die Websocket-Nutzung ermöglicht. Der Handshake beinhaltet außerdem weitere Informationen (z. B. die verwendete Protokollversion).
 
 

Anfrage des Clients

Im Folgenden ist ein Beispielhandshake des siebzehnten Protokollentwurfs (17) dargestellt und erläutert:

[cc lang=”php”]
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
[/cc]

Achtung: Ältere Protokollentwürfe können sehr stark von dieser Version des Protokolls abweichen, da es aufgrund von Sicherheitsbedenken umgestaltet wurde!

Wie auch im HTTP-Protokoll gibt der Client an, auf welche Ressource (hier: /chat) und auf welchen Host (hier: server.example.com) er zugreifen möchte. Außerdem fordert der Client ein Upgrade auf das Websocket-Protokoll. Der zufällig generierte “Sec-WebSocket-Key” dient zur Überprüfung, ob der Server die Anfrage tatsächlich gelesen und verstanden hat (siehe Abschnitt Antwort des Servers). Unter “Sec-WebSocket-Protocol” hat der Client die Möglichkeit, auf das Websocket-Protokoll aufbauende Protokolle anzugeben, die die Clientanwendung unterstützt (hier: ein Chat-Protokoll). Selbsterklärend sollte unter “Sec-WebSocket-Version” die verwendete Protokollversion angegeben werden.
 
 

Antwort des Servers

Auf die obige Beispielanfrage könnte ein Websocket-Server beispielsweise wie folgt antworten:

[cc lang=”php”]
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
[/cc]

Durch den HTTP-Statuscode 101 und die folgenden zwei Zeilen erklärt der Server, dass er mit dem Wechsel des Protokolls einverstanden ist.

Der zurückgesendete Schlüssel unter “Sec-WebSocket-Accept” dient der Verifikation, dass der Server die Anfrage des Clients gelesen hat. Er wird wie folgt erstellt: An den oben erwähnten, Base64-kodierten String, den der Client sendet (“Sec-WebSocket-Key”) wird der Globally Unique Identifier 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 angehängt. Daraufhin wird ein SHA1-Hash des entstandenen Schlüssels erstellt und Base64-kodiert. Anzumerken ist hierbei, dass der ursprünglich empfangene Schlüssel zwar Base64-kodiert ist, jedoch zu keinem Zeitpunkt dekodiert wird.

In diesem Beispiel gibt der Server zusätzlich an, dass er das angeforderte Protokoll “chat” kennt (“Sec-WebSocket-Protocol”).
 
 

Zusammenfassung

Fassen wir zusammen: Wir wissen jetzt was ein WebSocket ist, wie man auf diesen zugreifen und entsprechend nutzen kann (jedenfalls in der Theorie), an welchen Stellen wir besonders acht geben müssen und welche Software Client- und Server-seitig eingesetzt werden kann. Jetzt ist es an der Zeit die Informationen aus der Theorie in die Praxis zu überführen. Während ich an Teil 2 schreibe und die Codebeispiel vorbereite, empfehle ich dir, dich mit der angebotenen Software ein wenig näher zu befassen, da ich z. B. nicht im Detail auf die Funktionsweise von jQuery oder Node.js eingehen werden kann. Zu Node.js: Die Installation geht wirklich fix von der Hand und das experimentieren mit Node.js macht Spaß – so findet man am besten den Einstieg für die weitere Entwicklung mit Node.js.
 
 

Ausblick

In Teil 2 der Artikel-Serie werde ich Client- und Server-seitige Codebeispiele zeigen, erklären warum das Plugin jquery.gracefulWebSocket.js den Anforderungen vielleicht doch nicht reicht und warum wir ggf. mehr Komponenten benötigen als anfänglich gedacht (wie z. B. HAProxy).

PHP Coding-Standards und Programmierrichtlinien

Mit der zunehmenden Professionalität in PHP-Projekten der letzten Jahre, stieg auch die Anzahl der mir bekannten Coding-Standards und Programmierrichtlinien. Mittlerweile finden sich im World Wide Web unzählige Dokumente aus den unterschiedlichsten Projekten und in unterschiedlichsten Detailstufen.

Viele große Open-Source-Projekte, allen voran das PEAR-Projekt, haben einen Beitrag zur Vereinheitlichung der unterschiedlich gewachsenen Standards geleistet. Am bekanntesten sind im PHP-Umfeld wohl, schon aufgrund ihres Alters, die PEAR-Coding-Standards. Viele Coding-Standards basieren auf den Standards die die PEAR-Entwicklergemeinde erarbeitet hat. Auch die von mir ausgearbeiteten Coding-Standards sind eine Erweiterung, sowie Verfeinerung der bekannten PEAR-Standards. Deshalb dürften die verwendeten Regeln und Vorgaben den meisten von euch nicht fremd sein.

Wenn ich heute auf den Anfang von PHP zurückblicke, dann muss ich sagen, dass die Entwicklung grundsätzlich überwiegend positiv ist und sich PHP als Sprache, sowie die dazugehörende Community stetig weiter Richtung “Enterprise” entwickelt. Nur zu gut erinnere ich mich nämlich an die Zeit zurück, als PHP noch jung war und es noch keine Coding-Standards für PHP-Projekte gab. Projekte mit halbgarem OOP- (dies ist aber der Sprache geschuldet) / Spaghetti-Code waren das Resultat. Doch mit der Sprache sind in den letzten Jahren auch die Entwickler reifer geworden.

So wurde mit der “PHP-Standards-Working-Group” die nächste Stufe zu mehr Professionalität erreicht. In dieser Gruppe, die sich zum Ziel gesetzt hatte, die Interoperabilität der beteiligten Projekte zu steigern, wurde seit Anfang 2009 zuerst ein einheitlicher Autoloader unter dem Codenamen PSR-0 vorgestellt und dieser dann in unzähligen Runden verfeinert. Der PSR-0 getaufte Standard hat weithin Gültigkeit und wurde nach meiner Kenntnis von vielen Projekten akzeptiert sowie adaptiert. Die Gruppe wurde mittlerweile (22.11.2012) aufgelöst und die Aufgabe von der “PHP Framework Interoperability Group” übernommen.

Einige Teile des PSR-0 Standards habe ich in die erste Fassung der “PHPFlüsterer Coding-Standards und Programmierrichtlinien” aufgenommen. Allerdings erhebe ich aktuell noch keinen Anspruch auf Vollständigkeit. Mein erklärtes Ziel ist es, jetzt zuerst euer Feedback sowie konstruktive Kritik einzusammeln, dann die fehlenden Teile zu übertragen bzw. zu ergänzen und die Ergebnisse in einer der nächstenVersionen zu veröffentlichen.

Im Anschluss werden auch die passenden Rulesets für den “PHP-Codesniffer” sowie den Codeformatter der Zend-IDE (bzw. Eclipse/PDT) von mir veröffentlicht.

 

ACHTUNG!
Gesucht wird ein Übersetzer, der die finale Fassung 1.0.0 in die englische Sprache übersetzt. Wer Interesse an diesem Job hat, der möge bitte Kontakt mit mir aufnehmen.

 

Download PHPFlüsterer Coding-Standard und Programmierrichtlinien 1.0.0 (~ 1MB)

 

Olderposts

Copyright © 2014 PHPFlüsterer

Theme by Anders NorenUp ↑