In den letzten Tagen hat Christoph Krebs fleißig weiter gelesen und noch ein paar kleinere Fehler im Text gefunden. Vielen Dank Christoph!

Seite 256:
Auf Seite 256 findet sich diese Zeile bei der natürlich ein „s“ in „Klas(s)en“ fehlt: „[…] gibt es einige Klasen im PEAR-Framework […]“

Seite 258/259:
In der Auflistung auf Seite 258 nennt sich ein Verzeichnis in der Auflistung „configs“, auf Seite 259 gibt es einen Ordner „config“. Dort fehlt leider ein „s“ am Ende. Korrekt wäre auch hier „configs“

Seite 265:
Auf Seite 265 fehlt bei dem {$name|spacify:“&nbsp“} natürlich ein Semikolon nach dem &nbsp. Korrekt wäre also {$name|spacify:“ “}

Seite 268:
Hier ist einiges schief gelaufen… Als Beispiel für den Modifikator date_format finden sich dort die folgenden Zeilen:

PHP-Datei
$smarty=new MySmarty;
$smarty->display(‚template.tpl‘);

template.tpl
{$smarty.now|date_format:“}

Ausgabe
Hallo Welt

Zuerst fehlt nach dem date_format zuerst mal die Formatangabe wie das Datum formatiert werden soll. Das heißt nach dem date_format müsste eine Angabe wie z.B. „%d.%m.%Y“ um das Datum eines Tages auszugeben. Die Ausgabe lautet dann natürlich auch nicht „Hallo Welt“ sondern beispielsweise „15.01.1999“.

Seite 278:
Auf Seite 278 findet sich die Zeile

Wie gesagt sind die Funktionsweise von {section} und foreach} recht ähnlich,

am Anfang des dritten Absatzes. Heir fehlt eine geschweifte Klammer vor dem foreach}.

Seite 408:
In der zweiten Zeile des vorletzten Absatzes fehlt ein „zu erkennen“. Der Satz „Sie müssen dem JavaScript-DOM-Ausdruck nur ein dom= voranstellen, und schon ist Selenium in der Lage, dass es sich um DOM handelt.“ müsste natürlich so lauten: „Sie müssen dem JavaScript-DOM-Ausdruck nur ein dom= voranstellen, und schon ist Selenium in der Lage zu erkennen, dass es sich um DOM handelt.“

Christoph Krebs ist ein Mensch der Bücher erschreckend genau lesen kann. Die Fehler die er gefunden hat haben mich wirklich beeindruckt, muss ich zugeben. Freundlicherweise hat er mir eine Mail mit seinen Funden geschickt, sodass ich sie an Euch weitergeben und in der nächsten Auflage korrigieren kann. Vielen Dank Christoph!

Hier seine Funde:

Das Beispiel auf Seite 46 soll diese Ausgabe generieren:

array(4) {
 [0]=>
 int(1)
[]
}

Korrekt wäre aber diese Ausgabe:

array(4) {
 [0]=>
 int(5)
[]
}

Auf Seite 88 findet sich diese Zeile

