Rückblick: Fireside Chat Digital Employer Branding am 2. September

Podiumsdiskussion Employer Branding

Leider musste unser Fireside Chat (FSC/#MINISTRYFSC) „Smart Mobility“ am 24.09.  kurzfristig ausfallen. Um das Warten auf den nächsten Termin (am 29. Oktober ist es so weit und es geht um das Thema „Disruption trifft Display Advertising“) zu überbrücken, gibt es an dieser Stelle einen Rückblick auf den letzten Fireside Chat „Digital Employer Branding“. Viel Spaß beim Lesen! Rückblick: Fireside Chat Digital Employer Branding am 2. September weiterlesen

Solutions.Hamburg 2015: Hut ab, es war groß(artig)!

Voller Highlights: die #shh15
Voller Highlights: die #shh15

Kinder, wie die Zeit rennt! Schon sind wieder drei Wochen vergangen, seit die Solutions.Hamburg 2015 vorbei ist. Wir freuen uns, dass wir mit unserem Track “Going mobile” als Qualitätspate ein Teil dieser Veranstaltung auf dem Kampnagel-Gelände sein durften. Hier mein persönlicher Rückblick als Moderator des Tracks:

Solutions.Hamburg 2015: Hut ab, es war groß(artig)! weiterlesen

Schleichwerbung? „Nein, danke!“

Valentin hatte Spaß und ich muss aufräumen … Wichtiger Bildhinweis: Dies ist keine Schleichwerbung ;-)Aus aktuellem Anlass beschäftige ich mich heute mit dem Thema Schleichwerbung in Social Media. Wichtiger Bildhinweis: Dies ist keine Schleichwerbung – einfach weiterlesen und ihr werdet verstehen! 😉 Schleichwerbung? „Nein, danke!“ weiterlesen

“Lass ma’ eben schnell ‘ne App machen”

Betrag eingeben, Rubrik auswählen, fertig. So schnell lassen sich alle Ausgaben mit Cashcheck erfassen.

Oder: Wie wir zu unserer ersten eigenen App kamen. Und was wir daraus gelernt haben. Ein persönlicher Rückblick. “Lass ma’ eben schnell ‘ne App machen” weiterlesen

Agency Band Aid 2014: music goes social – again!

Gutes Ergebnis eines guten Abends mit guter Musik.
Gutes Ergebnis eines guten Abends mit guter Musik.

Als wir im Jahre 2013, aus einer Schnaps-Idee heraus, ein eigenes Band-Aid auf die Beine stellten, war niemandem bewusst, dass sich ein Kult-Format bilden würde. Agency Band Aid 2014: music goes social – again! weiterlesen

Vertrauen ins Team – Wir sind nominiert für den New Work Award!

Wir freuen uns: unsere Anstrengungen, ein Unternehmen zu bauen, in dem Menschen jeden Tag gerne arbeiten (und feiern), wurden heute ein weiteres Mal gewürdigt: Vertrauen ins Team – Wir sind nominiert für den New Work Award! weiterlesen


This article is part of a series which is continued here.

This article presents a proof of concept to greatly reduce/compress the filesize of alpha transparent PNG images via PHP without loosing the alpha information and reassembling the separated channels with the help of jQuery and HTML5 canvas.

Current evolution of HTML5, CSS3, widespread availability of broadband internet connections and (finally!) Internet Explorer 6 becoming more and more obsolete we see ourselves, at times, faced by new kinds of challenges.

As we frequently develop promotional microsites/raffles for our clients (and these kind of sites do actually have very special requirements in terms of product/brand identity and representation) we, as developers, are often forced to use huge amounts of PNG-images with full alpha-channel. Their sheer amount plus the fact that PNG is an almost uncrompessed format can become such an aforementioned challenge as you will see in the following article.

The Problem: huge filesize of PNG-images

In one of my latest projects I ended up having a page with 4.5MB of data in total which was mainly caused by one image-slider making extensive use of PNG files with alpha-channel information. The images of this slider, in fact, summed up to a total of 3.8MB alone which would lead to a loading time of approx. 20-30 seconds for a 2MBit connection! Otherwise the code was quite clean and making extensive use of CSS3 and sprites to reduce loading time and the number of requests. To put it in a nutshell: an unacceptable condition in terms of a developer’s honor.

