Posts Tagged ‘PHP’

Dienstag, 17. November 2009

Du sollst HTML nicht mit Regex parsen!

or many novice programmers, there’s something unusually seductive about parsing HTML the Cthulhu way instead of, y’know, using a library like a sane person. Which means this discussion gets reopened almost every single day on Stack Overflow. The above post from five years ago could be a discussion from yesterday.

Quelle: Coding Horror: Parsing Html The Cthulhu Way

Auch für mich waren Reguläre Ausdrücke während Jahren das Allheiltmittel, um Informationen im HTML-Format aus dem Web auf den lokalen Server zu ziehen und danach gewisse Informationsstücke daraus zu extrahieren.

Meine (mittlerweile verflossene) Anstellung bei Liip öffnete mir aber die Augen. Das erste Mal, als ich mit Marc Ammann, dem Entwickler von GottaGo, über die Abfrage von Fahrplänen über das Web-Interface der SBB fachsimpelte (die Informatikbeamten des Transportunternehmens stehen nicht so auf frei zugängliche APIs). Ich war völlig naiv der Auffassung, dass auch er den HTML-Output des SBB Online-Fahrplans mit Regex durchparsen würde. Stimmte aber nicht, für etwas gibt es ja DOM! Ich machte mir aber keine weiteren Gedanken dazu, weil ich mir nicht vorstellen konnte, dass es etwas besseres als Regex gäbe, um HTML zu zähmen (dabei arbeitete ich doch für eine XML-Bude).

Das zweite, nun definitiv den Ausschlag gebende Aha-Erlebnis ereignete sich im Frühjahr 2009: Bei den Arbeiten zu energiezukunft.ch setzten wir ein Glossary-Plugin für WordPress ein. Als ich einen Blick auf den Sourcecode dieses Plugins warf, entdeckte ich es — die wohl aus PHP-Sicht heilsbringendste Zeile der letzten Monate:

DOMDocument::loadHTML();

Quelle: DOMDocument::loadHTML();

Weiter ausführen möche ich diesen Fingerzeig nicht weiter. Ich darf aber mit gutem Gewissen sagen, dass ich dank dieser Erleuchtung mittlerweile eine kleine, private Applikation in Version 2 realisiert habe. Während die erste Version munter Reguläre Ausdrücke einsetzt (und dabei immer wieder grandios scheitert), benutzt Version 2 ebendiese Klassen, um die Aufgabe mit schönem, einfachen und leicht wartbaren Code auszuführen. Und plötzlich gehört das Gefrickel der Vergangenheit an.

(Aber ja, HTML kann man weiterhin mit Regulären Ausdrücken parsen — und sollte es auch, wenn es nur darum geht, ein kleines Informationsstückchen aus HTML-Code zu extrahieren, ohne dass man gleich einen ganzen Tag daran rumprogrammieren möchte. Wie beispielsweise ubs.mad4you.homeip.net — wobei ich hier auch eher einen JSON-Parser als Reguläre Ausdrücke verwendet hätte. Was solls, der Kern des Scripts war dank Regulären Ausdrücken innert Minuten geschrieben.)

Tags: , ,
Labels: Web

Keine Kommentare | neuen Kommentar verfassen

Donnerstag, 1. Januar 2009

WordPress 2.7 nach blanker Installation extrem langsam

Gerade habe ich auf einem Entwicklungsserver WordPress 2.7 installiert. Die Installation verlief wie gewohnt in einigen wenigen Schritten – doch das böse Erwachen folgte kurz darauf: Obwohl die Installation noch über keinen einzigen Blog-Artikel verfügte, betrug die Ladezeit pro Seite 60 bis 90 Sekunden!

Dank Google stiess ich rasch auf einige Hinweise (von Endanwendern) und fand schlussendlich einen dazugehörigen Bug-Report mit Informationen, die im Gegensatz zum vorangehenden Link auch für Sysadmins und Entwickler nützlich waren.

Die Lösung des Problems lautete in meinem Fall:

# apt-get install php5-curl

Jetzt laden die Seiten (des Frontends!) nur noch mit etwa 5 Sekunden Verzögerung …

Nachtrag: Administrationsoberfläche („Dashboard“)

Seit ich das LDAP-Plugin aktiviert habe, lädt die Web-Site wieder unterträglich langsam. Ein Grund könnte sein, dass der Testserver im Intranet steht und nur über einen Proxy-Server Kontakt ins Internet aufnehmen kann. Leider spinnt der Proxy-Server derzeit und kann auf keine URL verbinden …

Nach dem ich http.php gemäss Anleitung gepatcht habe, sieht man die Wurzel allen Übels:

[Thu Jan 01 23:06:02 2009] [error] [client 0.0.0.0] Requesting http://api.wordpress.org/plugins/update-check/1.0/
[Thu Jan 01 23:07:03 2009] [error] [client 0.0.0.0] Requesting http://api.wordpress.org/plugins/update-check/1.0/, referer: http://www.ma.hist-web.unibe.ch/wp-admin/

Die 60 Sekunden Ladezeit deuten auf ein – man verzeihe es mir – bescheuert hohes Timeout für HTTP-Requests hin. Ich versuche deshalb nun, Disable WordPress Core Update sowie Disable WordPress Plugin Updates zu installieren, um HTTP-Anfragen an jedwelche Server zu verhindern.

Weitere Informationen bietet beispielsweise WordPress 2.7 Core Update.

Tags: ,
Labels: Blogosphäre, Web

Keine Kommentare | neuen Kommentar verfassen

Montag, 27. Oktober 2008

Regex (Reguläre Ausdrücke) im Sandkasten testen

Regular Expression sind für viele Voodoo, für den fortgeschrittenen Programmierer aber ein unentbehrliches Hilfsmittel. Hier einige Tools, die dem Anfänger helfen, Reguläre Ausdrücke am „lebenden Beispiel“ zu meistern:

Empfehlungen Dritte

Tags: ,
Labels: IT

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 26. Oktober 2008

Segmentation Fault bei leerer Cacti-Tabelle

Wie bereits getwittert habe ich gestern zum ersten Mal eine PHP-Web-Applikation (cacti, eine Tool, mit welchem per SNMP Zähler von netzwerkfähigen Geräten aufgezeichnet und ausgegeben werden können) erlebt, die Apache mit einem …

[Sat Oct 25 15:55:52 2008] [notice] child pid 13452 exit signal Segmentation fault (11)

… bei jedem Aufruf zum Absturz gebracht hat (Apache-Threads sei dank, dass nicht gleich der ganze Web-Server zum erliegen kam).

Google wusste selbstverständlich die simple Lösung auf das Problem – für einmal musste ich aber die Suchanfrage mehrere Male abändern und auch auf die zweite Seite der Suchresultate blättern:

After throwing strace at it I could see before it died all it was doing was running the SQL query „select value from settings where name=’log_verbosity'“ over and over (around 6000 times before it died).

After squirting the cacti.sql file into MySQL all was well and the install completed OK.

Quelle: Seven Of Nine – Borg – Cacti – exit signal Segmentation fault (11)

Unglaublich, aber wahr: Wenn die Applikation die gesuchte Tabelle nicht findet, gelangt sie mit der Error Logging-Funktion in eine Endlosschleife. Auch bei mir löste sich das Problem, indem ich die im Cacti-Basisverzeichnis liegende cacti.sql manuell in MySQL importierte:

$ mysql -u cacti -p cacti < ./cacti.sql

Kostenloser Tipp an die Entwickler (Pseudo-Code):

if(!table_exists($tbl)) {
 mysql_import('./cacti.sql');
 
 if(!table_exists($tbl)) {
  die('Import of cacti.sql failed. Error #' . mysql_errno() . ' - ' . mysql_error());
 }
}

Tags: ,
Labels: Web

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 2. Juli 2008

Hostpoint-Problem des Monats: Zeichensalat

Kein Monat vergeht, in dem Hostpoint nicht eine Überraschung parat hat. Während ich im Juni das erste Mal seit langem etwas Positives berichten durfte, war klar, dass im Juli garantiert wieder etwas kaputt gehen musste.

