VAT Validation now for PHP 7.1+

When I started my European Commission (EC) VAT Information Exchange System (VIES) project back in 2011, PHP 5.3 was the current version that has given us so much. Earlier that year version 5.2 was announced End-of-Life and everyone was excited about the new features in PHP coming with the 5.3.x releases.

But fast-forwarding to today, PHP 7.1 is the latest stable release and PHP 5.6 only gets security fixes until the end of this year. In the mean time several open-source projects like PHPUnitXDebugZend FrameworkLaravelJoomlaTYPO3Magento and Symfony announced they stop development for PHP 5 versions and now only move forward with PHP 7.1 and higher.

After seeing Sebastian Bergmann’s talk PHP 7: Reality Check I was empowered by his reasoning that it’s not worth putting support in outdated PHP versions and focus on the current and future versions that will make a difference in functionality, performance and security.

For this reason I would like to announce that the European Commission (EC) VAT Information Exchange System (VIES) project will no longer support PHP 5 and uses PHP 7.1 features to ensure better security and application control.

We’re going to follow the release and support cycle of PHP itself and will only offer security fixes on our 1.x branch. If you can’t wait to run our VIES service in your PHP 7.1 web application, you can go ahead and update directly through Composer.

composer update dragonbe/vies

If you’re starting a new project and you would like to add VAT validation you can install it easily with Composer.

composer require dragonbe/vies

As mentioned, I will only provide security fixes on the 1.x branch until the end of this year! If you’re already using this VIES project in your own projects, I urge you to upgrade to PHP 7.1 to enjoy future features and updates.


PHP 7 and Apache on macOS Sierra

PHP 7.1.2 running on macOS Sierra
I posted several talks about compiling PHP from source, but everyone was trying to convince me that a package manager like Homebrew was a more convenient way to install.
The purpose of Homebrew is simple: a package manager for macOS that will allow you to set up and install common packages easily and allows you to update frequently using simple commands.
I used a clean installation of macOS Sierra to ensure all steps could be recorded and tested. In most cases you already have done work on your Mac, so chances are you can skip a few steps in this tutorial.


I’ve made this according to the installation instructions given on GetGrav.

The installation procedures

These installation procedures will set up your macOS Sierra with PHP 7.1 and Apache 2.4.

Install Xcode command line tools (if not done yet)

xcode-select --install

Install Homebrew

/usr/bin/ruby -e "$(curl -fsSL"
Set up for installation of PHP and Apache
brew tap homebrew/dupes
brew tap homebrew/versions
brew tap homebrew/homebrew-php
brew tap homebrew/apache

Unload the provisioned Apache from macOS Sierra

sudo apachectl stop
sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist 2>/dev/null

Install Homebrew Apache

brew install httpd24 --with-privileged-ports --with-http2

Set up Apache for autostart at macOS Sierra (re)boot

sudo cp -v /usr/local/Cellar/httpd24/2.4.25/homebrew.mxcl.httpd24.plist /Library/LaunchDaemons
sudo chown -v root:wheel /Library/LaunchDaemons/homebrew.mxcl.httpd24.plist
sudo chmod -v 644 /Library/LaunchDaemons/homebrew.mxcl.httpd24.plist
sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.httpd24.plist

Check to see Apache is running

ps -aef | grep httpd
You should see something similar as output
    0 23417     1   0  2:48PM ??         0:00.06 /usr/local/opt/httpd24/bin/httpd -D FOREGROUND
    1 23420 23417   0  2:48PM ??         0:00.00 /usr/local/opt/httpd24/bin/httpd -D FOREGROUND
    1 23421 23417   0  2:48PM ??         0:00.00 /usr/local/opt/httpd24/bin/httpd -D FOREGROUND
    1 23422 23417   0  2:48PM ??         0:00.00 /usr/local/opt/httpd24/bin/httpd -D FOREGROUND
    1 23423 23417   0  2:48PM ??         0:00.00 /usr/local/opt/httpd24/bin/httpd -D FOREGROUND
    1 23424 23417   0  2:48PM ??         0:00.00 /usr/local/opt/httpd24/bin/httpd -D FOREGROUND
  501 23428   403   0  2:48PM ttys000    0:00.00 grep httpd

Uninstall previous versions of PHP

We assume you had PHP 7.0 installed
brew unlink php70

Install latest PHP version (PHP 7.1.2 at the time of writing)

Time to install latest PHP with the apache web server
brew install php71 --with-httpd24
Don’t forget to set date.timezone in /usr/local/etc/php/7.1/php.ini!!!

Configure Apache for PHP usage