I discussed my concerns with Christoph when he finally joked about trying to use canvas to somehow circumvent the problem of huge filesizes when being forced to use PNGs. We both had an extended laugh, at first.

The idea: separate color- and alpha-channel and reassemble them in a canvas element

I then thought about it for a moment and had an idea: Canvas could indeed be part of a possible solution if I would somehow manage to separate the image’s color-information from its alpha-channel and then save them as separate files. Due to the fact that the most problematic PNGs are those that would normally best be saved as JPG (if they did not need an alpha-channel) I was almost sure that it should be possible to save the separated color-information as JPG thus greatly reducing total filesize.

At first I did some research (always remember: Google is your friend) and found some interesting articles. None of them covered all aspects of what I wanted to achieve but they were a great source of inspiration and knowledge:

The abstract: four challenges on the way to PNG size reduction

So I ended up facing four questions needed for a simple proof of concept:

  1. Would it be easily possible to separate color- and alpha-information via PHP?
  2. Is it possible to re-combine these two channels via Javascript and the canvas-element?
  3. Is there any chance to write the combined channels back into an image?
  4. Will there be a way to circumvent the doubled amount of requests due to the separation?

1. Separating color- and alpha-information via PHP

I actually started with some far more simple code for the proof of concept but this is what I came up with in the end. In this example, I am leaving out some parts, including mainly the saving of the final images to keep it short and easy to understand. (See the end of this articles for the helper functions used in the PHP-part)

			$sourceFile = 'Path to your source-image';

			// temporary storage for alpha-colors
			$colorCache = array(127 => rgb2color(0, 0, 0, 0));

			// read width and height from source-image
			$size   = @getimagesize($sourceFile);
			$width  = $size[0];
			$height = $size[1];

			// create image from source-image
			$imageSource = @imagecreatefrompng($sourceFile);

			// create image for color-information
			$imageJpg    = @imagecreatetruecolor($width, $height);

			// create image for alpha-information
			$imagePng    = @imagecreatetruecolor($width, $height);

			// enable alpha-handling for source- and alpha image
			@imagealphablending($imageSource, false);
			@imagesavealpha($imageSource, true);
			@imagealphablending($imagePng, false);
			@imagesavealpha($imagePng, true);

			// fill color- and alpha-image
			@imagefill($imageJpg, 0, 0, rgb2color(127, 127, 127));
			@imagefill($imagePng, 0, 0, $colorCache[127]);

			// iterate over source-image
			for($x = 0; $x < $width; $x++) {
				for($y = 0; $y < $height; $y++) {
					// convert GDLib-color to RGBa-values
					$color = color2rgb(imagecolorat($imageSource, $x, $y));

					// check if color alpha is less than 127 (which means transparent)
					if($color['a'] < 127) {
						// write color-information to color-image
						imagesetpixel($imageJpg, $x, $y, rgb2color($color['r'], $color['g'], $color['b']));

						// check if alpha-color is in temporary storage
						if(!isset($colorCache[$color['a']])) {
							// put alpha-color in temporary storage
							$colorCache[$color['a']] = rgb2color(0, 0, 0, 127 - $color['a']);

						// write alpha-information to alpha-image
						imagesetpixel($imagePng, $x, $y, $colorCache[$color['a']]);

			// convert GDLib-resources to color- (as JPEG) and alpha-image (as PNG)
			$imageJpg = getImage($imageJpg, 'jpeg', true, 80);
			$imagePng = getImage($imagePng, 'png', false, 9, PNG_ALL_FILTERS);

Just to give you a quick & dirty example the following source-image (leftmost: approx. 129 KB) is split into separate color- and alpha-images (approx. 32 KB in total using 80% compression for the JPEG)zwei

Note: The background pattern assigned is not part of the images but only used to visualize transparency. All images are resized via CSS to fit the layout.

2. Re-combine color- and alpha-image via Javascript and canvas

This is the main part of the javascript I ended up with. It combines the two separate channels from their img-elements via a canvas element. Remember to process this on window load. Otherwise the result will be an empty canvas.

			<script type="text/javascript">
			var context,
				width   = 256, // width of your source-image
				height  = 256, // height of your source-image
				jpg     = '', // img-element holding color-image
				png     = '', // img-element holding alpha-image
				canvas  = document.createElement('canvas');

			canvas.style.display = 'none';
			canvas.width         = width;
			canvas.height        = height;

			context = canvas.getContext('2d');
			context.clearRect(0, 0, width, height);
			context.drawImage(jpg, 0, 0, width, height);

			context.globalCompositeOperation = 'xor';
			context.drawImage(png, 0, 0, width, height);

3. Write combined channels back into image

This is by far the simplest part as the HTML5 canvas element provides a native method to directly fetch a valid dataURL. As an example I use jQuery to create an image, assign the dataURL and append it to the document body.

			<script type="text/javascript">
			var dataURL = canvas.toDataURL('image/png');

			jQuery('<img />', { src: dataURL, alt: '' }).appendTo('body');

Look at the final outcome on the right and carefully compare it to the source PNG on the left (remember, this is 32 KB instead of 129 KB, so only 25% of the original filesize):fünf

Note: The background pattern assigned is not part of the images but only used to visualize transparency.

Savings in filesize will vary roughly between 60% to 80% reduction of the original filesize (using 80% compression for the JPEG).


4. Circumvent doubled amount of HTTP-requests due to image separation

Well, up to now everything was quite simple due to the scripts being more or less a proof of concept. As stated before I left out some parts which, to be honest, mainly dealt with exactly this problem. The solution is in fact not that complicated but would simply be too much for this part of the article. Just to give you a hint: .htaccess and modRewrite come to the rescue in the second part of this article which can now be found here.

PHP helper functions
			function rgb2color($r, $g, $b, $a = 0) {
				return ($r << 16) + ($g << 8) + $b + ($a << 24); 			} 			function color2rgb($color) { 				$return = null; 				if(preg_match('/^\d+$/', $color)) { 					$return = array( 						'r' => ($color >> 16) & 0xFF,
						'g' => ($color >> 8) & 0xFF,
						'b' => $color & 0xFF,
						'a' => ($color & 0x7F000000) >> 24,

				return $return;

			function getImage($resource, $type = 'png', $interlace = false, $quality = NULL, $filter = 248) {
				if($interlace === true) {
					@imageinterlace($resource, 1);


				switch($type) {
					case 'png':
						$quality = ($quality === NULL) ? 9 : max(0, min(9, (int) $quality));

						@imagepng($resource, NULL, $quality, $filter);
					case 'jpeg':
						$quality = ($quality === NULL) ? 100 : max(0, min(100, (int) $quality));

						@imagejpeg($resource, NULL, $quality);

				return trim(ob_get_clean());
This article is part of a series which is continued here.

PHP event dispatcher

PHP event dispatcher

Dispatching and listening to events is a common concept with many advantages in a lot of applications but is hardly used nor natively supported in PHP. In this article I present you my own, very simple yet powerful implementation mimicking JavaScripts event bubbling on DOM-elements.

I stumbled across a nice article on phphatesme.com lately which made me think about event based programming in PHP. In jQuery or almost any of the Google Javascript-APIs, at least, events and event listeners are a concept widely spread, used and accepted.

I did some more research regarding event based concepts in PHP and found that symfony components has (as usual) its own solution which is quite similar to what phphatesme.com developed. A closer look showed that although working nicely both solutions seemed a bit limited in their possibilities because both allow listeners to be attached to an exactly named event only. So what I had in mind was more or less an event tree, behaving very similar to browser event bubbling.

Components of an event dispatcher in PHP

„Event“ class

As I tend to use object oriented programming whereever possible I started with a very small class as a skeleton for all types of events. An event only consists of a „name“ property and an array of „parameters“, both private. The magic method __get is used to the otherwise private properties publicly readable only.

			class Event {
				private $name;
				private $parameters = array();

				public function __construct($name, array $parameters = array()) {
					$this->name       = $name;
					$this->parameters = $parameters;

				public function __get($property) {
					if(isset($this->$property)) {
						return $this->$property;

„Dispatcher“ class

Afterwards I started building the skeleton for the so called dispatcher which is used to bind listeners to events and notify them when an event is triggered.

			class Dispatcher {
				private $callbacks = array();
				private $events    = null;

				public function __construct() {  }
				public function addListener($callback, $event) {  }
				public function notify(Event &$event) {  }

If you read carefully you might have noticed the word „tree“ and this is exactly what will be used throughout the class to store and manage all events. So the class constructor will initialize the private property „events“ to be a SimpleXMLElement:

			class Dispatcher {

				public function __construct() {
					$this->events = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" standalone="yes"?><events></events>');


After that I continued with the „addListener“ method. Notice the parameter „$event“ which is a string in this case and uses „/“ as a separator for the tree/path structure.

			class Dispatcher {

				public function addListener($callback, $event) {
					$return = false;

					if(is_callable($callback) === true) {
						if(is_array($callback)) {
							$id = md5(get_class($callback[0]) . json_encode($callback));
						} else {
							$id = md5(json_encode($callback));

						$matches =& $this->_getEvent($event);

						foreach($matches as $match) {
							$status = $match->xpath('./listener[@id=\'' . $id . '\']');
							$status = ($status === false || count($status) === 0) ? false : true;

							if($status === false) {
								$listener       = $match->addChild('listener');
								$listener['id'] = $id;


						if(!isset($this->callbacks[$id])) {
							$this->callbacks[$id] =& $callback;

						$return = true;

					return $return;

				// fetches all existing events matching the passed event name
				private function &_getEvent($node) {
					$matches = $this->events->xpath('/events/' . $node . '[not(@id)]');

					if($matches === false || count($matches) === 0) {
						$matches = $this->_build($node);

					return $matches;

				// adds an event to the class events property and returns it as a pointer
				private function _build($node) {
					$nodes   =  explode('/', $node);
					$pointer =& $this->events;

					foreach($nodes as $node) {
						if(!isset($pointer->$node)) {

						$pointer =& $pointer->$node;

					return array($pointer);


Being able to add listeners from here on only one thing is missing: a method to trigger an event or, to be precise, notify all registered listeners that an event was triggered.

			class Dispatcher {

				public function notify(Event &$event) {
					$return = false;

					if($this->events !== null) {
						$matches    =& $this->_getEvent($event->name);
						$expression =  '/events/' . $event->name . '[not(@id)]/listener[@id]|/events/' . $event->name . '[not(@id)]/ancestor::*/listener[@id]';
						$matches    =  $this->events->xpath($expression);

						if(is_array($matches)) {
							foreach($matches as $match) {
								call_user_func_array($this->callbacks[(string) $match['id']], $event->parameters);

						$return = true;

					return $return;


Practical usage of the dispatcher

Usage of the event dispatcher is really simple, just to give you an example:

			$dispatcher = new Dispatcher();
			$dispatcher->addListener('exampleCallback', 'example')

			// trigger the event directly...
				$event = new Event('example', array('exampleParam1', 'exampleParam2'));

			// or make use of "bubbling"
				$event = new Event('example/subevent', array('exampleParam1', 'exampleParam2'));

			function exampleCallback($exampleParam1, $exampleParam2) {
				echo $exampleParam1 . ', ' . $exampleParam2;


In größeren Webprojekten verbringt man viel Zeit damit, sich durch tief verschachtelte Ordner-Hierarchien zu klicken. Zeit, alte Vorgehensweisen über Bord zu werfen und einen Blick auf einen projektbasierten Dateimanager zu werfen.

Projektordner-Suche leicht gemacht

Wäre es nicht schön, jede Datei in seinem Projekt nur mit wenigen Tastendrücken zu erreichen? Ohne sich durch gefühlte 2000 Ordner hoch- unter herunterklicken zu müssen?

P ist im Grunde eine rekursive Suche durch einen Projektordner, welche seine Ergebnisse verzögerungsfrei anzeigt. Aus diesen Suchergebnissen wählt man dann mit den Cursortasten die Datei aus, die man öffnen möchte und drückt dann Enter. Schon öffnet sich die gewünschte Datei in dem für die Dateiendung hinterlegtem Programm.

Seine Stärke entfaltet das Tool aber erst durch die variablen Suchbegriffe, die man verwenden kann und dem Ausgangsverzeichnis der Suche, welches genauso frei gewählt werden kann.

Kein guter Dateimanager unter Linux

Entstanden ist P eigentlich aus dem Umstand, dass ich (Christoph) bei der Arbeit unter Windows den legendären Total Commander verwende, zuhause aber unter Linux keinen auch nur halbwegs konkurrenzfähigen Datei-Manager gefunden habe. Ich brauchte also eine Lösung zum schnellen Öffnen von Dateien unter Linux, bei der ich möglichst wenig tippen müsste und am besten komplett auf das unhandliche Touchpad verzichten könnte. Da ich im PHP-Umfeld zuhause bin, entschied ich mich zum Basteln eines PHP-Shell-Scripts, welches mein Problem pulverisieren sollte.

Als ich es dann Nils zeigte, der es auch unter Mac OS X ohne Probleme zum Laufen bekam und den Finder absolut unterirdisch findet, war er sofort bei der Weiterentwicklung dabei. Das Ergebnis der Zusammenarbeit sehr ihr hier.

Projektordnersuche ausprobieren

Wer jetzt Lust darauf bekommen hat, P einfach mal auszutesten, kann es folgendermaßen ganz einfach ausprobieren:

  1. Aktuelle Version von P w456 herunterladen
  2. Shell-Script ausführbar machen:
  3. Alias in der .bashrc (Linux) oder in der .bash_profile (Mac OS X) anlegen:
  4. Jetzt könnt ihr P einfach starten per:

Konfiguration anpassen

Nach der unglaublich zeitaufwendigen Installation muss P noch konfiguriert werden. Dafür müsst ihr einfach die Datei .proj_template.php kopieren und in .proj.php umbenennen:

Öffnet jetzt die .proj.php und passt diese nach euren Wünschen an. Alles sollte eigentlich selbsterklärend sein. Sollten wir in den Kommentaren sehen, dass dem nicht so ist, werden wir den Bereich hier natürlich ergänzen.

Und wie geht das jetzt?

Hier sind die speziellen Tastenkombinationen, die in P zur Verfügung stehen:

11 In der Ergebnisliste navigieren

22 In das ausgewählte Verzeichnis und damit in die Ordner-Ansicht wechseln.

33 Einen Ordner weiter nach oben wechseln.

44 In der Ergebnisliste nach oben springen

55 In der Ergebnisliste nach unten springen

66 Suchzeile komplett löschen

77 Ausgewählte Datei oder Ordner öffnen.

88 Den Root-Ordner neu indizieren.

99 P beenden.

Nutzung des Dateimanagers „P“ unter Windows

Die Nutzung unter Windows mit der Windows-Kommandozeile (cmd.exe) ist leider erstmal nicht möglich, weil das Script ein wenig an den Terminals herumkonfiguriert und teilweise auch auf Unix-Kommandos basiert. Dennoch gibt es in einer bestimmten Konstellation eine Möglichkeit.

Bei der Arbeit sieht es bei mir (Christoph) so aus, dass ich unter Windows arbeite, mein Webserver-Entwicklungsrechner aber eine Linux-Kiste ist, dessen DocumentRoot per Samba freigegeben ist. Ich verbinde mich jetzt per SSH (via Putty) und starte P, was natürlich dazu führt, dass die Dateien und die zugehörigen Programme auf dem Server statt auf meiner Windows-Maschine gestartet werden. Was mir erstmal relativ wenig hilft. Jetzt gibt es zwei Möglichkeiten.

Zum einen könnte ich X11-Forwarding für die SSH-Sitzung aktivieren und unter Windows einen X-Server aufsetzen (mit Xming sehr einfach). Allerdings könnte ich so ja nur auf dem Server installierte Programme nutzen (inkl. einer platzfressenden Installation von GTK oder Qt auf einer reinen Server-Installation). Ich möchte aber gern Notepad++ unter Windows verwenden.

Damit wären wir bei der zweiten Möglichkeit. Der Linux-Rechner müsste ein Signal an meinen Windows-Rechner schicken, um dort die richtige Datei (im Samba-Pfad) mit dem richtigen Programm aufzurufen. Ich habe es gelöst, indem ich mit PHP einen Socket-Server unter Windows aufgesetzt habe, welcher auf ein HTTP-Request wartet, um dann ein Programm mit der zugehörigen Datei zu starten.

Da es seit PHP5 einen eingebauten Webserver gibt, braucht man nicht mehr ein selbstgebasteltes Socket-Script, sondern kann ganz gemütlich PHP-eigene Funktionen nutzen, womit das Script um einiges kürzer wird:


// set the replacements
$replacements = array(
‚\\var\\www\\‘ =&gt; ‚V:\\‘, // map real path to samba path
‚[default]‘ =&gt; ’start‘, // the start command opens a file with the default application in windows
‚[folder]‘ =&gt; ‚&quot;C:\Program Files\totalcmd\TOTALCMD.EXE&quot; /O /L=‘, // open folders with total commander

if (isset($_SERVER[‚HTTP_X_P_COMMAND‘])) {
$command = $_SERVER[‚HTTP_X_P_COMMAND‘];
$command = str_replace(‚/‘, ‚\\‘, $command);
$command = str_replace( array_keys($replacements), array_values($replacements), $command);


Gestartet wird das Script jetzt z.B. mit Klick auf folgende Datei:

C:\Users\christoph\php\php.exe -S -t c:\p

Achtung! Dieser Socket-Server ist ein Sicherheitsrisiko, weil euer Rechner von außen gesteuert werden kann (wie bei einem Botnetz). Achtet also darauf, irgendeine Art von Authentifizierung einzubauen. Ein völlig abgedrehter Name des steuernden HTTP-Headers würde da schon reichen.

Jetzt muss natürlich noch die Konfiguration unter Linux angepasst werden. Ich hab es so gemacht.


‚file‘ => array(
‚open‘ => array(
‚default‘ => ‚wget –quiet –spider –tries=1 –header=“X-P-Command: [default] %s“ > /dev/null‘,

‚folder‘ => array(
‚open‘ => array(
‚default‘ => ‚wget –quiet –spider –tries=1 –header=“X-P-Command: [folder]%s“ > /dev/null‘,

Sollten Probleme beim Aufsetzen unter Windows aufkommen, helfe ich natürlich gern weiter.

Little helper: Geodistance

Today I present you a helper class int PHP offering methods for the most famous variants in calculating geographical distances by latitude and longitude (Circle, Cosines, Haversine and Vincenty included) as well as cartesian coordinates (a great alternative for use in SQL-queries).

During development of some PHP and JS applications using geolocations and distances I finally found the time to refactor the knowledge I gained into a tiny PHP-helper-class offering fast (but not that accurate) to slow (but accurate to the max) static methods for your daily geodistance calculations.

	class Geographical {
		const METHOD_CIRCLE        = 1;
		const METHOD_COSINES       = 2;
		const METHOD_HAVERSINE     = 3;
		const METHOD_VINCENTY      = 4;
		const RADIUS_METER         = 6371000.785;
		const SEMIAX_MAJOR         = 6378137;
		const SEMIAX_MINOR         = 6356752.3141;

			public static function getCartesian($longitude, $latitude) {
			$lambda    = $longitude * pi() / 180;
			$phi       = $latitude * pi() / 180;
			$return    = new stdClass();
			$return->x = self::RADIUS_METER * cos($phi) * cos($lambda);
			$return->y = self::RADIUS_METER * cos($phi) * sin($lambda);
			$return->z = self::RADIUS_METER * sin($phi);


				return $return;

			public static function getDistanceByCartesian($x1, $y1, $z1, $x2, $y2, $z2) {
				return 2 * self::RADIUS_METER *
							pow($x1 - $x2, 2)
							+ pow($y1 - $y2, 2)
							+ pow($z1 - $z2, 2)
						) / (2 * self::RADIUS_METER)

			public static function getDistanceByLatLng($lat1, $lng1, $lat2, $lng2, $method = self::METHOD_COSINES) {
				$return = false;
					switch($method) {
						case self::METHOD_CIRCLE:
							$factor  = deg2rad(1);
							$lat1   *= $factor;
							$lng1   *= $factor;
							$lat2   *= $factor;
							$lng2   *= $factor;

							$return = rad2deg(acos(sin($lat1) * sin($lat2) + cos($lat1) * cos($lat2))) * 60 * 1852;


						case self::METHOD_COSINES:
							$factor  = deg2rad(1);
							$lat1   *= $factor;
							$lng1   *= $factor;
							$lat2   *= $factor;
							$lng2   *= $factor;

							$return = self::RADIUS_METER * acos(sin($lat1) * sin($lat2) + cos($lat1) * cos($lat2) * cos($lng1 - $lng2));


						case self::METHOD_HAVERSINE:
							$factor  = deg2rad(1);
							$lat1   *= $factor;
							$lng1   *= $factor;
							$lat2   *= $factor;
							$lng2   *= $factor;
							$dlat    = $lat2 - $lat1;
							$dlng    = $lng2 - $lng1;

							$a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2);

							$return = self::RADIUS_METER * (2 * atan2(sqrt($a), sqrt(1 - $a)));


						case self::METHOD_VINCENTY:
							$factor  = deg2rad(1);
							$lat1   *= $factor;
							$lng1   *= $factor;
							$lat2   *= $factor;
							$lng2   *= $factor;
							$f       = (self::SEMIAX_MAJOR - self::SEMIAX_MINOR) / self::SEMIAX_MAJOR;
							$L       = $lng2 - $lng1;
							$U1      = atan((1 - $f) * tan($lat1));
							$U2      = atan((1 - $f) * tan($lat2));
							$sinU1   = sin($U1);
							$sinU2   = sin($U2);
							$cosU1   = cos($U1);
							$cosU2   = cos($U2);
							$lambda  = $L;
							$lambdaP = 2 * pi();
							$i       = 20;

							while(abs($lambda - $lambdaP) > 1e-12 and --$i > 0) {
								$sinLambda = sin($lambda);
								$cosLambda = cos($lambda);
								$sinSigma  = sqrt(($cosU2 * $sinLambda) * ($cosU2 * $sinLambda) + ($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosLambda) * ($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosLambda));

								if($sinSigma == 0) {
									return 0;

								$cosSigma   = $sinU1 * $sinU2 + $cosU1 * $cosU2 * $cosLambda;
								$sigma      = atan2($sinSigma, $cosSigma);
								$sinAlpha   = $cosU1 * $cosU2 * $sinLambda / $sinSigma;
								$cosSqAlpha = 1 - $sinAlpha * $sinAlpha;
								$cos2SigmaM = $cosSigma - 2 * $sinU1 * $sinU2 / $cosSqAlpha;

								if(is_nan($cos2SigmaM)) {
									$cos2SigmaM = 0;

								$c       = $f / 16 * $cosSqAlpha * (4 + $f * (4 - 3 * $cosSqAlpha));
								$lambdaP = $lambda;
								$lambda  = $L + (1 - $c) * $f * $sinAlpha * ($sigma + $c * $sinSigma * ($cos2SigmaM + $c * $cosSigma * (-1 + 2 * $cos2SigmaM * $cos2SigmaM)));

							if($i == 0) {
								return false;

							$uSq        = $cosSqAlpha * (self::SEMIAX_MAJOR * self::SEMIAX_MAJOR - self::SEMIAX_MINOR * self::SEMIAX_MINOR) / (self::SEMIAX_MINOR * self::SEMIAX_MINOR);
							$A          = 1 + $uSq / 16384 * (4096 + $uSq * (-768 + $uSq * (320 - 175 * $uSq)));
							$B          = $uSq / 1024 * (256 + $uSq * (-128 + $uSq * (74 - 47 * $uSq)));
							$deltaSigma = $B * $sinSigma * ($cos2SigmaM + $B / 4 * ($cosSigma * (-1 + 2 * $cos2SigmaM * $cos2SigmaM) - $B / 6 * $cos2SigmaM * (-3 + 4 * $sinSigma * $sinSigma) * (-3 + 4 * $cos2SigmaM * $cos2SigmaM)));

							$return = self::SEMIAX_MINOR * $A * ($sigma - $deltaSigma);


					return $return;

I took the code from various sources and refactored it to my needs. For all the calculations taking latitude and longitude directly being quite complex I also added a more simple method using cartesian coordinates and also integrated a method to convert latitude and longitude to cartesian coordinates. The Vincenty-method is by far the most accurate but takes quite some time. I prefer to use the Haversine-formula for it’s good compromise between accuracy and speed.