Und tatsächlich: Heute erhalte ich ein Mail eines Kunden, der über komische dargestellte Sonderzeichen flucht. Nach dem ich die Homepage angesurft habe, kann ich das Problem bestätigen: Irgendwie scheinen da UTF-8 und ISO-8859-1 durcheinander gekommen zu sein. Seit sechs Jahren hat die Web-Site keine Probleme mit Zeichensätzen aufgewiesen, doch nun ist über Nacht wohl etwas „kaputt“ gegangen.

Soweit ich erkennen konnte, liegt das Problem darin begründet, dass mysql_query() neu nicht mehr ISO-8859-1-kodierte Zeichensätze zurückliefert, sondern UTF-8. Das HTML-Dokument sagt von sich aber, dass es in ISO-8859-1 kodiert ist – und htmlentities() erwartet auch ISO-8859-1. Ah, und die Tabellen-Spalten weisen ebenfalls latin1_german1_ci als Kodierung auf (jedenfalls sagt mir das phpMyAdmin so).

Temporärer Workaround

mysql_query("SET NAMES latin1");

… zuoberst in der index.php (natürlich nach dem Initialisieren der Datenbankverbindung!)

Jetzt klappt es wieder mit den Zeichensätzen.

Mal schauen, was sich Hostpoint für den kommenden Monat einfallen lässt.

Tags: , , ,
Labels: Schweiz

1 Kommentar | neuen Kommentar verfassen

Dienstag, 24. Juni 2008

Xdebug-Meldungen verfeinern

Wie man Xdebug installiert, habe ich hier bereits beschrieben. Doch mit der Installation alleine ist es noch nicht getan; das Teufelswerkzeug muss nun auch noch derart konfiguriert werden, dass es dem Entwickler alle wichtigen Informationen liefert.

Die Jungs drüben bei IBM haben sich die Mühe gegeben, die (bezüglich INI-Einstellungen schwer durchschaubare) Dokumentation zu lesen und ihre Konfigurationsparameter im Netz zu publizieren:

xdebug.dump_once = On
xdebug.dump_globals = On
xdebug.dump_undefined = On
xdebug.dump.SERVER = REQUEST_METHOD,REQUEST_URI,HTTP_USER_AGENT
xdebug.dump.REQUEST=*

xdebug.show_exception_trace = On
xdebug.show_local_vars = 1
xdebug.var_display_max_depth = 6

Quelle: Squash bugs in PHP applications with Xdebug

Tönt gut und produziert äusserst detaillierte Fehlermeldungen.

Wer nichts vom korrekten Initialisieren von Variablen hält, sollte xdebug.dump_undefined vielleicht lieber auf Off schalten …

Wer auf Exceptions setzt und diese sauber abfängt, sollte vielleicht auch xdebug.show_exception_trace auf Off schalten …

Tags: ,
Labels: Linux, Web

Keine Kommentare | neuen Kommentar verfassen

Dienstag, 10. Juni 2008

Apache 1.3, MySQL 5 und PHP 5 unter Mac OS X auf UTF-8 trimmen

Mittlerweile habe auch ich den AMP-Stack auf meinem MacBook installiert und entwickle damit Web-Applikationen. Damit es bezüglich den Zeichensätzen koscher zu und her geht, musste ich folgende zwei Anpassungen an der Konfiguration vornehmen:

Apache 1.3

(Ich verwende aus Faulheit den mit Tiger mitgelieferten Apache – leider halt noch nicht 2.x)

In der /etc/httpd/httpd.conf wird mit folgendem Befehl eingestellt, dass im Header der HTTP-Antwort UTF-8 als Zeichensatz angegeben wird:

AddDefaultCharset UTF-8

MySQL

In der /etc/my.cnf

init-connect='SET NAMES utf8'

Bei jeder Verbindungsaufnahme (bspw. mysql_connect() via PHP) wird der Zeichensatz der ausgelieferten Daten damit auf UTF-8 geschaltet.

Selbstverständlich muss man aber immer noch aufpassen, in welchem Zeichensatz man Datenbank-Dumps exportiert und wieder einspielt …

Tags: , , , , ,
Labels: Linux, Web

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 28. Mai 2008

Vom Hammer und den Nägeln

Some of the largest sites on the internet — sites you probably interact with on a daily basis — are written in PHP. If PHP sucks so profoundly, why is it powering so much of the internet?

