Inleiding
Laatst kwam ik tussen oude back-ups een SQL-bestand tegen van een zelfgebouwd forum uit 2010. Ook de code was bewaard gebleven en stond zelfs in één van mijn lokale Git-repositories. Hoe leuk zou het zijn om al die oude berichten nog eens te kunnen lezen? Om van de hilarische code-kwaliteit nog maar te zwijgen…
Setup
Het inlezen van de database was redelijk eenvoudig: een source setup.sql
in de
MySQL-console en het was geregeld. Het op gang helpen van de PHP-code zou
behoorlijk wat meer tijd in beslag nemen. In eerste instantie verscheen er een
blanco pagina bij het oproepen van index.php
- een slecht teken.
Diagnose
Aldus ging ik met echo
en var_dump
op zoek naar de plek waar PHP de bocht
uit vloog. Ik kwam terecht bij een aanroep van mysql_query()
, een veelgebruikte
functie om een aanvraag op de database uit te voeren. Maar, ik heb toch een
MySQL-server draaien, en de juiste gegevens in de configuratie ingesteld?
Jawel, maar sinds PHP 5.5 zijn de oude mysql_
-functies afgeschreven en
vervangen door de modernere, snellere en veiligere mysqli_
-varianten. Als ik
dit forum op mijn huidige (PHP7) machine wilde draaien, moest ik een alternatief
zoeken.
Aanpak
Door de gehele broncode lagen honderden aanroepen verspreid - ik had geen zin om alle code door te spitten en overal aanpassingen te maken. Als vanzelf kwam de gedachte om wrapper-functies te schrijven. Als PHP de functies niet meer aan boord heeft, dan kan ik ze toch zelf opnieuw definiëren? En dan achter de schermen de nieuwe functies aanroepen.
Maar hoe vind ik alle verschillende functies die ik moet 'vervangen'? grep
to
the rescue! Met onderstaande one-liner vond ik alle aan MySQL geliëerde commando's
in de broncode:
$ grep -rihIPo 'mysql_[^(]+' * | sort | uniq
mysql_affected_rows
mysql_errno
mysql_fetch_array
mysql_num_rows
mysql_pconnect
mysql_query
mysql_real_escape_string
mysql_result
mysql_select_db
mysql_set_charset
grep
zoekt in tekstbestanden naar tekenreeksen of patronen. In dit geval
recursief in alle mappen (-r
) en bestanden (*
) met Perl-compatibele regular
expressies (-P
). Verder wordt geen verschil gemaakt tussen hoofd- en kleine
letters (-i
), worden binaire bestanden genegeerd (-I
) en geen bestandsnamen
in de output opgenomen (-h
). Met -o
geeft grep
alléén het gematchte stukje
terug.
Dan volgt de magie van een eenvoudige reguliere expressie. Hier wordt gezocht
naar de tekst mysql_
, gevolgd door alles wat geen openende ronde haak is
([^(]+
). De uitvoer wordt gesorteerd en gefilterd op duplicaten. Uiteindelijk
bleven de getoonde funcies over, waarvoor ik een wrapper moest schrijven.
Wrappers
Gelukkig gebruikte ik in die tijd wel al het systeem van één centrale include
.
Daarin werd de databaseverbinding gelegd en alle globale functies gedefiniëerd.
Ik maakte de volgende aanpassing:
<?php
$db = mysqli_connect(
$config['host'], $config['user'], $config['password'], $config['database']
);
mysqli_set_charset($db, 'utf8');
function mysql_affected_rows(){
global $db;
return mysqli_affected_rows($db);
}
function mysql_errno(){
global $db;
return mysqli_errno($db);
}
function mysql_fetch_array($q){
return mysqli_fetch_array($q);
}
function mysql_num_rows($q){
return mysqli_num_rows($q);
}
function mysql_query($q){
global $db;
return mysqli_query($db, $q);
}
function mysql_real_escape_string($q){
global $db;
return mysqli_real_escape_string($db, $q);
}
function mysql_result($q, $o){
mysqli_data_seek($q, $o);
$row = $q->fetch_row();
return $row[0];
}