Also make sure to set the following line in /usr/local/etc/apache2/2.4/httpd.conf (You might need to disable others):
LoadModule php7_module    /usr/local/opt/php71/libexec/apache2/
Also make sure you have set the following lines correctly:
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.

    DirectoryIndex index.html index.php

    SetHandler application/x-httpd-php

Time to restart apache

sudo /usr/local/bin/apachectl -k restart

Test your setup

Create a phpinfo.php in /usr/local/var/www/htdocs with the following contents:
<?php phpinfo();
You should see the famous PHP information page!

Next steps

Now you can set up your virtual hosts like you normally would do.


Sessions in PHP 7.1 and Redis

In case you have missed it, PHP 7.1.0 has been released recently. Now you can’t wait to upgrade your servers to the latest and greatest PHP version ever. But hold that thought a second…
With PHP 7 lots of things have changed underneath the hood. But these changed features can also put unexpected challenges on your path.

Our challenge

One of these challenges that we faced was getting PHP 7.1 to play nice storing sessions in our Redis storage. In order to store sessions in Redis, we needed to install the Redis PHP extension that not only provides PHP functions for Redis, but also installs the PHP session handler for Redis.
Because we upgraded our servers to PHP 7.1, we were looking to use the latest provided version for this Redis extension: redis-3.1.0. Once installed, we bumped against a nasty problem.
Warning: session_start(): Failed to read session data: redis (path: tcp://
Searching the internet for this error, we didn’t got many hits that could point us into a direction of a solution. 
We came up with this very basic PHP code snippet that could reproduce the error in a clean, stand-alone way. Since we used a framework, we wanted to make sure the problem was in PHP and not related to the choice of our PHP framework.

ini_set('session.save_handler', 'redis');
    'session.save_path', 'tcp://devcache1:6379'

echo nl2br(
    '<pre>' . session_save_path() . '</pre>' . PHP_EOL

echo nl2br(
    'Running PHP version: ' . phpversion() . PHP_EOL

if (!array_key_exists('visit', $_SESSION)) {
    $_SESSION['visit'] = 0;

echo nl2br(
    'You have been here ' . $_SESSION['visit'] . ' times.'
To give us some room to try things out, we decided to use Docker to create containers for us to try things out while searching for a solution. Find our basic setup from my GitHub repository.
cd /path/to/workspace
git clone
cd docker-php-redis-example/
We’ve added a docker-compose.yml to get started quickly using Docker Compose.
docker-compose up
This command will launch the different containers for PHP 5.6, 7.0 and 7.1 including a single Redis instance.
In the following YouTube video you can see what we experienced on our side.
PHP7, Redis extension and Docker
The redis PHP session handler worked perfect for PHP 5.6, failed with Segmentation faults on PHP 7.0 and wasn’t able to initialise a new session on PHP 7.1. Remarkable was that once we started a session on PHP 5.6, the session handler was having no issues updating this existing session on PHP 7.1.

Our solution

So we figured out there must be something broken with the update in the redis extension. Looking at the changelog we couldn’t directly spot a problem on how sessions are instantiated. Searching the internet we came to a lot of mentioning of session_regenerate_id(), but this was not affected in our situation.
In one of the comments someone mentioned that a similar failure started appearing after upgrading from v3.0.0 to v3.1.0. That sparked our interest. We downgraded our redis extension to version 3.0.0 and tried again.
Hooray!!! Our session creation was now working on PHP 7.1, so mission accomplished. Now we needed to agree on taking the unfixed issues between redis-3.0.0 and redis-3.1.0 as compromise. Since the earlier mentioned changelog didn’t contain issues that directly could have an effect on our use cases for Redis it was easy to agree.
Now we’re enjoying running our web applications on PHP 7.1.0 while our sessions are handled through Redis. And we hope by sharing this experience, you too can enjoy running your PHP application on the latest version: PHP 7.1.

Update 2016-12-22!!!

Today I received a tweet that there's an update available in the form of redis-3.1.1RC1. Go check out my github branch to see how to implement it with Docker.

This fix also solves the issue I displayed for PHP 7.0. You should be good to go and implement it on your PHP 7 installations.


PHP 7 on macOS Sierra

PHP 7 on macOS Sierra

Apple has released the latest version of their OS X operating system to the broad public and many have already upgraded their mac devices. But as it goes with each release, Apple likes to do things a bit different making it quite challenging for PHP developers to stay current with the latest PHP version (or other versions).

This version of mac OS (11.12) comes pre-installed with PHP 5.6.24.

PHP 5.6.24 (cli) (built: Aug  8 2016 16:58:37)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies

Good for Apple, but this version reaches end-of-life support by the end of this year, so it would be great if you could upgrade to PHP 7.0 or even play with the latest PHP 7.1 release candidates.

Of course you can always turn to Homebrew, XAMMP or whatever package manager you use for easy installations, but taking the compiling path is just as complicated. The failure is equal in most situations.

Configuring PHP on macOS Sierra triggers the following error:

apxs:Error: /Applications/ not found!.
configure: error: Aborting

In this version of Apple's OS the Apache Portable Runtime was not included. You need to download it and compile it yourself.


Check the checksums!

tar -xjf apr-1.5.2.tar.bz2
tar -xjf apr-util-1.5.4.tar.bz2

cd apr-1.5.2/
make install

cd ../apr-util-1.5.4/
./configure --with-apr=/usr/local/apr
make install

sudo mkdir -p /Applications/
sudo ln -s /usr/local/apr/bin/apu-1-config /Applications/
sudo ln -s /usr/local/apr/bin/apr-1-config /Applications/

Now you can hapily compile and run the latest PHP version on the latest OS from Apple. See my previous article Compile PHP 7 on Mac OS X 10.11 "El Capitain" for instructions.

Happy PHP-ing!


Compile PHP 7 on Mac OS X 10.11 "El Capitain"

Apple has made a numerous changes to the way OS X (10.11) "El Capitain" uses open source elements like PHP and OpenSSL. Compiling PHP from source requires a bit more modifications.
This article is a follow-up on my previous post Installing PHP 7 with XDebug, Apache and MySQL on OS X Yosemite


Get the latest OpenSSL from and unpack it so you can work with the sources.
Then just execute:
./Configure shared darwin64-x86_64-cc
make depend
sudo make install


Download the latest PHP 7 source code from and unpack it in a temporarily directory, I like to use /tmp.
My configure command arguments:
./configure \
--prefix=/opt/php7 \
--enable-cli \
--enable-mbstring \
--enable-gd-native-ttf \
--enable-gd-jis-conv \
--enable-sockets \
--enable-exif \
--enable-ftp \
--enable-intl \
--enable-soap \
--enable-zip \
--with-apxs2 \
--with-iconv=/usr \
--with-config-file-path=/etc/php7 \
--with-config-file-scan-dir=/etc/php7/ext \
--with-libxml-dir=/Applications/ \
--with-openssl=/usr/local/ssl \
--with-curl \
--with-gd \
--with-libedit \
--with-mcrypt=/usr/local/bin \
--with-mysqli \
--with-zlib \
--with-pdo-mysql \
This gives me most of the modules and extensions I require for doing my PHP work. For concrete situations I prefer to use virtual machines or Docker containers to mimic the production environment as much as possible, but for small work it's easy to have it running natively on my local machine.
WARNING: Compile OpenSSL instead of using the build-in SSL as it's not compatible!
Edit PHP's Makefile and find the line that begins with EXTRA_LIBS. In this line, replace the following references -lcrypto with /usr/local/ssl/lib/libcrypto.dylib and -lssl with /usr/local/ssl/lib/libssl.dylibor where you have installed the latest OpenSSL library.
A convenient way is to use vi and use :s/\-lcrypto/\usr\/local\/ssl\/lib\/libcrypto.dylib/g to immediately replace all instances of -lcrypto in the line. Do the same for -lssl as well.
Once done, just execute makemake test and sudo make install to install the latest PHP 7 version on your MacBook.
You might want to replace the build-in php with your new compiled version of PHP.
cd /usr/bin
sudo mv php php-orig
sudo ln -sf /opt/php7/bin/php php
When you execute php -v you should see something like the following:
PHP 7.0.8 (cli) (built: Jul 19 2016 11:36:18) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Xdebug v2.4.0RC2, Copyright (c) 2002-2015, by Derick Rethans


It's nice to have PHP on command line, but you might want to have it run in your apache configuration as well.
If you look at the output of "make install" you will see the line:
[activating module `php7' in /private/etc/apache2/httpd.conf]
This means PHP has modified your apache configuration and included the php7 module, you only need to activate it.
In /etc/apache/httpd.conf find the following line:
LoadModule php5_module libexec/apache2/
And comment it out, as we're no longer use php 5, like this:
#LoadModule php5_module libexec/apache2/
Locate the line:
#LoadModule php7_module        libexec/apache2/
And remove the comment hash (#) in front of it
LoadModule php7_module        libexec/apache2/
Restart apache with sudo /usr/sbin/apachectl restart
Now put the following file (info.php) in your document root (see /etc/apache/httpd.conf where this is)
>?php phpinfo();
And point your browser to that file on your local machine, in my case it is http://localhost/info.php.
PHP 7.0.8 running on "El Capitain"

You're now ready to unleash the PHP7 power! Have fun and let me know in the comments if it worked out for you. If not, let's work together how we can solve the issue.


PHPSrbija Conference 2016 review

This past weekend I was invited to speak at PHP Srbija Conference 2016 which was held in Belgrade, the capital of Serbia in the south-east of Europe.

I feared that my departure from Brussels Airport was going to take up a lot of time since the terrorist bombing on March 22, but going through the additional security measures went very smoothly.
Arrived at Brussels Airport well ahead of departure time for #phpsrbija
So, I ended up in "the Loft" business lounge on terminal A where I could catch up on some email and do some work before my flight left for Zurich.
Made it to “the Loft” lounge at Brussels Airport. Let’s get some work done! #IWorkAnywhere #DigitalNomad
This StarAlliance business lounge offers soups, bread and hot snacks along with a variety of drinks. So while waiting for your flight you can relax in the very comfortable sofa's (see picture), have a desk-like table for meals or work, use the sleeping pods or take a shower. I decided to have my coffee and a warm snack before take-off.

At the gate I got a pleasant surprise as I was upgraded to business class, making my trip to Zurich very comfortable.
Just got upgraded to @FlySWISS Business Class! W00t! #travelmagic #phpsrb2016
The flight from BRU to ZRH was quick and uneventful. Making the connection in Zurich was without stress as my flight to Belgrade was delayed. But Zurich is a very nice airport with lots of shops and bars, so instead of heading to the business lounge I ended up wondering around from shop to shop.

At my arrival at Nikola Tesla Airport Belgrade I was welcomed by Milan Popović, one of the 3 organizers of the conference. Milan is a very passionate guy who made PHP Srbija to what it is today.

Awesome reception by @komita1981 as a great start for #phpsrb2016
Before we got to the hotel, we first went for dinner. The other two organizers Aco Gagic and Nikola Poša, a couple of volunteers, Phil Sturgeon and Chris Hartjes were already there and had completed their meals. Milan and I joined the table and got extras. The food was awesome and made me forget I had traveled the bigger part of the day. That night, I slept immediately after we arrived at the hotel.
It's pre #phpsrb16 with @grmpyprogrammer @philsturgeon @DragonBe @nikolaposa @komita1981 @AcoGagic @LDusan

The day before the conference, Milan and Nikola took us on a tour at Belgrade Fortress, a beautiful piece of European history that is kept well preserved against the evils of time. If you visit Belgrade, you should visit this place, with perfect view over the Sava and Danube as it was build at their juncture. The visit was followed by a "small" lunch offered by the crew where we catched up with my good friend and fellow ninja turtle Rafael Dohms.

Lunch time! #phpsrb2016
In the evening we were joined by Ciaran McNulty when we went out for drinks and food. I've come to realize that "lots of meat" is just a simple meal in Serbia.

Just a bit of meat

Conference Day 1! Chris Hartjes was opening keynote and presented his best talk I've seen so far. Was it because of the great food or the warm welcome of the Serbian community, I leave that up to your immagination, but Chris flawlessly presented his keynote talk "An oral history of how I became Grumpy". The rest of the day was filled by Sebastian Bergmann, Rafael DohmsCiaran McNulty, Derick Rethans and Phil Sturgeon.

Conference Day 2: Again a day filled with awesome talks by Rafael Dohms, Marco Pivetta, Michelangelo van Dam (me), a dual talk by Sebastian Bergmann and Ciaran McNulty to be closed off by Gojko Adzic who presented an amazing "The future of test automation" closing keynote.

Again, I would like to thank the organizers Aco GagicMilan Popović and Nikola Poša of #PHPSrb16 for going way beyond expectations. You are awesome hosts and it was my privilege being part of this amazing event and taking home so many wonderful experiences.

I can recommend PHPSrbija Conference to every speaker!

It was hard to say goodbye to the good friends I made at this conference, but every beginning has to have an end. So on Monday I started my way back home. But this time it was a bit more eventful as I had hoped for. Flights were delayed because of bad weather in Western Europe and once I arrived back in Belgium, I ended up without normal public transportation because of strikes. In the end, I litterly had to walk the last mile back home. But I made it safe and sound. This little setback was nothing compared to the great conference I had in Serbia. Can't wait for next year!


PHP Arrays - The php array functions

Source: Xavier33300 on
In my previous article about arrays (the basicssimple operations and associative arrays or hash maps) I have shown what arrays are and what you can do with it. Now I want to dive into real fun and explain PHP's array functions with real-world examples and how you can apply them in your day-to-day work.

Collection to select form key-values

Many of the website registration forms uses a country select element or an autocomplete input field using data from a database.

If this was a single PHP with HTML combined page, there was no problem as you could easily reuse the query made to collect the data. But when using an MVC approach where your controller needs to push the data it fetches from the backend to the form before the form can be passed to the view you're in for a treat. We're addressing the issues for an MVC approach here.

Let's look at our country table first to get an impression how data is being stored in the database.

| Field     | Type        | Null | Key | Default | Extra          |
| id        | int(11)     | NO   | PRI | NULL    | auto_increment |
| iso       | char(2)     | NO   |     | NULL    |                |
| name      | varchar(80) | NO   |     | NULL    |                |
| nicename  | varchar(80) | NO   |     | NULL    |                |
| iso3      | char(3)     | YES  |     | NULL    |                |
| numcode   | smallint(6) | YES  |     | NULL    |                |
| phonecode | int(5)      | NO   |     | NULL    |                |

In order to use this data in our forms, the two fields "iso" and "printable_name" are most likely the fields that would make the most sense.

Two approaches we can take here:

  1. we query our database for only those fields we need, with the requirement that we need to make a second database call when we need to populate our select field for country phone prefixes
  2. we query all of our required fields "iso", "printable_name" and "phonecode" in one query and use PHP array functions to populate our select fields
We choose to take option 2.

Let's have a look on how most people do things nowadays. The first thing they do is retrieve the data from their backend in the controller. In the controller they prepare their form and pass the form back to the view.

public function registerAction()
$form $this->getForm('member');

$countryMapper = new CountryMapper();
$countryList $countryMapper->fetchAll();
$countrySelect = [];
$phoneSelect = [];
    foreach (
$countryList as $country) {
$countrySelect[] = [
'iso' => $country['iso'],
'nicename' => $country['nicename'],
$phoneSelect[] = [
'phonecode' => $country['phonecode'],
'nicename' => $country['nicename'],

    if (isset (
$this->session->memberForm)) {
$form unserialize($this->session->memberForm);
        unset (
    return [
'memberForm' => $form,

So, within the controller a loop is created to populate two field elements "country" and "phoneprefix".  Even though this is an easy approach and works in most cases, the moment you have a lot of data to process, this kind of approach is slowing down your application. Say hello to two power functions: "array_walk" and "array_intersect_key"!

PHP function "array_walk" allows you to apply user functionality to each element of that array. This means we can apply our second functionality "array_intersect_key" on each row.

PHP function "array_intersect_key" gives us the ability to take the common elements from our country list row and the keys we provide as second argument.

$countrySelect = [];
array_walk($countryList, function ($row$key) use (&$countrySelect) {
$countrySelect[] = array_intersect_key(
'iso' => null'nicename' => null]

$phoneSelect = [];
array_walk($countryList, function ($row$key) use (&$phoneSelect) {
$phoneSelect[] = array_intersect_key(
'iso' => null'phonecode' => null]

Now we have two arrays that contain only the elements we can just pass on to the form select elements. And the whole controller action now looks like this:

public function registerAction()
$form $this->getForm('member');

$countryMapper = new CountryMapper();
$countryList $countryMapper->fetchAll();
$countrySelect = [];
array_walk($countryList, function ($row$key) use (&$countrySelect) {
$countrySelect[] = array_intersect_key(
'iso' => null'nicename' => null]

$phoneSelect = [];
array_walk($countryList, function ($row$key) use (&$phoneSelect) {
$phoneSelect[] = array_intersect_key(
'iso' => null'phonecode' => null]

    if (isset (
$this->session->memberForm)) {
$form unserialize($this->session->memberForm);
        unset (
    return [
'memberForm' => $form,

Finding primary keys from a collection

Another common pattern I see is when developers need to pull ID's from a collection of elements to pass on to a next request. Again, foreach is the common used loop to iterate over each element, adding the ID property to another array which then gets passed on to the query.

Let's first look our code that we're going to process.

class PhpFunction {

    public function 
$this->id $id;
$this->label $label;
$functions = [

Now this example is only containing 3 elements, but when you look at the website there are thousands of functions, so consider this is a huge collection of php functions.

In many cases I see something like the following code to retrieve the ID's from this collection:

$functionIds = [];
foreach (
$functions as $function) {
$functionIds[] = $function->id;

Even though this is a common pattern, I would prefer to use a native PHP function for processing this. Say hello to "array_map", the function that allows you to use a custom functionality on each element of the given array.

$functionIds array_map(function ($element) {

The result is exactly the same, but now using PHP's native C power processing huge arrays goes a bit faster than the "foreach"-loop.

Next article we're looking at more common patterns for processing arrays. Love to see you again.