The only conclusion I can draw is that building a compelling application is far more important than choice of language.

Quelle: Coding Horror: PHP Sucks, But It Doesn’t Matter

Wie sagt ein Kollege immer so schön? Es kommt nicht auf die Grösse des Hammers drauf an, sondern wie man damit nagelt … Übertragen wohl: Es kommt nicht auf die Grösse des Hammers drauf an, sondern auf das, Haus, das man zusammennagelt. Oder so …

Tags: ,
Labels: Web

Keine Kommentare | neuen Kommentar verfassen

Sonntag, 11. Mai 2008

MySQL INSERTs und UPDATEs mit Subselects

Kürzlich durfte ich nachträglich zwei Datenbanktabelle normalisieren. Obwohl ich längst von den Subselect-Fähigkeiten von MySQL wusste, hatte ich es bis dato noch nie ausprobiert. Wie es sich herausgestellt hat, ist das Prozedere deutlich einfacher, als ich es mir erträumt hatte.

Rubriken neu in separater Tabelle

Die Tabelle daten enthält bspw. Adressen, die jeweils einer bestimmten Rubrik zugewiesen sind. Selbstverständlich kann man die Rubrik in dieselbe Tabelle hardcoden – doch deutlich hübscher ist es, die Rubrik in eine eigene Tabelle auszulagern und diese mittels eines Foreign Keys zu verknüpfen. Einer der Vorteile: Muss der Name einer Rubrik angepasst werden, geschieht dies an einem einzigen Ort, die Änderung wird aber gleich für alle Adressen übernommen.

Folgender Befehl nahm die hardcodierten Rubriken und fügte diese (jeweils einmal!) in die Tabelle rubriken ein:

INSERT INTO daten_rubriken
(rubrik)
SELECT DISTINCT(rubrik) FROM daten

Wichtig ist die SELECT ... Klausel – bis dahin handelt es sich beim SQL-Query um einen ganz normalen INSERT. DISTINCT bewirkt, dass der Rubrikennamen nur einmal ausgelesen wird (es können ja dutzende oder tausende Einträge dieselbe Rubrik haben).

Rubriken-IDs in Ursprungstabelle

Nachdem wir also nun die Rubriken in eine eigene Tabelle ausgelagert haben, möchten wir diese wieder mit der Ursprungstabelle verknüpfen. Hierzu verknüpfen wir die Textfelder der Ursprungs- mit der Rubriken-Tabelle und fügen in die Ursprungstabelle in ein neu erstelltes Feld die ID der Rubrik ein:

UPDATE daten d
SET d.`daten_rubriken-id` = (SELECT r.id FROM daten_rubriken r WHERE r.rubrik = s.rubrik)

Tags: , ,
Labels: Allgemein

1 Kommentar | neuen Kommentar verfassen

Dienstag, 6. November 2007

Mediawiki mit kurzen und schönen URLs

Mediawiki kann über äusserst hässliche URLs wie http://wiki.domain.tld/index.php?title=Startseite oder aber über kurze und schöne URLs in der Form http://wiki.domain.tld/Startseite angesprochen werden.

Wie? Folgende Kurzanleitung soll mir (und allen anderen Leuten da draussenTM) für zukünftige Installationen als Gedankenstütze dienen:

.htaccess

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule  ^(.+)  /index.php?title=$1  [L]

LocalSettings.php

$wgArticlePath = "/$1";
$wgUsePathInfo = false;

Übrigens: Wenn ich in solchen Momenten den Code dieses Wiki-Systems näher betrachte, frage mich immer wieder, wie Wikipedia mit einem solchen Murks gross werden konnte.

Welches Wiki überzeugt?

Auf der Arbeit an der Uni verwende ich TWiki (Kurzkritik: Perl *wäh*, simple Dateistruktur, GUI unübersichtlich); auf der Arbeit in der Privatwirtschaft Atlassian Confluence. Dieses gefällt mir von all den Wikis da draussen bisher am meisten. Leider kostet es auch einen saftigen Batzen :-/

Tags:
Labels: Linux, Web

Keine Kommentare | neuen Kommentar verfassen