Posts Tagged ‘PHP’

Dienstag, 11. September 2007

PHP5: 2006-13-01 wird nicht mehr akzeptiert

Als ich noch ein junger, unerfahrener PHP-„Programmierer“ war (ich brauchte das Geld!), kamen ab und zu solche Konstrukte heraus:

$str_next_month = strtotime($arr_date["year"] . "-" . ($arr_date["mon"] + 1) . "-" . "01");

Das Script nimmt in Kauf, dass bei nicht sachgemässer Handhabung der Wert für den Monat auch einmal 13 betragen kann. In PHP4 meckerte strtotime() nicht gross um und rechnete das Datum kommentarlos auf den auf Dezember folgenden Januar um.

Nun, seit kurzem läuft PHP 5.2.2 auf meinem Entwicklungsserver (Liip und Hostpoint haben das ihre dazu beigetragen) – und bisher hielt sich mein Code tapfer. Bis heute abend.

Zu spüren bekam mein Server diese Fehlprogrammierung ausgerechnet in einer schicken while-Schleife (zu meiner Rehabilitierung die einzige in den knapp 1000 Zeilen PHP-Code). 120 Sekunden lang eine CPU-Auslastung von 100% – yippie! Multipliziert mit den Anzahl Versuchen, den Fehler einzugrenzen … Heute wurden einige Elektronen zusätzlich verbraten und Schaltungen überbeansprucht.

Was lernen wir daraus?

  • Programmiere keinen Scheiss zusammen! (Y2k reloaded?)
  • Wenn du while-Schleifen schon nicht vermeiden kannst, baue wenigstens Sicherungen ein, z.B. ganz stümperhaft in Form eines Counters

Tags: ,
Labels: Allgemein

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 29. August 2007

Danke Hostpoint! (oder: MySQL Suchen-und-Ersetzen)

Dank dem Wechsel von PHP4 auf PHP5 bei meinem für Kunden bevorzugten Hoster musste ich bei einigen Web-Sites folgende Änderungen vornehmen:

UPDATE `smt_content`
SET source_de = REPLACE( source_de,  'PHP_SELF',  'ORIG_SCRIPT_NAME' )

Das Problem scheint daher zu rühren, dass PHP5 als CGI ausgeführt wird und einige Werte von $_SERVER nicht oder falsch zu setzen scheint. Mit ORIG_SCRIPT_NAME erhalte ich auf jeden Fall wieder den vom Web-Server ausgesehenen WWW-Pfad zum entsprechenden Script.

ACHTUNG

Natürlich erst, nachdem ich einen Dump der entsprechenden Tabelle gezogen hatte (ein Typo, und flutsch sind alle Seiteninhalte nach /dev/null unterwegs).

Nachtrag

Im Oktober 2007 wurde ein weiterer Wechsel nötig. Neu heisst die gesuchte Variable SCRIPT_NAME:

UPDATE `smt_content` SET source_de = REPLACE( source_de,  'PHP_SELF',  'SCRIPT_NAME' )

Tags: ,
Labels: Web

Keine Kommentare | neuen Kommentar verfassen

Dienstag, 12. Juni 2007

PHP aussagekräftiger benchmarken

In einer vor einigen Jahren programmierten Web-Applikation (ANIBILL; Übernachtungsstatistik und Rechnungsstellung für einen Tierstall) gab es vor einigen Wochen gewisse Performance-Engpässe, die sich in einer äusserst schleppenden Antwortzeit äusserten. Nach einigen ersten Untersuchungen isolierte ich MySQL (respektive unoptimierte Queries) als Ursache der Probleme.

Die richtige Vorgehensweise

Doch was nun? Klar konnte ich nun temporäre Änderungen an der Applikation auf einem Test-Server vornehmen und hoffen, dass ich den Fehler reproduzieren konnte. Oder aber: Ich änderte den Code dermassen, dass die Applikation künftig bei jedem Aufruf Zeitmessungen vornahm, mit denen ich ein aussagekräftigeres Bild erhielt. PHP-Programmierer werden es zu schätzen wissen, wenn sie Optimierungen auf Grund von 1’000 Messungen anstelle von 1-2 Probeläufen vornehmen können.

Die Lösung

Heraus kamen zwei Funktionen: anibill__get_db_data() und anibill__dump_microtime(). Durch die erste Funktion werden alle SQL-Queries „kanalisiert“, die mit SELECTs arbeiten. Zur Beruhigung der versierten Leser: Diese Funktion war seit Beginn der Applikation vorhanden, ich musste also nicht 1’000 Codezeilen nach mysql_query() durchstrählen …

Innerhalb dieser Funktion messe ich mittels microtime(), wie lange mysql_query() zum Ausführen meines SQL-Queries benötigt (und nur das, der Rest interessiert mich nicht). Bevor ich die aus der Datenbank gelesenen Daten zurückgebe, rufe ich die Benchmark-Funktion anibill__dump_microtime() auf, die mir einerseits die Laufzeit des Queries als auch gleich die aufrufende Funktion in eine Datenbank-Tabelle speichert. Bis zu diesem Zeitpunkt kannte ich die PHP-Funktion debug_backtrace() nicht – dabei ist sie äusserst mächtig. Ihre Ausgabe führt genau Buch, welche Funktionen seit dem Aufruf des Scripts ausgeführt wurden. Und nicht nur das – sogar die Zeilennummer des die Funktion enthaltenden PHP-Scripts ist angegeben. Ein Traum!

