071 - 576 13 23
Upgrade naar PHP 7 in één uur

Upgrade naar PHP 7 in één uur

door op 28 augustus 2017


Ik heb recentelijk een project afgerond waarin al onze websites over zijn gezet naar PHP 7. Tijdens dit traject heb ik ongeveer 200 sites overgezet. Dit proces was leuk, maar soms toch ook een beetje frustrerend. In dit artikel vertel ik hoe ik het heb aangepakt en geef ik een aantal tips om razendsnel te kunnen updaten.

Ontwikkelen in een oude PHP versie is niet leuk en ik wil graag dat developers het naar hun zin hebben bij SWIS. Dit was dé voornaamste reden om aan de slag te gaan met het upgraden.

Daarnaast zijn er vanuit andere hoeken natuurlijk ook genoeg redenen om te upgraden. De performance van PHP 7 is het dubbele van eerdere versies, wat je servers dus ontlast. Daarnaast zijn er stappen gezet qua features, zaken als return types en strict typing. Dit zijn grote stappen vooruit om te zorgen dat je kwalitatief nog betere code kan schrijven.

Liever direct de tools lokaal gebruiken? Kijk dan bij de tools installeren om binnen 5 minuten aan de slag te kunnen

Statische analyse

Om in te schatten wat de staat van een project is heb ik een tweetal tools gebruikt die statische analyse uitvoeren op de code. PHP CodeSniffer met de PhpCompatibility package en PHP 7 Compatibility Checker.

PhpCompatibility gebruikt PHP CodeSniffer voor het uitzoeken of er problemen zijn in je PHP bestanden. Tijdens het uitvoeren geeft hij aan in welke bestanden problemen aanwezig zijn.

PHP7CC is de tweede tool die ik gebruikt heb voor de upgrade. Deze doet ongeveer hetzelfde als de eerste, maar in het begin wilde ik iets meer zekerheid. Ze controleren de bestanden op een iets andere manier en daardoor kunnen ze elkaar aanvullen. Later in het project heb ik deze laten varen aangezien er bijna geen extra fouten gevonden werden.

De tools installeren

Het handmatig installeren van de tools is niet helemaal foolproof. Zeker PHPCompatibility is wat lastig om goed te installeren. Daarom heb ik op GitHub een project Php 7 upgrade tools aangemaakt om direct aan de slag te kunnen.

Installatie

  1. Clone de git repository:
    git clone https://github.com/swisnl/php7-upgrade-tools
  2. In de directory die aangemaakt is, installateer de tools met composer:
    composer install
  1. De tools zijn nu beschikbaar!
    ./vendor/bin/phpcs /pad/naar/project
    ./vendor/bin/php7cc /pad/naar/project

Verder staat ook de code voor de shims waar we het later nog over hebben in je vendor map zodat je kan kijken hoe die werken.

Veel voorkomende migratieproblemen

De problemen die ik het meeste tegen kwam in oude projecten heb ik verzameld. Eigenlijk was 90% van het werk gerelateerd aan deze kleine subset aan code aanpassingen.

Mysql_* functies

In PHP 7 zijn deze functies niet meer beschikbaar, dus moesten alle `mysql_` functies omgeschreven worden naar mysqli of PDO functies.

Ereg* functies

Alle ereg functies zijn niet meer beschikbaar. Dit heeft als gevolg dat je deze om moet schrijven naar hun preg* equivalient

Split functie

Deze functie was al erg lang deprecated maar werkte nog wel. Helaas is deze nu echt weg en moet hij vervangen worden voor een van de alternatieven. 

PHP errors worden nu gethrowed

Voor PHP 7 gaf PHP een error als er wat mis was in je code. Een groot aantal van deze errors geven nu een Error als een Throwable. Dit heeft wel een paar gevolgen.

Op het moment dat je `set_exception_handler` gebruikt om een zelf excepties af te handelen kan deze nu ook een Throwable ontvangen wat een PHP error kan zijn. Deze klasse is geen subklasse van Exception, dus daar kan je code op stuk lopen. Als je code voortaan alleen nog op PHP7 gaat draaien is de fix simpel, vervang de typehint naar Throwable, nu kan hij zowel normale excepties als errors afhandelen.

Preg_replace /e modifier

Eval is the root of all evil. Maar oude projecten roepen nog wel eens `preg_replace` aan die gebruik maakt van `/e` (eval). Het gebruik van deze modifier is een slechte gewoonte, en hopelijk kom je hem nooit tegen. Kom je 'm wel tegen, dan moeten deze calls vervangen worden door preg_replace_callback.

Andere breaking changes

Behalve de bovenstaande breaking changes zijn er nog een aantal. Maar deze ben ik persoonlijk niet tegen gekomen in onze projecten. Veel van de problemen komen naar boven tijdens de statische analyse, maar het is natuurlijk aan te raden om je projecten altijd goed te testen voordat je de upgrade live zet.

Shims?

Er is ook een snelle oplossing voor projecten waar je geen tijd voor hebt om deze te herschrijven: shims. Dit is niet aan te raden, maar soms wel nodig.

a shim is a small library that transparently intercepts API calls and changes the arguments passed, handles the operation itself, or redirects the operation elsewhere.

Voor MySQL heb ik een goed werkende shim gevonden. Deze zorgt ervoor dat hij automatisch alle functies upgrade naar de nieuwe aanroepen. Hij doet verder niets met het verbeteren van code om bijvoorbeeld prepared statements te gebruiken en de kans op SQL-injectie te verkleinen, maar het kan wel gebruikt worden als een snelle pleister.

Naast MySQL hebben we ook nog te maken met ereg functies. Deze zijn niet meer beschikbaar dus moeten ook vervangen worden. Hiervoor heb ik een eigen shim die ereg functies vervangt door hun preg equivalent geschreven. Hier geldt ook bij, dit is een pleister, en geen structurele oplossing.

Upgrade naar PHP 7 binnen een uur

De upgrade van onze sites naar PHP 7 is erg gemakkelijk verlopen. Door gebruik te maken van de open source tools die beschikbaar zijn kan een hoop handmatig zoekwerk uit handen genomen worden. Daardoor is het voor ons, en nu ook voor jou, mogelijk om sites binnen een uurtje te upgraden naar PHP 7.