Drew Tuzson Drew Tuzson - 1 month ago 7
HTML Question

Beginner using php to create guest book that logs info to text file and displays data on separate page

I am a php beginner and I am working to create a guest book page that will accept a name and an email address from the user. Once they submit the form, the script writes this data to a text file. The user can then view all guest book entries. This is where I am having issues.

The guestbook page is creating the table data as desired, however the Name and Email portions are not calling the correct data. I am using the explode method and I think that is where I have confused myself and broken the program. I queried here and found nothing specific to this issue. I also dug through the documentation and I only confused myself more. Can anyone tell me where I have gone wrong? I have included the source code for both files below:

sign-book.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Post Message</title>
<meta http-equiv="content-type"
content="text/html; charset=iso-8859-1" />
</head>
<body>

<?php

if (isset($_POST['submit'])) {
$Name = stripslashes($_POST['name']);
$Email = stripslashes($_POST['email']);

$Name = str_replace("~", "-", $Name);
$Email = str_replace("~", "-", $Email);
$MessageRecord = "$Name~$Email\n";
$MessageFile = fopen("Guestbook/messages.txt", "ab");
if ($MessageFile === FALSE)
echo "There was an error saving your
entry.\n";
else {
fwrite($MessageFile, $MessageRecord);
fclose($MessageFile);
echo "Thank you for signing the Guest Book!\n";
}
}

?>

<h1>Please Sign the Guest Book</h1>
<hr />
<form action="sign-book.php" method="POST">
<span style="font-weight:bold">Name:</span>
<input type="text" name="name" />
<span style="font-weight:bold">Email:</span>
<input type="text" name="email" /><br /><br />
<input type="submit" name="submit"
value="Sign Guest Book" />
<input type="reset" name="reset"
value="Reset Form" />
</form>
<hr />
<p>
<a href="guestbook.php">View Previous Entries</a>
</p>

</body>
</html>


guestbook.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Message Board</title>
<meta http-equiv="content-type"
content="text/html; charset=iso-8859-1" />
</head>
<body>

<h1>Our Guestbook</h1>
<?php

if (isset($_GET['action'])) {
if ((file_exists(
"Guestbook/messages.txt")) &&
(filesize(
"Guestbook/messages.txt") != 0)) {
$MessageArray = file(
"Guestbook/messages.txt");
switch ($_GET['action']) {
case 'Delete Message':
if (isset($_GET['message'])) {
$Index = $_GET['message'];
unset($MessageArray[$Index]);
$MessageArray = array_values($MessageArray);
}
break;
case 'Remove Duplicates':
$MessageArray = array_unique($MessageArray);
$MessageArray = array_values($MessageArray);
break;
case 'Sort Ascending':
sort($MessageArray);
break;
case 'Sort Descending':
rsort($MessageArray);
break;
}

if (count($MessageArray)>0) {
$NewMessages = implode($MessageArray);
$MessageStore = fopen("Guestbook/messages.txt", "wb");
if ($MessageStore === false)
echo "There was an error
updating the message
file\n";
else {
fwrite($MessageStore,
$NewMessages);
fclose($MessageStore);
}
} else
unlink("Guestbook/messages.txt");
}
}

if ((!file_exists("Guestbook/messages.txt"))
|| (filesize("Guestbook/messages.txt")
== 0))
echo "<p>There are no entries
logged.</p>\n";
else {
$MessageArray = file("Guestbook/messages.txt");
echo "<table
style=\"background-color:lightgray\"
border=\"1\" width=\"100%\">\n";

$count = count($MessageArray);

for ($i = 0; $i < $count; ++$i) {
$CurrMsg = explode("~", $MessageArray[$i]);
$KeyArray[] = $CurrMsg[0];
$ValueArray[] = $CurrMsg[1];
$KeyMessageArray = array_combine($KeyArray, $ValueArray);
}

$Index = 1;

foreach($KeyMessageArray as $Message) {
$CurrMsg = explode("~", $Message);
echo "<tr>\n";
echo "<td width=\"5%\"
style=\"text-align:center\"><span
style=\"font-weight:bold\">" .
$Index . "</span></td>\n";
echo "<td width=\"85%\"><span
style=\"font-weight:bold\">
Name:</span> " .
htmlentities($KeyArray[1]) . "<br />";
echo "<span style=\"font-weight:bold\">
Email:</span> " . htmlentities($CurrMsg[0]) .
"<br />";
echo "<td width=\"10%\"
style=\"text-align:center\">" .
"<a href='guestbook.php?" .
"action=Delete%20Message&" .
"message=" . ($Index - 1) .
"'>Delete This Entry</a>" .
"</td>\n";
echo "</tr>\n";
++$Index;
next($KeyMessageArray);
}
echo "</table>\n";
}


?>
<p>
<a href="sign-book.php">
Log Another Entry</a><br />
<a href="guestbook.php?action=Sort%20Ascending">
Sort Subjects A-Z</a><br />
<a href="guestbook.php?action=Sort%20Descending">
Sort Subjects Z-A</a><br />
<a href="guestbook.php?action=Remove%20Duplicates">
Remove Duplicate Messages</a><br />
</p>

</body>
</html>

Answer

You have already exploded $MessageArray[$i] by ~ here:

for ($i = 0; $i < $count; ++$i) {
    $CurrMsg = explode("~", $MessageArray[$i]);
    $KeyArray[] = $CurrMsg[0];
    $ValueArray[] = $CurrMsg[1];
    $KeyMessageArray = array_combine($KeyArray, $ValueArray);
}

So, now you have all names in $KeyArray and all emails in $ValueArray. (By the way - if your names will be repeated, example Paul, Paul, John - oops) Nevertheless, next you do:

foreach($KeyMessageArray as $Message) { 
    $CurrMsg = explode("~", $Message); 

But why do you do this as $Message is an email already and definitely has NO ~ in it!

You should use foreach this way:

foreach($KeyMessageArray as $name => $email) { 
     // do stuff
}

Update about names:

so, as I said, when your names will repeat, your code will not work as expected. To avoid it - don't use name as a key, just use name and email as values for an array:

for ($i = 0; $i < $count; ++$i) {
    $CurrMsg = explode("~", $MessageArray[$i]);
    // add both values to array:
    $KeyMessageArray[] = array(
        'name' => $CurrMsg[0],
        'email' => $CurrMsg[1],
    );
}

// next - iterate:
foreach($KeyMessageArray as $data) { 
    echo 'name is ' . $data['name'] . ', email is ' . $data['email'];
    // do stuff
}

And even further - you can do all stuff in one loop:

for ($i = 0; $i < $count; ++$i) {
    $CurrMsg = explode("~", $MessageArray[$i]);
    echo 'name is ' . $CurrMsg[0] . ', email is ' . $CurrMsg[1];
    // show some table stuff
}