function anibill__get_db_data($str_sql_query,$bol_die_on_err = TRUE) {
 ...
 
 // Benchmark current MySQL query
 $arr_time[0] = microtime();
 $obj_db_data = mysql_query($str_sql_query,$res_db_conn);
 $arr_time[1] = microtime();
 
 ...
 
 // Store benchmark to database
 anibill__dump_microtime($arr_time,$str_sql_query);
 
 return $arr_db_data;
}

function anibill__dump_microtime($arr_time,$str_sql_query) {
 ...
 
 // Still using PHP4 and therefore wrestling with microtime()'s format
 $arr_start    = explode(" ", $arr_time[0]);
 $arr_end    = explode(" ", $arr_time[1]);

 $int_seconds            = $arr_end[1] - $arr_start[1];
 $flo_microseconds       = $arr_end[0] - $arr_start[0];

 $flo_runtime            = $int_seconds + $flo_microseconds;
 
 // Which function called anibill__get_db_data() in the first place?
 $arr_debug = debug_backtrace();
 if(isset($arr_debug[2]['function']))
   $str_function = $arr_debug[2]['function'];
 else
   $str_function = NULL;

 if(isset($arr_debug[1]['line']))
   $str_line = $arr_debug[1]['line'];
 else
   $str_line = NULL;
 
 ...
 
 return TRUE;
}

Ich möchte all die Christians, Andreas und Silvans da draussen um Gnade bitten – mein Coding-Stil wird wohl nicht der effektivste sein (zu viele Zeilen, zu viele Einzüge etc.), doch die Lesbarkeit liegt mir am Herzen. Und ja, von OOP keine Spur …

Selbstverständlich generiert das Benchmarken und Backtracen einen gewissen Overhead, doch aus meiner Sicht ist die vorgestellte Methode geeignet, die Performance kleinerer Web-Applikationen mit wenigen gleichzeitigen Zugriffen zu messen – ohne kostenpflichtige Tools einzukaufen und grosse Profiling-Sessions zu starten.

Zum Schluss

Erfinde ich das Rad neu? Gibt es elegantere Lösungen? Die Kommentarfunktion ist ab sofort geöffnet.

Tags:
Labels: Web

Keine Kommentare | neuen Kommentar verfassen

Freitag, 4. Mai 2007

Wenn Smarty nicht schreiben will

Vor kurzem erhielt ich bei der Installation einer PHP-Web-Applikation folgende Fehlermeldung in die error.log geschrieben:

[client 0.0.0.0] PHP Warning:  Smarty error: problem creating directory "/var/webs/smarty/templates_c/%%778/%%778656331" in /var/webs/smarty/Smarty.class.php on line 589, referer: http://www.server.tld/
[client 0.0.0.0] PHP Warning:  Smarty error: problem writing '/var/webs/smarty/templates_c/%%778/%%778656331/error.tpl.php.' in /var/webs/smarty/Smarty.class.php on line 589, referer: http://www.server.tld/

Obwohl ich die Berechtigungen des übergeordneten Verzeichnisses auf rwxrwxrwx (chmod 777) gesetzt hatte, weigerte sich Smarty resp. PHP, einen neuen Unterordner zu erstellen.

Nach einigen Pröbeleien und Google-Suchen fand ich dann doch noch eine einleuchte Antwort auf die Ursache des Problems:

A: This is the problem with your hosting provider. The directories which are created by php modules, have 644 permissions by default. You cannot fix it.

Quelle: Smarty error

Am selben Ort ist ein Workaround beschrieben. Man bearbeite inc/smarty.inc.php und ändere folgende Konfigurationsvariable:

$this->use_sub_dirs = false;

Voilà! Nun funkioniert auch UCCASS 1.8.1 auf meinem Server.

Tags: ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 11. März 2007

TerminGenius!

Um Sitzungen auf der Arbeit besser planen zu können, habe ich mich vor einigen Jahren spontan dazu entschlossen, ein PHP-Script zu schreiben, das mir die Online-Termin-Umfrage ermöglicht (genannt „Terminfinder“). Mit der Zeit kamen einige Inputs von den Benutzern hinzu und mit Version 2.0beta wurde das Produkt in „TerminGenius!“ umbenannt.

Auf Wunsch von Stefan Oberwahrenbrock habe ich meine OSS-Applikation TerminGenius! um eine wichtige Funktion erweitert: Zur Erleichterung des Entscheides wird nun zusammengezählt, wie viele Leute an einem bestimmten Tag können.

eMeidi.com – Quelloffene Software

Weiterhin viel Spass bei der Suche nach einem Termin, der allen passt *smile*

PS: Wer sich nicht mit der Installation von PHP-Scripts auf einem Web-Server herumschlagen will, benutze Doodle.

Tags: ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen