Errata

Head First PHP & MySQL

Errata for Head First PHP & MySQL

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
Other Digital Version 25
3rd paragraph

The paragraph says "If there is any PHP code in a web page, it's a good idea to name the file on the web server with .php, not .html". Actually, it is usually required to name it .php to tell the server to parse a script. .html pages will mostly not get parsed and will return the source code of the php script instead.

Anonymous  Mar 21, 2009 
Printed Page 26
1st paragraph

The first sentence of the first paragraph on page 26 (2009 edition) uses 'are' before and after an 'also' making it a little confusing to read at first.

"In addition to starting with a $, PHP variable names are also are case-sensitive."

Don Norman  Jan 29, 2011 
PDF Page 35, 36
Code lines referring to alien_description

Reference on p. 36, 3rd line of php code is presented as the correct form field name, but is missing underscore between "alien" and "description" that is present in every other instance across these 2 pages.

Peter McDonald  Apr 18, 2009 
Printed Page 36
Solution explanation

The arrow between the text block containing "The name of the form field in report.html is..." and the called out portion of code occludes some of the text in the aforementioned text block.

Dave Solomon  May 31, 2011 
PDF Page 41
echo code

Inconsistent form field names between pages using underscores between names here but on previous pages like p. 40 there are no underscores, i.e. "what_they_did" vs. "whattheydid"

Peter McDonald  Apr 19, 2009 
Printed Page 50
The caption for the bracket under "'From:' . $email" halfway down the page

The caption says:

"The period's handy yet again for concatinating 'From:' with Owen's e-mail address."

The e-mail is supposed to going to Owen and be coming from the submitter of the form. I believe the caption should read something like the following:

"The period's handy yet again for concatinating 'From:' with the submitter's email address."

StickyJr  Sep 03, 2011 
64
SQL code on lower half of page

As with the PHP script previously noted, the SQL code on this page do not copy and paste into text editors properly (tried two).

Spaces are created, before the commas in all cases and before the numbers in some cases.

Erich Riesenberg  Jun 10, 2010 
Printed Page 67
Bubble Box next to 'sally@gregs-list.net'

In the the bubble next to sally@gregs-list.net it says that a SQL statements does not end in a semicolon when used in PHP code. However, in the PHP code in the example that follows, the $query variable that is assigned from the INSERT INTO statement ends in a semicolon. Also, when entering the code into the MYSQL terminal, the semicolon is also required. I was confused by the bubble box statement.

Jonathan  Dec 02, 2011 
Printed Page 88
Chapter 2

The fourth point on the bullet points list contains a reference to the function mysqi_query(). The correct spelling is mysqli_query()

Maristella  Oct 15, 2009 
Printed Page 128
Near the bottom

The statement:

mysqli_query($dbc,$query)

is incomplete. It needs to be:

$result = mysqli_query($dbc,$query)

XJupiter  Sep 30, 2009 
Printed Page 136
email_list graphic

The arrows connecting the queries to the $row buckets pass behind the email_list graphic with the exception of the last arrow, which passes over the graphic. It seems like it was meant to be behind like the others but the layer order get mixed up.

Dave Solomon  Jun 06, 2011 
Printed Page 152
php code

OK, I'm an ultimate newbie and have very little idea of what I'm doing...which is why I picked up this book. So far, I'm working through the examples, but I'm far from confident with what I'm doing.:-)

My question...

Up until this this point in the author has been using:

$result = mysqli_query($dbc, $query)
or die('Error querying database.');

Here though it was written without "$result = ":

mysqli_query($dbc, $query)
or die('Error querying database.');

Both ways seem to work, but for consistency, shouldn't it be shown and coded in the example as the earlier examples?

TIA

Anonymous  Nov 27, 2009 
Printed Page 152
3th line of the php code

<?php


$dbc = msqli_connect ('localhost','elmer','theking','elvis_store')
or die ('unable to connect'); //the semicolon was missing here
I must admit I didn't even saw it until I compaired my code with the one in the book ;-)


?>

epic tree climber  Jan 30, 2010 
PDF Page 152
Bottom

The Query for the Delete clase in the book:

$query = ?DELETE FROM email_list WHERE email = ?$email??;

It may not match in MySQL since the EMail field in MySQL is varchar(60) charactersand may contain extra spaces and the submitted EMail is the exact length.

I use the following line to make sure both are equal:

$query = "DELETE FROM email_list WHERE TRIM(email) = TRIM('$email') ";

Anonymous  Oct 23, 2010 
Printed Page 171
2nd IF statement

The text indicates that we want to require input to both the subject and the text fields. The 2nd IF statement only outputs an error message if both fields are blank. The IF statement should use an OR, not an AND.

DJPJ  May 28, 2009 
Printed Page 171
Validation logic statements

$_POST['elvismail'] is assigned to the variable $text, but the validation logic statements use the variable $body.

lemuel  Jun 01, 2009 
Printed Page 171
full page

The name of the email body variable is inconsistent. At the top of the page and in the problem solution, it's referred to as $text, but in the logic examples it's referred to as $body.

Also, the header and the first paragraph are duplicated word-for-word from page 165.

Carl Jonard  Jul 13, 2009 
Printed Page 171
3rd and 4th paragraphs

There are two errors on this page:

1) IF $subject contains text AND $body contains text

This should be:

IF $subject contains text AND $text contains text

2) IF $subject is empty AND $body is empty

This should be:

IF $subject is empty AND $text is empty

XJupiter  Sep 30, 2009 
Printed Page 172
sharpen your pencil

Continuation of the same problem on page 171. If you use the logic in the book as is, then if subject is blank and text is filled in, no email will be sent and no error message will be given. Same thing if subject is filled in and the text field is blank.

DJPJ  May 28, 2009 
Printed Page 173-174
Sharpen your pencil

The same logic error as on 171 and 172.

DJPJ  May 28, 2009 
Printed Page 179
third and fourth code snippets

the third and fourth code snippets read

if (empty($subject) && (!empty($text))) {

if ((!empty($subject)) && empty($text)) {

they should read instead as follows:

if ((empty($subject)) && (!empty($text))) {

if ((!empty($subject)) && (empty($text))) {

Maristella  Oct 21, 2009 
Printed Page 186
Underneath "// We know both $subject AND $text are blank"

You are missing the echo statement below the following statement:

// We know both $subject AND $text are blank"

The echo statement should be:

echo 'You forgot the email subject and body text.<br />';

XJupiter  Sep 30, 2009 
Printed Page 188
5th coding line

The Author is missing one right parenthesis on the 5th coding line.

The line:

if (empty($subject){

Should be:

if (empty($subject)){

XJupiter  Sep 30, 2009 
Printed Page 190
5th coding line

The Author is missing one right parenthesis on the 5th coding line.

The line:

if (empty($subject){

Should be:

if (empty($subject)){

XJupiter  Sep 30, 2009 
Printed Page 202
Last sentence in "Check to see if the form has been submitted" section

"Just make sure the 'submit' matches up with the id attribute of the Submit button in the form code." should say "Just make sure the 'submit' matches up with the name attribute of the Submit button in the form code."

I tried using the id attribute instead of the name attribute, and it did not work.

DJPJ  May 28, 2009 
Printed Page 203
Top right of page (the comment)

The first line of the comment is incorrect:

We check the value of $_POST"submit']

The line should be:

We check the value of $_POST['submit']


XJupiter  Sep 30, 2009 
Printed Page 204
Modified form code

Code as written results in "undefined variable" errors for both $subject and $text the first time the script is run. Setting both variables to null before checking for $_POST['submit'] is one solution:

$text = '';
$subject = '';
if(isset($_POST['submit'])) {

etc.

lemuel  Jun 01, 2009 
Printed Page 204
sample code at bottom of page

Sample code's textarea tag is indented <?php echo $text; ?> on next line, but doing so caused whitespace to be inserted in form's textarea on initial page load. If no body text is entered in the form, the spaces in the textarea still cause the $text variable to be "not empty" and the email is able to be sent despite the user not having entered any text there.

Removing the indentation got rid of the spaces and enable the validation to work properly again.

Anonymous  Jul 22, 2009 
Printed Page 204
chapter 4, final code

The code that is missing something is in the book within chapter 4, when the authors are showing how to put all the code into the into the sendemail.php.
See
pages 203 and 204.
Page 204 highlights php-inside-html code exactly where the error
messages come from.

The highlighted code is in these two lines:
<input id="subject" name="subject" type="text" value="<?php echo
$subject; ?>" size="30" /><br />
<textarea id="elvismail" name="elvismail" rows="8" cols="40"><?php echo
$text; ?></textarea><br />

Specifically, the error messages occur because $subject and $text have
not been initialized:
<?php echo $subject; ?>
<?php echo $text; ?>

In addition to the book, the code that is downloaded has the same problem.
It is in the \chapter04\final\sendemail.php


When running your 'final' version, 2 error messages occur, because two PHP variables were not initialized.

I solved that by adding these two lines of code at the top of the php code:

?php
my code to fix problem:
if (!isset($subject)) {$subject = "";}
if (!isset($text)) {$text = "";}

your code follows:
if (isset($_POST['submit'])) {
........

Anonymous  Jan 28, 2011 
Printed Page 211
ALTER TABLE statement

FYI .... I'm running MySQL 5.1.34, and the syntax that worked is:

ALTER TABLE email_list ADD id INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;

DJPJ  May 28, 2009 
Printed Page 216
both code snippets

German translation, 1st edition, 2009.

Both code snippets end with an semicolon, which is each not supposed to be there, according to PHP kurz & gut ( pocket reference ) on page 32.

Sebastian Pohl  Aug 28, 2012 
Printed Page 227
Left Center Comment

The comment:

After entering a name and score and clicking Add, the new score is confirmed and added to the guitarwars table in the database.

This should be changed to:

After entering a name and score and clicking Add, the new score is added to the guitarwars table in the database.

The new score at this point of the coding only gets added to the database, it DOES NOT GET CONFIRMED AND ADDED. The confirmation is performed by the Administrator at a later time by accessing the Admin page.

XJupiter  Sep 30, 2009 
Printed Page 235
mysql command line screen shot

sql statement is incorrect uses DESCRIBE email_list; should be DESCRIBE guitarwars;

Anonymous  Apr 11, 2009 
Printed Page 235
Test Drive

Before creating the table, you have to either create a new database, or decide to add the table to an existing database. Then you have to issue the USE statement; then you can run the CREATE TABLE and INSERT statements.

DJPJ  May 29, 2009 
Printed Page 236
First sentence

"With a new column added to the high score database,"?? The database is named "gwdb" and the table is named "guitarwars." I think it should say "With a new column added to the guitarwars table,"

DJPJ  May 29, 2009 
Printed Page 242
IF statemetn

filesize($row["screenshot'] should be filesize($row['screenshot']

DJPJ  Jun 01, 2009 
Printed Page 242
Near bottom of the page

The following line of code is incorrect:


if (is_file($row['screenshot']) && filesize($row["screenshot']) > 0) {

This should be:

if (is_file($row['screenshot']) && filesize($row['screenshot']) > 0) {

In other words "screenshot' should be 'screenshot'


XJupiter  Sep 30, 2009 
245
First Paragraph

Maybe this is clarified later on the text, but it says:

"you can't control the the initial storage location of uploaded files with PHP, which is why the location is considered temporary."

However, it is possible to do this in php.ini by changing upload_tmp_dir .

David Friedman  Aug 23, 2009 
Printed Page 251
addscore.php code lines with move_uploaded_file

It almost seems like a page is missing from the book, because it never actually shows you entering in code for a line that includes move_uploaded_file onto the addscore.php, (which makes this whole area confusing) but on page 251, it is there already inserted, while discussing the creation and integration of the GW_UPLOADPATH.

However, the code is incorrect. It is saying that the move_uploaded_file is a condition to test against, but it shouldn't be...

The line in the book is...

if (move_uploaded_file($_FILES['screenshot'][tmp_name'], $target)) {

and it should simply read...

move_uploaded_file($_FILES['screenshot'][tmp_name'], $target)

Jeff  Feb 26, 2009 
Printed Page 252
answer to making file names unique with adding time()

Adding the time() function to the $target variable will not work for the web site because it causes the name in the database to be different than the name of the actual picture file that is being saved in the images folder. The time function should be added to the

$screenshot=$_FILES['screenshot']['name'];

line of code, giving you...

$screenshot=time().$_FILES['screenshot']['name'];

This will allow the image to be named the exact same both in the images folder and the database table, and therefore in the index page it will properly reference the correct filename for the picture.

Jeff  Feb 26, 2009 
Printed Page 267
Top right comment

This line:

.....bytes is 1.22MB, or 1,250KB).

Should be replaced by:

.....bytes is 1.28MB, or 1,280KB).


XJupiter  Sep 30, 2009 
268
top

The description asks for less than the GW_MAXFILESIZE however the code is implemented as less than or equal to GW_MAXFILESIZE.

David Friedman  Nov 11, 2009 
268
top

At least on my system png images were identified by the mime type image/x-png

(I'm using a local apache server running on a Windows 7 laptop which is maybe a little unusual, so maybe that is the cause of that)

David Friedman  Apr 19, 2010 
Printed Page 268
"Sharpen your pencil solution" box at top of page

This might be the authors using "tough love" to get readers to think for themselves, or it might be an oversight, but in the "Sharpen your pencil" solution box on p. 268 of the printed book, the answer includes two new variables and the text says "Assume the file size and type have already been stored in variables named $screenshot_size and $screenshot type."

There are never instructions to create those variables though, and none of the code snippets actually shows those variables having been created. The script will always return the error message about file type and size if you use it without setting those variables.

Like I said, it could be intentional, I'm just not sure.

Mike  May 10, 2010 
Printed Page 269
code sample

Looks like we are testing for 4 error conditions, but only displaying a message for 3 of them.
The "if ($_FILES['screenshot']['error'] == 0 {" does not display an error if there was an upload problem, you just fall out and nothing happens.
The code that sounds like the right message for this condition is run if there is an error moving the uploaded file from the temp directory to the target. I think we need an appropriate message for this condition. Then by rearranging the '}' we can have the proper message for the upload error statement.

DJPJ  Jun 01, 2009 
Printed Page 269
Coding near the bottom

The following line:

.....(GW_MAXFILESIZE / 1024) . ' KB in size.</p>';

Should be changed to:

(GW_MAXFILESIZE / 32) . ' KB in size.</p>';

XJupiter  Sep 30, 2009 
Printed Page 276
First paragraph.

The third sentence of paragraph begins "This begs the question, how does the Admin script" et cet. This is incorrect usage. "Begging the question" is a logical fallacy wherein one assumes as a premise of an argument exactly that which the argument purports to prove.

http://en.wikipedia.org/wiki/Begging_the_question

The sentence should say "This raises the question...".

Thomas Kennedy  Aug 16, 2010 
301

Passwords should always be encyrpted becosue pepole don't use diffrent passwords on separate sites. On page 301 it gives the developers the idea that passwrods should at any time be unencrypted. This is not a good idea becosue pepole use their password in more places then one.

Not only that it is not that hard to do encryption on passwords.

Kyle  Aug 18, 2010 
Printed Page 322
ALTER statement

In my version of MySQL (5.1.34) adding the column 'approved' as TINYINT sets the value to NULL in all existing rows.

I re-did my ALTER to specify NOT NULL. That set the column value to 0 for all existing rows.
ALTER TABLE guitarwars ADD COLUMN approved TINYINT NOT NULL;

Now we can go through and approve them using the modified application.

Otherwise, they won't show up on the index.html page (because we are looking for a value of 1) and we won't create an 'Approve' link for those rows (because we are looking for a value of 0.)

I guess we could just look for a value of 1 or not 1, but that isn't how things are designed in the text.

DJPJ  Jun 02, 2009 
Printed Page 324
Sharpen Your Pencil Solution

Since we created the Approved field as integer rather than a string, there should not be single quotes around $id in the UPDATE query.

Downloaded version is ok.

lemuel  Jun 17, 2011 
Printed Page 326
Sharpen your Pencil solution

if ( $row['approved'] == '0') should probably be
if ( $row['approved'] == 0) since approved is a TINYINT, but testing works both ways .... hhhmmmmm, interesting.

DJPJ  Jun 02, 2009 
335
bottom right hand corner

I'm not sure I understand what the text means in this passage:

>
Q: Would Ethel's SQL injection attack have still worked if the approved column wasn't at the end of the table?

A: No, and that's a really important point. This particular INSERT query relies on the default ordering of columns in the table. Tacking on 1 to the end of the query just happened to work because approved is the last column, appearing immediately after the screenshot column.
<

I think Ethel needs to know the structure of the table but if approved is moved to a different location then Ethel just has to figure out where to move the 1 in doing the SQL injection attack.

David Friedman  May 06, 2010 
Printed Page 336
lower half

Instructions to add "mysqli_real_escape_string" to variables is incomplete; the parameters include the database connection in the form of the variable "$dbc", but the script won't work because that variable is not set until later in the script. The line of script setting the variable and connecting to the database must be moved up in the script.

I got it to work by moving the line setting "$dbc" to be the first line after "if (isset(_POST['submit'])) { "

Mike  May 14, 2010 
Printed Page 339
Last paragraph /"Exercise" section

isnumeric should be is_numeric

Cathy Austin  Oct 20, 2009 
361
3rd grayed part of the code

in the line of code:

$query="SELECT user_id, username FROM mismatch_user WHERE username='$user_username' AND "."password=SHA($user_password)";

SHA($user_password) should be surrounded by single quotes.

The line of code should be:

$query="SELECT user_id, username FROM mismatch_user WHERE username='$user_username' AND "."password='SHA($user_password)'";

Sherif Mahmoud  May 24, 2009 
Printed Page 361
Code example of login.php, first two lines

The login.php code starts with getting an include file:
<?php
require_once('connectvars.php');
.....
However, this is just before the header authentication code.
I received an error message:
PHP Warning: Cannot modify header information - headers already sent by (output started at ............/ch7/connectvars.php:1)

Obviously the page is sending a header before the authentication header. So moving the include file line to just after the header but before the database connection resolves the issue.

Jonathan Richards  Feb 20, 2015 
Printed Page 371

When conducting the "Test Drive" and adding a image i was getting an error stating "Notice: Undefined index: file ...editprofile.php line 60"
the error on this line looked something like this:
if ($_FILES['file']['error'] == 0) {

Corrected like this and the error goes away:
if ($_FILES['new_picture']['error'] == 0) {

jr_holland28  May 17, 2009 
Printed Page 380
in the code

Error message is returned for:
if (mysqli_num_rows($data) == 1) {

The error message is:
mysqli_num_rows() expects parameter 1 to be mysqli_result()

What is some alternative code for this line?

Thanks

happynewton  Oct 18, 2010 
Printed Page 399
First code example image

On page 379 the illustration caption on the lower right of the page indicates that the index page will show the latest member names as links instead of static text if the user is logged in. However, there are never instructions in the book to make this change to the index page code or to download and use the later version of the page from the Head First site.

On page 399 the first code illustration shows the script with the added code creating the alternate display with the latest members shown as links.

I understand the authors want to get people used to thinking for themselves, but this just seems like an oversight.

Mike  May 17, 2010 
Printed Page 403
Main Paragraph

There is a description of the php.ini setting "session.use_trans_id", which should be "session.use_trans_sid", according to the php manual.

lemuel  Jun 12, 2009 
Printed Page 403
middle of the paragraph

Here they talk about "session.use_trans_id". However, it should be "session.use_trans_sid". Small typo.

David Tang  Jun 14, 2009 
416
Top

To check if a user is logged in is it better to use isset($_COOKIE['user_id']) or empty($_COOKIE['user_id']) ?

In a previous place the book implements it using isset() (specifically page 380)

empty($_COOKIE['user_id']) may actually be better though.

If the cookie user_id field is set but empty that may mean the cookie got modified or corrupted somehow on the local machine, and so the user should log back in so that the cookie gets set to a consistent value.


David Friedman  May 13, 2010 
443
Lower part

It looks like there are some discrepancies between the database as defined by the SQL statements downloaded from the website, and the screenshots of the output of the DESCRIBE statements.

For example, the name field of mismatch_topic is not specifically defined as NOT NULL but that is what the screenshot says.

And there may be some other discrepancies in terms of what the default values are set to be.

David Friedman  May 17, 2010 
443
Download Link

In the script which generates the mismatch_topic table it looks like there are some typos in category labels:

Specifically for:

1. Bill Gates
2. Easy Listening Music

David Friedman  May 18, 2010 
Printed Page 447
Second SELECT query of PHP & MySQL Magnets on line 6

The $query in the book and in the download code is: "SELECT topic_id FROM mismatch_topic ORDER BY category_id, topic_id"

The $query should actually read: "SELECT topic_id FROM mismatch_topic ORDER BY category, topic_id"

Basically, category_id should be replaced with category. Also shown on pages 448 and 456.


Rich dev  Feb 15, 2009 
448
Center

$query = "INSERT INTO mismatch_response (user_id, topic_id) VALUES ('" . $_SESSION['user_id'] . "' , '$topic_id' )" ;

Maybe this would be better written as:

$query = "INSERT INTO mismatch_response (user_id, topic_id, response) VALUES ('" . $_SESSION['user_id'] . "' , '$topic_id', '0' )" ;

Or to have it that the response field defaults to 0.

David Friedman  May 18, 2010 
Printed Page 456
Code section marked with 1

The query shows:

$query = "SELECT topic_id FROM mismatch_topic ORDER BY category_id, topic_id";

it should read:
$query = "SELECT topic_id FROM mismatch_topic ORDER BY category, topic_id";

The downloaded code also contains this error, line 29 in questionnaire.php.

Jim Munro  May 08, 2009 
Printed Page 456
In the code, Second"$query"

$query is set to equal "SLECT * FROM mistmatch_response ORDER BY category_it, topic_id".

Unfortunatley, category_id is not a field in the database, yet "category" is.

I'm not sure if this is a typo on the database end, or in the questionaire.php, but this needs to be fixed because it disables the script.

A fix for it is to change "category_id" to just "category" in the query.

Here is where a solution was posted:
http://forums.oreilly.com/index.php?s=&showtopic=3057&view=findpost&p=9596

Anonymous  Jun 04, 2009 
Printed Page 456
In section of code labeled #1

the second query reads "SELECT topic_id FROM mismatch_topic ORDER BY category_id, topic_id";


category_id DOES NOT EXIST YET

It is still category

Anonymous  Jan 20, 2010 
Other Digital Version 457
in the example code, not in the book I don't think

In the downloaded code of chapter 7.5 I got an error when submitting my profile picture.

The error was line 44 of the file: editprofile.php

Code was:
if ($_FILES['file']['error'] == 0) {

Code should be:
if ($_FILES['new_picture']['error'] == 0) {

Thanks for the great book!!

Jim Munro  May 08, 2009 
Other Digital Version 458
Test Drive

Hello:

I found two errors in the Downloadable Coding for Chapter 8. The errors were found in login.php and logout.php. Here they are:

login.php

The following statement:

$home_url = 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . '/index.php';
header('Location: ' . $home_url);

Should be:


$home_url = 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . 'index.php';
header('Location: ' . $home_url);


(i.e. delete the "/" in front of index.php)



logout.php

The following statement:


// Redirect to the home page
$home_url = 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . '/index.php';
header('Location: ' . $home_url);


Should be:

// Redirect to the home page
$home_url = 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . 'index.php';
header('Location: ' . $home_url);


(i.e. delete the "/" in front of index.php)

Anonymous  Nov 29, 2009 
Printed Page 476
Top of page, first "A"nswer

The text says:

"
So the INNER JOIN takes place with respect to the category_id column in, both tables but the WHERE clause refines the results using only the name column in the mismatch_topic table."

The comma after "column in," is superfluous.

Robert Kulagowski  May 13, 2011 
Printed Page 492
United States

On page 492, "The text response('2' for example) is cast to an integer(2) so that it can be added and compared. In both the code supplied for page 493 and the final code, the int() cast is missing:

if ($user_responses[$i]['response'] + $mismatch_responses[$i]['response'] == 3) {
$score += 1;

Mike Griffin  Sep 28, 2011 
PDF, ePub Page 492
for loop in the page

The code in this page and the downloaded file does not work correctly unless you also check in the "for" loop if the variable
$mismatch_responses is not empty. If one or more users did not answer any of the questions, a message would be printed on the screen.

Just like this:

"Notice: Undefined offset: 0 in E:\xampp\htdocs\mismatch\mymismatchoriginal.php on line 60"

ORIGINAL CODE

for ($i = 0; $i < count($user_responses); $i++) {
if ($user_responses[$i]['response'] + $mismatch_responses[$i]['response'] == 3) {
$score += 1;
array_push($topics, $user_responses[$i]['topic_name']);
}
}

SUGGESTED MODIFIED CODE

for ($i = 0; $i < count($user_responses) && !empty($mismatch_responses); $i++) {
if ($user_responses[$i]['response'] + $mismatch_responses[$i]['response'] == 3) {
$score += 1;
array_push($topics, $user_responses[$i]['topic_name']);
}
}

Renato Fiuza  Dec 12, 2013 
Printed Page 493
in code somewhere...

When I uploaded your code to find my errors, it worked fine, except for the link to the user's profile at the bottom of the page. It displayed my user profile rather than the mismatched user profile.

Heidi Daley  Mar 09, 2010 
Printed Page 493
United States

It doesn't matter if you use the "final" code as distributed or you add the (int) cast as shown in the book, when you try to open mymismatch.php, the

if ($user_responses[$i]['response'] + $mismatch_responses[$i]['response'] == 3)

code throws an "undefined offset" error for each of the array indexes.

If you enclose that section of code with if (isset($mismatch_resposes[0]) && isset(user_responses[0])) {
...
}

else {
echo 'the arrays are undefined';

The result is that the arrays are undefined. I've used print_r to print the arrays after they are populated, and they print, so somewhere this is a scope issue because after throwing the the undefined offset error, the results of the mismatch are still printed. It would be nice to know what I should be looking at to fix this!

Mike Griffin  Sep 28, 2011 
Printed Page 493
United States

The undefined offset error running this code really bugged me. So I did a lot of searching. It appears that this may be badly written code for the book. I found several posts where other books used code that produced the same error..Here's the quote:

"The real reason this is a problem is because the default configuration settings of PHP versions earlier than 4.2.0 suppressed NOTICE level warnings, so many programmers thought that the ... 'bad' code was, in fact, 'clever '."

Several sites also say that the error doesn't matter, which is what I had already found. So if you suppress all error reporting for this script with adding

error_reporting(0);

to the top of the script, it runs fine. So there is something wrong with the code for this line that causes the error. Maybe the authors can post what it is!!!

Mike Griffin  Sep 28, 2011 
Other Digital Version 506
Downloadable SQL Database

The database does not import properly as it is on the server: entry number 12, Pet Food Tester, has the following description:

'We pride ourselves on how good our pet food tastes. Now you can help make our products even better. We&#8217;re hiring pet food tasters, apply now!'

Where it says "We&#8217;re", the mysql terminal confuses the apostrophy for a closing single quote. Changing it to "We''re" fixed this issue for me.

Laurel Raven  Aug 14, 2009 
Other Digital Version 506
At end of the page

The .sql file given in the source for chapter 9 is not importing. please give a valid .sql file.

Seraphimus Phoenix  Sep 07, 2012 
Printed Page 508
Solution for "LIKE '%ma'"

In the magnet exercise solution, it only shows "Human Cannonball" and "Team Mascot" being a match for LIKE '%ma%'; however, since the LIKE term is case insensitive and % matches on anything INCLUDING nothing, it should also list "Matador" as a match.

Laurel Raven  Aug 14, 2009 
508
Magnets for 'c%'

It looks like one of the magnets is missing for 'c%' (the magnet for Crash Test Dummy)

David Friedman  May 20, 2010 
Printed Page 509
Speach/Thought Bubble at top

Poor wording choice:

"That last LIKE clause, LIKE '%Tipper Cow%', doesn't match anything because "Tipper" and "Cow" don't show up together as a phrase."

This is, as written, inaccurate: Tipper and Cow appear together as a phrase, but as "Cow Tipper". The thought bubble really should say something more like:

"That last LIKE clause, LIKE '%Tipper Cow%', doesn't match anything because "Tipper" and "Cow" don't show up together as a phrase in that order."

Laurel Raven  Aug 14, 2009 
Printed Page 515
1st paragraph

Test Drive Download - "The search.php script contains the query generation code you just worked through..."

The initial script does not contain the "worked through" code, doe not work as stated.

Head First Gunieau Pig  Apr 15, 2010 
523
Center

SELECT * FROM riskyjobs
WHERE description LIKE '%bull%' OR
description LIKE '%matador%' OR
description LIKE '% %' OR
description LIKE '% %' OR
description LIKE '%cape%'

It seems that here if you actually use the code from page 514 you would get:

SELECT * FROM riskyjobs
WHERE description LIKE '%bull%' OR
description LIKE '%matador%' OR
description LIKE '%%' OR
description LIKE '%%' OR
description LIKE '%cape%'

since those are empty string not single spaces.

However, the text says on page 523 "we _might_ end up with something like this" so maybe that was intended.

David Friedman  May 20, 2010 
Printed Page 530
Sharpen your PEncil

The comment in that section states that the data is in MM-DD-YYYY format, but it's not. It's YYYY-MM-DD.

You may also want to expand the text stating that storing dates in ISO8601 format is:

1) Unambiguous across various date/time standards throughout the world. Europeans use DD-MM-YYYY, USA uses MM-DD-YYYY, so what date is 03-04-2011? Is it March 4th, or is it April 3rd?

2) It allows for easy sorting.

Robert Kulagowski  May 16, 2011 
534
first query and fourth query

In the queries the actual column name created by the script is "title" yet in the answers it is written as "job_title".

David Friedman  May 21, 2010 
Printed Page 544
Exercise Solution

I couldn't bring myself to put all that redundant code in my script.
Here's what mine looks like:

function generate_sort_links($user_search, $sort) {

$sort_links = '';
switch($sort) {
case 1:
$sortA = 2;
$sortB = 3;
$sortC = 5;
break;
case 3:
$sortA = 1;
$sortB = 4;
$sortC = 5;
break;
case 5:
$sortA = 1;
$sortB = 3;
$sortC = 6;
break;
default:
$sortA = 1;
$sortB = 3;
$sortC = 5;
}

$sort_links .= '<td><a href="' . $_SERVER['PHP_SELF'] . '?usersearch=' . $user_search .
'&sort=' . $sortA . '">Job Title</a></td><td>Description</td>';

$sort_links .= '<td><a href="' . $_SERVER['PHP_SELF'] . '?usersearch=' . $user_search .
'&sort=' . $sortB . '">State</a></td>';

$sort_links .= '<td><a href="' . $_SERVER['PHP_SELF'] . '?usersearch=' . $user_search .
'&sort=' . $sortC . '">Date Posted</a></td>';

return $sort_links;
}

DJPJ  Aug 28, 2009 
Printed Page 546
Test Drive

When I take the test drive, I get an error "Notice: Undefined index: sort in C:\Inetpub\wwwroot\hfphp\ch09\riskyjobs\search.php on line 109.

I changed the code from
"$sort = $_GET['sort'];"

to

"isset($_GET['sort']) ? $sort = $_GET['sort'] : $sort = '';"

I got the same error when I ran the code I downloaded from your site.

DJPJ  Aug 28, 2009 
Printed Page 546
Test Drive

that should appear as $sort = ''; not $sort = ";"

I'm not sure why your errata form changed what I pasted in to it.

DJPJ  Aug 28, 2009 
Printed Page 549
Bottom paragraph, last sentence, above queries

The last sentence of the paragraph states "For example, here's how you get rows 11 through 25, which would be the third page of results." It should be 11 through 15 as the query is only set to return 5 results beginning at 11.

$query = $query . " LIMIT 10, 5";

Anonymous  Mar 03, 2009 
Printed Page 549
3rd paragraph (last).

The last line of the page says, "For example, here's how you get rows 11 through 25, which would be the third page of the results:". The '25' should be replaced with a '15'.

Waleed Khan  May 19, 2011 
Printed Page 550
1st paragraph

The book reads:

"...LIMIT clause to set up the naviagation...."

Maristella  Nov 28, 2009 
Printed Page 552
Code example and downloadable code for chapter

Hi, me again.

I noticed this earlier than was likely mentioned in the book, but the same error occurs in the downloaded code.

The line 144 in search.php is:
$sort = $_GET['sort'];

But the first sort will not have this variable sent in the GET so it shows an error:

Notice: Undefined index: sort in D:\wamp\www\search.php on line 141

I fixed it as you did with the page GET variable.

$sort = isset($_GET['sort']) ? $_GET['sort'] : '';

Jim Munro  May 11, 2009 
556
Links for next and previous

When you do a less than sign or greater than sign in HTML it should probably be done with &gt; or &lt; rather than the direct symbol since the '>' is used to do the markup.

David Friedman  May 24, 2010 
Printed Page 577
(min,max) box

I think the last sentence should be removed ... "Here we're saying it should appear 2, 3, or 4 times in a row."

I don't see anything that supports that statement.

DJPJ  Aug 28, 2009 
578
Bottom (description of the exercise)

Write a regular expression that matches international phone numbers:

Maybe this should actually read "matches U.S. phone numbers."

David Friedman  May 27, 2010 
Printed Page 582
Regular expression

On page 582 is a regex made and used in the further pages, it contains an error...

/^\(?[2-9]\d{2}\)?[-\s]\d{3}[-\s]\d{4}$/
is what it should be, the regex mentioned (also in the files!!!!) is
/^\(?[2-9]\d{2}\)?[-\s]\d{3}-\d{4}$/
(mind the dash in the used regex, this makes the use of a space here impossible)

Anonymous  Feb 12, 2013 
Printed Page 587
Downloaded Source Code

Similar to error on 552. The registration form attempts to pre-populate the input fields with variables based on the $_POST data. The first time the script is run these variables do not exist and each field shows a php "Undefined variable" error.

Each field could use a ternary input such as
echo isset($first_name) ? $first_name : '';

lemuel  Jul 08, 2009 
Printed Page 596
Sample regex, bottom half of page

In the sample regex, the question mark is not escaped. According to the text on page 580 a question mark must be escaped because it is a reserved character.

Also, in many places in the book hyphens (dashes) are escaped even though they are not included in the list on page 580 of characters that must be escaped.

Escaping characters that do not require it is in most cases OK but it is not advised according to my research, as one may inadvertently change a character into a metacharacter by escaping it.

Mike  May 23, 2010 
Printed Page 596
sample regex in bottom half of page

Upon further investigation it's looking like escaping rules are not exactly the same inside character sets. When I used that regex in the registration script without escaping the hyphen, I got a warning about it. When I escaped it, the warning did not occur.
Earlier I had done a simple test using preg_replace() to test whether hyphens needed to be escaped and got the same result both with the character escaped and not escaped.
In any case, it's confusing when the text escapes characters that weren't listed as requiring escape when it appears very much to matter, and the rules are different in different circumstances.
So while the errata I submitted about this isn't exactly right, this still represents an error in the book in my opinion.

Mike  May 23, 2010 
602
top of the page in preg_match() call

I think we need to add a caret to the beginning of the regular expression which checks for the valid local part of the email address.

David Friedman  May 31, 2010 
Printed Page 604
top right post-it

The post-it box describes some REGEX metacharacters and references a whitespace metacharacter with '\w'.
The whitespace metacharacter is '\s'.

Mitch Lowther  May 21, 2013 
Printed Page 614
imagettftext function

The parameter with the font name some times should be writed with a absolute path, depending on your GD library version.

The solution for me was:

- to rename the font name to 'courier.ttf';
- to insert the function dirname with the font name: dirname(__FILE__).'\courier.ttf'

Douglas Oliveira  Apr 10, 2020 
Printed Page 618
middle of page

The description of the imagefilledellipse points to parameters 2 and 3 as width and height, and parameters 4 and 5 as x and y coordinates. It seems as though they are reversed. Parameters 2 and 3 should represent the x and y coordinates and parameters 4 and 5 should represent the width and height.

tmichael  Mar 20, 2009 
PDF Page 623
41th line of code

When you start captcha.php on the linux server generated picture, but without the text.
To add text to place the font "Courier New Bold.ttf" in the directory with the script, and insert before the name of the font "./"

imagettftext($img, 18, 0, 5, CAPTCHA_HEIGHT - 5, $text_color, './Courier New Bold.ttf', $pass_phrase);

Anonymous  Jul 31, 2013 
634
center

Seems that we also need the response field in order to see whether there is a mismatch.

David Friedman  Jun 02, 2010 
634
Center

With respect to my above question:

--
Seems that we also need the response field in order to see whether there is a mismatch.
--

actually I think it is okay, because the topics that are mismatched are already stored in an array in the mymismatch.php script.

David Friedman  Jun 02, 2010 
Printed Page 641
Exercise, bottom half of page

The exercise creates a two-dimensional array populated with the data from the array $mismatch_categories. But the instructions up to this point never create an array called $mismatch_categories. It appears as a line in the downloadable file for page 646 (in the folder ch11) in the downloads. It is line 111:
" $mismatch_categories = array_slice($categories, 0);"
There are never instructions in the book to add that line.
This is a serious oversight.

Mike  May 25, 2010 
Printed Page 674
By #4, the query statement and by #5 the link tag

This page is a listing for newsfeed.php. The lines in question are:

$query="SELECT abduction_id, first_name, last_name, DATE_FORMAT(when_it_happened, '%a, %d %b %Y %T') AS when_it_happened_rfc, alien_description, what_they_did " .
"FROM aliens_abduction " .
"ORDER BY when_it_happened DESC";

echo ' <link>http://www.aliensabductedme.com/index.php?abduction_id=' . $row['abduction_id'] . '</link>';

In the book, when did we add abduction_id to the table aliens_abduction? I don't remember adding the field and the values to the field. Without abduction_id, newsfeed.php crashes with no indication why.

Ed  Sep 07, 2012 
Printed Page 674
By #4, the query statement and by #5 the link tag

When did the data type for when_it_happened changed?

Does the DATE_FORMAT function take text?

Adding or die() to $data=mysqli_query($dbc, $query) crashed the page. What happens of the query has an error?

Ed  Sep 07, 2012 
Printed Page 675
Downloaded Source Code

Line 49 of index.php has $row[last_name], should be $row['last_name'].

lemuel  Jul 14, 2009 
Printed Page 677
Top

When did we create an index.php for Aliens Abducted Me?

The second sentence says "Modify the index.php script". I don't recall creating index.php or instructed to download it from the Head First wevsite.

Edward  Sep 12, 2012 
694
bottom

The text says that the yt namespace is used solely with the statistics tag, yet it seems that it is used also in other places.

For example, <yt:duration> is at the beginning of the code snippet.

I also see it in a <media:content> tag as part of an attribute (namely yt:format ).

David Friedman  Jun 10, 2010 
Printed Page 715
7th row, columns 2 and 3

The printed version correctly states how to execute a MySQL query. In other words, the errata stating that the printed version is in error is incorrect (i.e. the errata is wrong).

If you go to www.w3schools.com and look up the format for mysqli_query, it contradicts the printed version of what the format should be. In other words, www.w3schools.com made a mistake!!!!!

Just go to www.php.net, type in mysqli_query, and you will find out that the format is mysqli_query($dbc, $query).

Also, Google mysqli_query and you will find out that the format is indeed mysqli_query($dbc, $query).

Generally, www.w3schools.com is extremely accurate, but they screwed up with mysqli_query!!!!!

Anonymous  Feb 01, 2010 
Printed Page 733, 737
page 733, top of page 737

Also, the version of PHP is now 5.3.6 and the installer no longer displays the long list of servers to configure - as shown on page 737.

Anonymous  Aug 24, 2011 
Printed Page 734
2nd paragraph

The book reads "To determine if you have MySQL on the Mac, open your terminal and type: cd /user/local/mysql

It should read
and type: cd /usr/local/mysql

as it is illustrated in the image of the terminal window below this passage.

Anonymous  Nov 10, 2009 
738
the link just above the last paragraph

It says to get version 6.0 or newer. The MySQL documentation page says, "Note: The MySQL 6.0 Reference Manual has been retired. MySQL 6.0 was not developed beyond Alpha status and new releases have not been made for some time, so the manual has been withdrawn as well."

Now what?

kajaco2  Oct 08, 2009 
Printed Page 751
1st paragraph

The book suggests to go to the www.libgd.org website to obtain the php_gd2.dll file. It seems that this is no longer the case or there is now an easier method.

I have installed Apache 2.2.15 and PHP 5.2.13 (using the windows installer provided on the PHP website). If you have installed these versions using the installer, then to add the php_gd2.dll extension, you must to to Control Panel -> Add or Remove Programs and select "PHP" and press the "Change" button. Press Next, then press "Change" again, press Next two more times, and enable the "GD2" extension.

Hans Prorok  Apr 05, 2010