Errata for Learning PHP, MySQL, and JavaScript

The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

Example does not define $day_number.
<?php
$day_number = date("z"); // This is today's day number
$days_to_new_year = 366 - $day_number;
if ($days_to_new_year < 30)
{
echo "Not long till new year";
}else {
echo "We have a way to go till the end of the year.";
}
?>

Note from the Author or Editor:Yes, you would set $day_number to a value (such as 350) before executing the example, like this:
$day_number = 350;
$days_to_new_year = 366 - $day_number;
if ($days_to_new_year < 30)
{
echo "Not long now till new year";
}

Phil Cyphers

Feb 25, 2013

Printed

Page 72
Example 4-19

$money += 1000;
should be:
$money = 1000;

George

Apr 26, 2012

PDF

Page 82
3rd paragraph from bottom

The terminating condition in the for loop is:
$i + $j < 10
but in the analysis of this loop it appears as:
$i + $j < 1

Note from the Author or Editor:The three example lines at the foot of page 82 should be as follows (the middle line should be $j < 10, not $j < 1):
$i = 1, $j = 1 // Initialize $i and $j
$i + $j < 10 // Terminating condition
$i++ , $j++ // Modify $i and $j at the end of each iteration

razorbill

Nov 30, 2010

Feb 01, 2011

PDF

Page 84
Example 4-36

In the final closing tag '?' is missing, i. e. should be "?>".

Vadim Flyagin

Oct 07, 2011

PDF

Page 103
2nd paragraph from below

--printed--
copies the property values from the original class to the new instance.
--should be--
copies the property values from the original instance to the new instance.

Note from the Author or Editor:With PHP 5.3 running in strict mode you have to make the function within the class static.

Anonymous

Aug 31, 2010

Nov 01, 2010

PDF

Page 118
bottom of the page

--printed--
echo $p1['inkjet']; // Undefined index
echo $p2['3']; // Undefined offset
--should be--
In the second line single quotes near number 3 must be deleted. For they will produce another kind of error: "Undefined index", instead of "Undefined offset". Also, in the first line "Inkjet" would be better then "inkjet", because in the previous example 6.5 array $p1 has "Inkjet" element, but not "inkjet".

Vadim Flyagin

Dec 03, 2011

Printed

Page 122
Example 6-11

Sorry to be pedantic, but if your depiction of a chessboard is to follow the usual convention of white pieces starting at the bottom of the board, you need to swap round the King and Queen positions.
;-)

john maguire

Sep 26, 2011

Printed

Page 122
Example 6-11

In Example 6-11 on page 122 there are 10 rows instead of 8 in the array used to construct a chessboard. Two of the blank rows should be removed from the middle.

I think in line 3 the "Display precision" value ".2" should be assign to line 2 and value ".4" in line 2 should be assign to line 3.

Note from the Author or Editor:On page 132, in Table 7-2, the .4 and .2 in the 'Display precision' column should be swapped.

Anonymous

Oct 11, 2009

Feb 01, 2010

PDF

Page 135
Table 7-4, under "Week specifier"

--printed--
Week number of year 1 to 52
--should be--
Week number of year 01 to 52

Vadim Flyagin

Jan 21, 2012

Printed

Page 136
DATA_COOKIE example

The 'l' format specifier implies that the day should be output as 'Thursday'
and not 'Thu' as shown.
Also hyphens are shown in the format specifier but not in the example output.
Which is the correct format for DATA_COOKIE format?

The book says:
"...by setting the mode with '+r', which puts..."
It should say:
"...by setting the mode with 'r+', which puts..."

razorbill

Dec 10, 2010

Feb 01, 2011

Printed

Page 142
Example 7-12

The command fseek($fh, 0, SEEK_END); must be moved to become the first statement inside the following if statement to ensure it also benefits from the file locking. The corrected example should look like:
<?php
$fh = fopen("testfile.txt", 'r+') or die("Failed to open file");
$text = fgets($fh);
if (flock($fh, LOCK_EX))
{
fseek($fh, 0, SEEK_END);
fwrite($fh, "$text") or die("Could not write to file");
flock($fh, LOCK_UN);
}
fclose($fh);
echo "File 'testfile.txt' successfully updated";
?>