while (false === ($zeile = mysql_fetch_assoc($erg))) {

die so natürlich keinen Sinn ergibt. Im schlimmsten Fall könnte sie sogar zu einer Endlosschleife führen. Richtig wäre hier ein Ungleich:

while (false !== ($zeile = mysql_fetch_assoc($erg))) {

Auf Seite 97 ist in dem Satz

"Das heißt, hier ist sind die Abfrage und der […]"

ein „ist zu viel enthalten

Auf Seite 117 findet sich diese Fehlermeldung:

die ("Falscher Aufruf: Parameter 3 und 4 müssen Integer-Werte sein");

Leider handelt es sich aber nicht um die Parameter 3 und 4 sondern um die Parameter 2 und 3.

Auf Seite 120 fehlt in dieser Zeile ein s da die Variable natürlich $sql heißen müsste:

$erg = mysql_query($ql, $db);

Auf Seite 129 habe ich einen Fehler in einen Kommentar eingebaut. Der Kommentar in der Klasse ShoppingCart sollte nicht

// Deklaration der Eigenschaften

sondern

// Deklaration der Methoden

heißen

Auf Seite 191 unten steht

"Die Methode bindet dann eine Klassendatei mit dem Namen db_mysql.php ein, […]"

was natürlich nicht korrekt ist. Die Namen der Dateien die eingebunden werden haben noch ein „class“ in der Mitte, sodass der Dateiname „db_mysql.class.php“ lautet.

Auf Seite 222 fehlt im vierten Absatz das Wort „die“ in dem Satz „Sollte es das Verzeichnis mit der externen Bibliothek betreffen, dann schreiben Sie Meldung in ein Logfile.“

In der dritten Auflage habe ich auf Seite 142 bei dem Beispiel mit dem Setter für die Temperatur leider einen Fehler eingebaut.
Dort findet sich diese if-Abfrage:
if (0 > $neue_temp)
Da ist das Größer-Als-Zeichen natürlich falsch. Ein Kleiner-Als-Zeichen wäre korrekt. Das heißt, die if-Abfrage müsste so lauten:
if (0 < $neue_temp)
Vielen Dank an Martin Riedel, der den Fehler gefunden und mich darauf hingewiesen hat.

Am 17.04.09 hat Timo Furrer mir eine Mail geschrieben, in der er mir mitteilte, dass er einige Fehler gefunden hat, die sonst noch niemand entdeckt hatte (zumindest niemand der mir geschrieben hat 😉 ).

Das erste Problem findet sich auf Seite 763, bzw. beginnt es da. Hier wird die Normalisierung von Tabellen erläutert. Bei der Normalisierung hat sich dann aber leider ein kleiner Fehler eingeschlichen. Die ursprüngliche Tabelle, die normalisiert werden soll lautet so:

ID Name Strasse Ort Kinder
1 Meiser Am Wühlwasser 12 33125 Paderborn Gerd 12
Hans 13
2 Müller Gottesberg 1 33119 Paderborn Paula 17
Josy 12
3 Görgens Willemstraße 14 22104 Hamburg

Bei den folgenden Tabellen heißt das älteste Kind von Herrn oder Frau Müller dann aber nicht mehr Paula sondern Gerd, was natürlich falsch ist. Davon sind die Tabellen 9.41, 9.43 und 9.46 betroffen.

Auf Seite 768 füge ich Daten in die Tabelle aenderungen ein und schreibe dann, dass die Spalte aenderungen automatisch ergänzt wird. Die Spalte heißt aber nicht aenderungen sondern nur aenderung.

Auch auf Seite 808 findet sich ein Fehler im Text. In der ersten Zeile auf der Seite steht „Um sowohl bei einem UPDATE als auch bei einem BACKUP einen Backup…“. Korrekt wäre hier allerdings „Um sowohl bei einem UPDATE als auch bei einem DELETE einen Backup…“

Vielen Dank an Timo Furrer

Gestern erreichte mich eine E-Mail in der Steven Lüttig mich freundlicherweise darauf hingewiesen hat, dass ich in der dritten Auflage auf Seite 603 einen Fehler eingebaut habe. In der vorletzten Zeile auf der Seite habe ich start_session() geschrieben. Korrekt wäre natürlich session_start(), wie ich es auch im Listing davor korrekt geschrieben habe.
Leider ist das Verwechseln von session_start() und start_session() wirklich mein absoluter „Lieblingsfehler“ bei der Arbeit mit PHP. Irgendwie schreibe ich das ständig falsch herum. Sorry for inconvenience…
Oh, korrekterweise muss man sagen, dass der Fehler nicht nur die dritte Auflage sondern auch die erste und zweite Auflage betrifft. Der ist nämlich schon immer da. Leider habe ich gerade kein Exemplar der ersten Auflage da, aber in der zweiten Auflage ist der Fehler auf Seite 509 im dritten Absatz in der ersten Zeile.
Vielen Dank an Steven Lüttig für den Hinweis auf den Fehler.

Es gibt so Sachen die macht man unwissentlich immer richtig und wundert sich dann plötzlich dass nichts mehr geht wenn man es mal anders macht. Letzte Woche hatte ich wieder so einen Fall. Es handelte sich um ein recht banales SQL-Statement, das allerdings in einer unschönen Fehlermeldung resultierte…

Das eigentliche Statement war so eins wie dieses hier:

SELECT * FROM blog WHERE datum > now();

Zumindest hätte es das sein sollen. Allerdings hatte ich ein Leerzeichen nach dem now getippt, sodass sich ein solches Statement ergab:

SELECT * FROM blog WHERE datum > now ();

Durch das Leerzeichen ist MySQL leider nicht mehr in der Lage das now() zu erkennen. Daher liefert MySQL nur einen Fehler wie diesen zurück:
ERROR 1305 (42000): FUNCTION test.now does not exist

Dieses Beispiel liefert übrigens auf MySQL 5.0 und 5.1 einen Fehler.
Interessant ist allerdings, dass das Statement das ich genutzt habe auf dem Entwicklungsserver funktionierte, das Live-System aber eine Fehlermeldung lieferte. MySQL 5.1 (Entwicklungsserver) scheint da (zumindest bei einigen Funktionen) nicht ganz so streng zu sein wie MySQL 5.0, das auf dem Live-System genutzt wird. Das kann man an diesem Beispiel ganz schön sehen. Was mit MySQL 5.1 funktioniert:

mysql> SELECT version();
+-------------+
| version()   |
+-------------+
| 5.1.16-beta | 
+-------------+
1 ROW IN SET (0.00 sec)
 
mysql> SELECT date_format (now(), '%d.%m.%Y');
+---------------------------------+
| date_format (now(), '%d.%m.%Y') |
+---------------------------------+
| 17.02.2009                      | 
+---------------------------------+
1 ROW IN SET (0.00 sec)

liefert in MySQL 5.0 nur einen Fehler:

mysql> SELECT version();
+--------------------+
| version()          |
+--------------------+
| 5.0.51a-3ubuntu5.4 | 
+--------------------+
1 ROW IN SET (0.00 sec)
 
mysql> SELECT date_format (now(), '%d.%m.%Y');
ERROR 1305 (42000): FUNCTION test.date_format does NOT exist

Also immer schön darauf achten, dass vor dem Klammerpaar kein Leerzeichen steht, dann hat man auch kein Problem 😉

Auch auf Seite 118 (Kapitel 4.2.1) hat sich leider noch ein Fehler eingeschlichen. Und zwar prüfe ich hier mithilfe des Operators instanceof ob $obj eine Instanz der Klasse 'klasse' ist. Ungefähr auf der Mitte der Seite findet sich diese Zeile:

if ($obj instanceof 'klasse')

Das ist leider nicht korrekt. Der Name der Klasse darf bei der Nutzung instanceof nicht in Anführungszeichen (Gänsefüßchen, Hochkommas etc.) gesetzt werden. Nutzt man die Zeile so wie Sie im Buch steht, dann quittiert PHP das mit dieser Meldung:

...syntax error, unexpected T_CONSTANT_ENCAPSED_STRING, 
   expecting T_STRING or T_VARIABLE or '$' in...

Die Zeile müsste also eigentlich so lauten:

if ($obj instanceof klasse)

Vielen Dank an Ralf Oltmanns, der diesen Fehler gefunden und sich bei mir gemeldet hat.
[edit] Fehler korrigiert die Marko gefunden hatte. Vielen Dank für den Hinweis, Marko 🙂

Gestern bekam ich eine Mail in der ein Leser fragte wie man denn an solchen Vorträgen teilnehmen kann wie sie auf der DVD zum Buch enthalten sind. Daher wollte ich da noch ein paar Dinge zu anmerken.

Multimediatreff

Die Vorträge die auf der DVD enthalten sind, sind auf einem Multimediatreff in Köln entstanden. Der Multimediatreff ist eine kostengünstige Veranstaltung, die mehrmals im Jahr stattfindet. Üblicherweise sind die Referenten wirklich sehr gut und auch die Verpflegung ist vortrefflich. dazu kommt noch, dass man da viele spannende Menschen treffen kann. Weitere Informationen dazu gibt’s hier: http://www.multimediatreff.de

Barcamps und Unkonferenzen

Eine weitere tolle Sachen wenn man spannende Menschen kennenlernen und etwas lernen möchte sind Barcamps. Bei Barcamps handelt es sich um „kostenlose Konferenzen“. Das heißt, ein Haufen Menschen der Interesse an einem Thema hat trifft sich irgendwo in Deutschland (meist für ein ganzes Wochenende) und jeder der möchte kann einen Vortrag halten. Die Qualität der Vorträge ist dabei meist ein wenig unterschiedlich aber die Veranstaltungen lohnen sich auf jeden Fall. Informationen zu Barcamps gibt es bei Wikipedia http://de.wikipedia.org/wiki/BarCamp und die Frage wo das nächste Barcamp stattfindet kann man mithilfe von http://www.barcamp.org klären.
Barcamps sind eigentlich eine „Unconference“. Eine Unconference hat eigentlich dieselbe Idee nur einen anderen Namen. Auch da gibt es viele spannende Veranstaltungen. Meist sind Unconferences aber ein wenig spezieller und das Niveau ist höher als bei einem normalen Barcamp. Lohnenswert sind besonders die PHP Unconference (http://www.php-unconference.de)

Usergroups, Webmontage & Co.

In den meisten größeren Städten gibt es auch noch Usergroups zu allen möglichen Themen. Bei einer Usergroup handelt es sich um einen Haufen Leute die sich meist ein Mal pro Monat treffen und sich zu einem bestimmten Thema austauschen. Zugegebenermaßen ist der „Haufen“ meist nicht ganz so groß (hier und da sind auch schon zwei Leute eine Usergroup) aber auch diese Treffen können sich lohnen. Ob bei solchen Treffen Vorträge gehalten werden oder ob man nur ein Bier zusammen trinkt variiert immer ein wenig.
In vielen Städten gibt es auch noch Webmontage. Die Idee ist dabei ähnlich wie bei einer Usergroup nur dass man sich etwas allgemeiner über das Thema Internet unterhält. Allerdings ist es meist so, dass auf den Webmontagen mehr Vorträge gehalten werden.
Teilweise finden sich auch noch lokale Gruppen des CCC oder anderer Vereine. Einfach mal nach Webmontagen, Usergroups etc. googlen.

Auf dem Laufenden bleiben…

Bei der Vielzahl der Veranstaltungen und der Dynamik der Szene ist es immer ein wenig schwierig auf dem Laufenden zu bleiben was gerade wo stattfindet. Daher kann ich nur empfehlen, wenn man das ein oder andere Blog liest. Einige der bekannten PHPler sind auf vielen Konferenzen / Veranstaltungen zu finden und das dokumentieren sie dann auch meist im eigenen Blog. Also immer fleißig Blogs lesen 😉

Bestimmt habe ich hier noch ein paar Veranstaltunge vergessen (z.B. die FrOSCon oder das PHP Vikinger) aber ich glaube wenn man die ganzen Sachen die ich hier genannt habe mitnimmt, dann hat man schon eine ganze Menge zu tun 😉

In der dritten Auflage von „Besser PHP programmieren“ ist auf den Seiten 137 und 138 ein gewisses Durcheinander mit den Konstruktoren entstanden. Der Hintergrund ist, dass PHP 4 noch vorgesehen hat, dass der Konstruktor eine Methode ist welche denselben Namen hat wie die Klasse. In PHP 5 funktioniert das zwar auch noch aber ein Konstruktor sollte in PHP 5 den Namen __construct() haben.

Die vorhergehenden Auflagen von „Besser PHP programmieren“ bezogen sich noch auf PHP 4. Bei der Übernahme der Texte für die neue Auflage habe ich auf den Seiten 137 und 138 leider ein paar Sachen mit den Namen der Konstruktoren durcheinander gebracht.

In Listing 4.5 sollte der Konstruktor den Namen __construct() haben und nicht kunde(). Zwar wäre es nicht unbedingt falsch den Konstruktor kunde() zu nennen aber es ist halt PHP 4 und nicht 5. Hier nochmal das Listing 4.5 in einer korrekten Version:

class Kunde extends Kontakt
{
   var $anrede; // die zusätzlichen Eigenschaften
   var $email;
   function __construct ($anrede,$name,$telefon,$email) // Konstruktor
   {
      parent::__construct($name,$telefon); // Konstruktor der Basisklasse aufrufen
      $this->anrede=$anrede; // neue Eigenschaften zuweisen
      $this->email=$email;
   }
   function zeigeAn() // zeigt alle Daten an
   {
      echo "Anrede: $this->anrede <br />"; // Anrede ausgeben
      parent::zeigeAn(); // zeigeAn aus der Basisklasse aufrufen
      echo "<br />E-Mail: $this->email"; // E-Mail ausgeben
   }
}

Des Weiteren findet sich in der Erläuterung des Konstruktors auf Seite 138 diese Zeile:

parent::kontakt($name, $telefon);

Das ist natürlich falsch. Im Code, in Listing 4.5, ist die Zeile korrekt. Das heißt, hier müsste eigentlich

parent::__construct($name, $telefon);

stehen…

Leider hat die Fehler niemand bemerkt bevor das Buch in Druck gegangen ist. Eigentlich ist es ja immer wieder erstaunlich, dass niemand einen solchen Fehler bemerkt. Ich selbst habe den Text geschrieben und mehrfach gelesen. Dann haben ihn noch der Gutachter, der Lektor und die Korrektorin gelesen aber niemandem ist das aufgefallen. Vielen Dank an José Stiller der diesen Fehler gefunden und mir eine Mail geschrieben hat.

Weitere Informationen zu Konstruktoren in PHP 4 und 5 gibt es hier

Eine der Änderungen die sich von PHP 4 nach PHP 5 ergab war, dass die Konstruktoren von Klassen anders zu benennen sind. Der Konstruktor, also die Methode die automatisch ausgeführt wird, wenn eine Klasse instanziiert wird, musste in PHP 4 denselben Namen haben wir die Klasse selbst. In PHP 5 ist der Konstruktor aber anders zu bennen. Die Methode muss den Namen __construct() haben. Eine Klasse foo müsste in PHP 4 also so aussehen:

class foo
{
   function foo ()
   {
      echo "Ich bin der Konstruktor";
   }
}

die PHP 5 Variante sieht so aus:

class foo
{
   public function __construct ()
   {
      echo "Ich bin der Konstruktor";
   }
}

In beiden Varianten würde der Text Ich bin der Konstruktor ausgegeben, wenn ein neues Objekt der Klasse instanziiert wird. Die PHP 4-Variante kann übrigens auch mit PHP 5 ausgeführt werden. Um eine bessere Abwärtskompatibilität zu gewährleisten kann PHP 5 also mit Konstruktoren in beiden Varianten umgehen.

Jetzt stellt sich aber die interessante Frage wie eine Klasse sich verhält, wenn Konstruktoren in beiden Varianten da sind. Würde die Klasse mit PHP 4 ausgeführt, dann ist das (vielleicht) kein Problem, da PHP 4 den Konstruktor __construct() nicht kennt. Allerdings dürfte die Methode __construct() dann nicht als public function __construct() deklariert werden, sondern nur als function __construct(), da PHP 4 dieses Schlüsselwort och nicht kennt. Aber was passiert mit PHP 5? Wird ein Objekt dieser Klasse instanziiert, dann wird nur die PHP 5 Variante ausgeführt:

class foo
{
   public function foo ()
   {
      echo "Ich bin der PHP 4 Konstruktor";
   }
   public function __construct ()
   {
      echo "Ich bin der PHP 5 Konstruktor";
   }
}

Das heißt, es wird nur der Text Ich bin der PHP 5 Konstruktor ausgegeben. War eigentlich zu erwarten, oder? Interessant wird es aber, wenn die beiden Varianten gemischt werden, beipsielsweise enn die eine Klasse ein Elter ist und die andere Klasse abgeleitet ist. Diese Variante führt zu einem Fatal Error:

class foo
{
   public function __construct ()
   {
      echo "Ich bin der PHP 5 Konstruktor";
   }
}
 
class bar extends foo 
{
    public function bar()
    {
        parent::foo();
    }
}
 
new bar();

Logisch, die Methode foo() ist in der Superklasse ja auch nicht deklariert. Diese Version funktioniert insteressanterweise aber:

class foo
{
   public function foo()
   {
      echo "Ich bin der PHP 4 Konstruktor";
   }
}
 
class bar extends foo 
{
    public function bar()
    {
        parent::__construct();
    }
}
 
new bar();

Kurios, wie ich finde. Aber so ist PHP halt 😉