Note from the Author or Editor:Summary: In some cases if you do not have a password set and are using MySQL as the root user, then you can enter it by using both the -u root and -p options, and simply pressing Enter when prompted for the password.

Damian

Feb 07, 2011

Printed

Page 166
After the first paragraph

Instead of GRANT ALL ON publications.* TO 'jim' IDENTIFIED BY 'mypasswd';
Following is the correct syntax, as recommended at http://dev.mysql.com/doc/refman/5.1/en/adding-users.html:
GRANT ALL ON publications.* TO 'jim'@'localhost' IDENTIFIED BY 'mypasswd';

Example 9-9 should include "use publications;" statements after both startings of the mySql command line environment, and semicolons at the end of each mySql command.

Note from the Author or Editor:The section on page 221 that reads as follows is not quite correct, since the publications table is not selected before issuing the LOCK command, and it can also be much simplified:
Should you wish to back up only a single table from a database
(such as the classics table from the publications database), you
could use a sequence of commands such as those in Example 9-9, in
which you simply follow the database name with that of the table
to be backed up.
I've assumed here that you haven't shut down the MySQL server.
You're letting it run while you back up the classics table, but
you lock that single table during the backup so that no one can
access it.
Example 9-9. Dumping just the classics table from publications
$ mysql -u user -ppassword
mysql> LOCK TABLES classics READ
mysql> QUIT
$ mysqldump -u user -ppassword publications classics > classics.sql
$ mysql -u user -ppassword
mysql> UNLOCK TABLES
mysql> QUIT
The replacement text for these two paragraphs and Example 9-9 is as follows:
To back up only a single table from a database (such as the
classics table from the publications database), you should first
lock the table from within the MySQL command line, by issuing a
command such as the following:
LOCK TABLES publications.classics READ
This ensures that MySQL remains running for read purposes, but
writes cannot be made. Then, while keeping the MySQL command line
open, use another terminal window to issue the following command
from the operating system command line:
mysqldump -u user -ppassword publications classics > classics.sql
You must now release the table lock by entering the following
command from the MySQL command line, which unlocks all tables
that have been locked during the current session:
UNLOCK TABLES

Title of this example should read:-
Connecting to a MySQL server
rather than a database.

john maguire

Sep 26, 2011

Printed

Page 227
bottom of page in note re: function mysql_fatal_error

in line 3 of example:
$msg2 - mysql_error();
should be:
$msg2 = mysql_error();

sdguy

Nov 09, 2009

Feb 01, 2010

Printed

Page 231
Example 10-7

The title of example 10-7 should be
Closing a MySql server connection
although it does by implication also close the database.

john maguire

Sep 26, 2011

Printed

Page 233
Start of page

The listed example does not correctly handle deleting an entry and the entire code should be replaced with the following:
<?php // sqltest.php
require_once 'login.php';
$db_server = mysql_connect($db_hostname, $db_username, $db_password);
if (!$db_server) die(

The section that begins "But there's a slight window of opportunity" should be ignored. After having spent a lot of time researching the reports on the web about this, none of those I looked at were actually bugs in MySQL, and were instead bugs in the programmer's code. Therefore I will lay this one to rest and say that there is not a problem in MySQL with mysql_insert_id() and race conditions.

Note from the Author or Editor:The <form method... /> statement in Example 11-1 should not have the self-closing /> tag, and should therefore read:
<form method="post" action="formtest.php">
However, since self-closing is not supported by the <form> tag, this typo should not affect the behavior of the HTML.

In the first paragraph of page 266 the author writes down the formula for converting from Celsius to Fahrenheit.
According to him, the formula is "Fahrenheit = (9/5) * (Celsius +32).
I have tested back an forth, and I think the correct way of writing it would be like this:
"Fahrenheit = ((9/5) * Celsius) + 32"

Haavard

Oct 22, 2011

Printed

Page 271
The final line of Example 12-1

Because the path to the template files is already known, the final line of Example 12-1, which reads
$smarty->display("$path/temp/index.tpl");
Should be replaced with:
$smarty->display("index.tpl");

The directory structure above the heading says to create a directory named 'config' should be named 'configs' according to the install readme from Smarty and the code examples within this chapter.

Garry Freemyer

May 17, 2010

Nov 01, 2010

Printed

Page 274
The fifth line from the bottom of Example 12-3

Because the path to the template files is already known, the fifth line from the bottom of Example 12-3, which reads:
$smarty->display("$path/temp/smartytest.tpl");
Should be replaced with:
$smarty->display("smartytest.tpl");

Calling setcookie() after echo causes the following warning:
Warning: Cannot modify header information - headers already sent by (output started at C:\web\lpmj.examples\named_examples\continue.php:36) in C:\web\lpmj.examples\named_examples\continue.php on line 47

Note from the Author or Editor:The section of code which reads as follows:
echo "Welcome back $forename.<br />
Your full name is $forename $surname.<br />
Your username is '$username'
and your password is '$password'.";
destroy_session_and_data();
Should be changed so that the call to destroy_session_and_data() comes first, like this:
destroy_session_and_data();
echo "Welcome back $forename.<br />
Your full name is $forename $surname.<br />
Your username is '$username'
and your password is '$password'.";

Ron Inbar

Aug 21, 2010

Nov 01, 2010

Printed

Page 303
Table 14-1

Note from the Author or Editor:On Page 303 in Table 14-1, the entry that reads:
"Safari does not have an Error Console enabled by default, so the Firebug Lite JavaScript module will do what you need."
should be changed to
"Safari does not have an Error Console enabled by default, but you can turn it on by selecting Safari->Preferences->Advanced->Show Develop menu in menu bar. However, you may prefer to use the Firebug Lite JavaScript module which many people find easier to use."

Benjamin Westafer

Aug 17, 2009

Nov 01, 2010

Printed

Page 313-314
Example 14-11 , Example 14-12 and top of page 314

Note: Second time posting this errata.
You can not pass an undefined variable as an argument to a function.
The comment on page 314, "If your browser issues a warning about b being undefined, the warning is correct but can be ignored." is not accurate. An error is generated not a warning.
To confirm this is true, in script Example 14-12 reverse the following statements:
if (isset(a)) document.write('a = "' + a + '"<br />')
if (isset(b)) document.write('b = "' + b + '"<br />')
to:
if (isset(b)) document.write('b = "' + b + '"<br />')
if (isset(a)) document.write('a = "' + a + '"<br />')
Now when you execute this script, no output will be generated, instead an error is generated in the JavaScript/error console.
In Chromium 9, the following error message is generated:
Uncaught ReferenceError: b is not defined.
In Firefox 13.6, the following error message is generated:
b is not defined

In order for the sample code to produce the output described in the follow up paragraph the following code statements:
if (a > b) document.write("a is greater than b<br />")
if (a < b) document.write("a is less than b<br />")
if (a >= b) document.write("a is greater than or equal to b<br />")
if (a <= b) document.write("a is less than or equal to b<br />")
need to be changed as follows:
if (a > b) document.write(a + " is greater than " + b + "<br />")
if (a < b) document.write(a + " is less than " + b + "<br />")
if (a >= b) document.write(a + " is greater than or equal to " + b + "<br />")
if (a <= b) document.write(a + " is less than or equal to " + b + "<br />")

Note from the Author or Editor:the output following Example 15-6 on page 324 should be changed from this:
7 is less than 11
7 is less than or equal to 11
To the following
a is less than b
a is less than or equal to b

Ken Wilson

Oct 24, 2009

Feb 01, 2010

PDF

Page 325
Example 15-9

In the JavaScript code:
gn = getnext()
if (finished == 1 OR gn == 1) done = 1;
there should be "||" instead of "OR".

Tigran

Jul 16, 2012

Printed

Page 326
Example 15-11

"onError" should be all lowercase, i.e. "onerror". JavaScript is case sensitive.

Note from the Author or Editor:

Ken Wilson

Oct 24, 2009

Feb 01, 2010

Printed

Page 350
Top of page

The out at the top of this page should be:
Element at index 0 has the value Cat
Element at index 1 has the value Dog
Element at index 2 has the value Rabbit
Element at index 3 has the value Hamster

Note from the Author or Editor:Example 16-11 was modified late in the copy edit stage to clarify the difference between indexes and elements held in indexes. Therefore the output shown from the modified example should include the extra words "at index". This does not affect the working of the example or the explanation of its function.

Hongjiang Li

Jul 04, 2010

Nov 01, 2010

PDF

Page 353
2nd paragraph

Written:
"If the function returns a value greater than zero, the sort assumes that a comes before b. If the function returns a value less than zero, the sort assumes that b comes before a."
In fact it is vice versa:
"If the function returns a value greater than zero, the sort assumes that a comes AFTER b. If the function returns a value less than zero, the sort assumes that b comes BEFORE a."
Also if the function returns 0, a and b remain unchanged with respect to each other.

Tigran

Jul 16, 2012

Printed

Page 360
1st paragraph.

I just submitted an error where I thought code on page 358 was incorrect but it is the text description that is incorrect not the code.
The description of the function code in the first paragraph of page 360 is "If even one character that isn't one of the acceptable characters is encountered, the test function returns FALSE. and so validateUser returns an error string."
The word in all caps above should actually be true, not false in keeping with the code.

Note from the Author or Editor:The sentence at the top of page 360 which goes "If even one character that isn't one of the acceptable characters is encountered, the test function returns false. and so validateUser returns an error string.", should be replaced with the following:
"If even one character that isn't one of the acceptable characters is encountered, the test function returns true, and so validateUser returns an error string."

Second sentence "Within these slashes, certain characters have special meanings; there are called metacharacters." should change "there" (after semicolon) to "they".

Russell Stringham

Aug 04, 2010

Nov 01, 2010

Printed

Page 365 and 366
figure 17-3 and 17-4

First slash is in the wrong direction on the figure.
It is correct in the rest of the explanation

Note from the Author or Editor:On page 365 of the printed edition, the first character in Figure 17-3 is shown as a \, but it should be a /. The same goes for the first character of Figure 17-4 which should be a /.

Anonymous

Jan 01, 2010

Feb 01, 2011

Printed

Page 368
Table 17-2

The fourth example in Table 17-2, rec(ei)|(ie)ve, should be: rec(ei|ie)ve.

In table 17-2, example:
a-f Matches any of the characters a,b,c,d,e or f
the a-f should be in square brackets:
[a-f]

Note from the Author or Editor:You would place such sequences within square brackets so I agree it would be better to show them in the table.

jteeters

Apr 15, 2010

Nov 01, 2010

Printed

Page 381-384

I downloaded code for Examples 18-2 and 18-3. It simply does not work in Google Chrome, Firefox or IE.
With GC and FF, I get an error message "Ajax error". After running the unaltered code, I changed it slightly. By changing the text of the relevant error message, I found that condition "if (this.status == 200) is not met. This change to the text of 18-2 was necessary because "this.statusText" does not display in the alert box. Without this modification on my part, I would have been unable to determine if the problem was with the this.status or the this.responseText condition was the problem.
What is the solution? Thanks.

Note from the Author or Editor:Ajax must be run on a server with a valid domain and cannot simply be loaded from a local filesystem. This is because of all the security built around Ajax to prevent cross site scripting attacks.

Anonymous

Jan 04, 2013

Printed

Page 382
2nd paragraph

The line "After this, the open method is called to set the object to make a POST request to geturl.php in asynchronous mode." Does not correspond with the code on page 381 where it is listed as:
request.open("POST", "urlpost.php", true)
The 'geturl.php' on page 382 needs to be replaced with 'urlpost.php'

Anonymous

Aug 12, 2010

Nov 01, 2010

Printed

Page 397
Just after heading "The YUI asnynRequest method

The line in bold after '"The syntax is:" should conclude with
...callback, [ 'parameters...'] rather than
...callback [, 'paramaters...']. In other words, the first comma and the first square bracket are juxtaposed.
I discovered this in writing Example 19-1 using the POST method.

Note from the Author or Editor:...callback [, 'parameters...'] is correct.
It means that the code within the [ ] brackets is optional, but if you choose to use it there must be a comma then the parameters. If you place the comma and don't provide a parameter following you may get unpredicted results, so the comma is omitted unless a parameter is to be added.

Jim Holmberg

Jan 10, 2013

Safari Books Online

409
Example 20-2 rnheader.php

In the file rnheader.php, it is necessary to place the "session_start()" statement before the "include 'rnfunctions.php" statement in order to have the example work properly.
This is probably due to the fact that "rnfuctions.php" introduces html code.

Note from the Author or Editor:Thanks for pointing this out. rnsetup.php had a single HTML message added that ended up requiring this fix. The alternative solution would be to remove the command "echo '<h3>Setting up</h3>';" from rnsetup.php.

Josť Fournier

Feb 24, 2010

Printed

Page 415
Near the end of example 20-5

The section of code that reads:
else
{
$query = "INSERT INTO rnmembers VALUES('$user', '$pass')";
queryMysql($query);
}
die("<h4>Account created</h4>Please Log in.");
Should actually be as follows...
else
{
$query = "INSERT INTO rnmembers VALUES('$user', '$pass')";
queryMysql($query);
die("<h4>Account created</h4>Please Log in.");
}
This is not a serious problem but, without the modification, it will display an incorrect success message instead of an error if you try to create a user that already exists.

Note from the Author or Editor:Although not an error the reader makes a useful suggestion to change the type of the user input from text to password. I had left it as text so that the user could see what was happening, but on reflection this change to obscure the password as it is entered is better practice.

Pule Nong

Feb 28, 2010

Feb 01, 2011

Printed

Page 423
imageconvolution

Ubuntu (debian) uses the generic GD libray (as in apt-get install php5-gd). This library does not include many functions including imageconvolution - hence rnprofile.php won't run. To force PHP to use its inbuilt (forked) GD library I followed the useful post at http://cumu.li/2008/5/13/recompiling-php5-with-bundled-support-for-gd-on-ubuntu to recompile PHP from source. I suggest a footnote/instructions and a security warning to readers since many may be using Ubuntu/Debian.
Thanks for a good book.

Note from the Author or Editor:The date() function call as used displayed hh:ss (hours and seconds) instead of hh:mm (hours and minutes). To correct this it should read as follows:
echo date('M jS \'y g:ia', $row[4]);

Henry

Jan 03, 2011

Feb 01, 2011

Printed

Page 433
Example 20-13, line 2

The rnheaders.php file (included at the start) outputs html meaning that the call to destroySession() at line 7 cannot delete the cookie since headers are closed already.
I coded logout.php as follows to avoid this:
<?php // rnlogout.php
require_once 'rnfunctions.php';
session_start();
if(isset($_SESSION['user'])){
destroySession();
}
require_once 'rnheader.php';
...
Thanks for a good book.

Note from the Author or Editor:The following code should replace that for rnlogout.php, shown in the book:
<?php // rnlogout.php
include_once 'rnheader.php';
if (isset($_SESSION['user']))
{
destroySession();
echo "<h3>Log out</h3>You have been logged out. Please
<a href='index.php'>click here</a> to refresh the screen.";
}
else echo "<h3>Log out</h3>You are not logged in";
?>

matt black

Feb 18, 2010

Feb 01, 2011

Other Digital Version

10395
2nd paragraph

"The next chapter will show you how to use the Smarty templating engine..."
The Amazon Kindle edition of this book (which I purchased at URL http://www.amazon.com/dp/1449319262) seems to contain no Smarty material whatsoever, other than a URL at location 108503.
I can only conclude that a large chunk of the book is missing.

Note from the Author or Editor:Smarty was covered in Edition 1 of the book but so few readers actually used it the decision was taken to focus on an area of more interest, and so that chapter was removed to make way for one of the later chapters on CSS. Unfortunately the reference to Smarty appears not to have also been removed, please ignore that sentence.