Page 1 of 1

Private Message Errors

Posted: Mon Jun 18, 2012 8:52 pm
by AndrewD92
Hey, its been a while. I have returned to the Private Message tutorial and this error caused me to give up last time. When viewing a conversation I get the following errors;

Notice: Undefined variable: messages in C:\xampp\htdocs\PHP\Better PHP\PrivateMessage\core\pages\view_conversation.page.inc.php on line 45

Warning: Invalid argument supplied for foreach() in C:\xampp\htdocs\PHP\Better PHP\PrivateMessage\core\pages\view_conversation.page.inc.php on line 45

Here is my code. Any advice would be great. I don't know where to start as I left it abit too long.

private_message.inc.php
<?php

// Fetches a summary of the conversations.
function fetch_conversation_summary(){
	$sql = "SELECT
				`conversations`.`conversation_id`,
				`conversations`.`conversation_subject`,
				MAX(`conversations_messages`.`message_date`) AS `conversation_last_reply`,
				MAX(`conversations_messages`.`message_date`) > `conversations_members`.`conversation_last_view` AS `conversation_unread`
			FROM `conversations`
			LEFT JOIN `conversations_messages` ON  `conversations`.`conversation_id` = `conversations_messages`.`conversation_id`
			INNER JOIN `conversations_members` ON `conversations`.`conversation_id` = `conversations_messages`.`conversation_id`
			WHERE `conversations_members`.`user_id` = {$_SESSION['user_id']}
			AND `conversations_members`.`conversation_deleted` = 0
			GROUP BY `conversations`.`conversation_id`
			ORDER BY `conversation_last_reply` DESC";
			
	$result = mysql_query($sql);
	
	$conversations = array();
			
	while (($row = mysql_fetch_assoc($result)) !== false){
		$conversations[] = array(
			'id' 				=> $row['conversation_id'],
			'subject' 			=> $row['conversation_subject'],
			'last_reply' 		=> $row['conversation_last_reply'],
			'unread_messages'	=> ($row['conversation_unread'] == 1),
		);
	}

	return $conversations;
}

// Fetches all of the messages in the given converstion.
function fetch_conversation_messages($conversation_id){
	$conversation_id = (int)$conversation_id;
	
	$sql = "SELECT
				`conversations_messages`.`message_date`,
				`conversations_messages`.`message_date` > `conversations_members`.`conversation_last_view` AS `message_unread`,
				`conversations_message`.`message_text`,
				`users`.`user_name`
			FROM `conversations_messages`
			INNER JOIN `users` ON `conversations_messages`.`user_id` = `users`.`user_id`
			INNER JOIN `conversations_members` ON `conversations_messages`.`conversation_id` = `
			s`.`conversation_id`
			WHERE `conversations_messages`.`conversation_id` = {$conversation_id}
			AND `conversations_members`.`user_id` = {$_SESSION['user_id']}
			ORDER BY `conversations_messages`.`message_date` DESC";

	$result = mysql_query($sql);
	
	$messages = array();
	
	while (($row = mysql_fetch_assoc($result)) !== false){
		$messages[] = array(
			'date' 		=> $row['message_date'],
			'unread'	=> $row['message_unread'],
			'text' 		=> $row['message_text'],
			'user_name' => $row['user_name'],
		);
	}
	
	return $messages;
}

// Sets the last view time to the current time for the given conversation.
function update_conversation_last_view($conversation_id){
	$conversation_id = (int)$conversation_id;
	
	$sql ="UPDATE `conversations_members`
			SET `conversation_last_view` = UNIX_TIMESTAMP()
			WHERE `conversation_id` = {$conversation_id}
			AND `user_id` = {$_SESSION['user_id']}";
			
	mysql_query($sql);	
}

// Creates a new conversation, making the given users a member.
function create_conversation($user_ids, $subject, $body){
	$subject	= mysql_real_escape_string(htmlentities($subject));
	$body		= mysql_real_escape_string(htmlentities($body));
	
	mysql_query("INSERT INTO `conversations` (`conversation_subject`) VALUES ('{$subject}')");
	
	$conversation_id = mysql_insert_id();
	
	$sql = "INSERT INTO `conversations_messages` (`conversation_id`, `user_id`, `message_date`, `message_text`)
			VALUES ({$conversation_id}, {$_SESSION['user_id']}, UNIX_TIMESTAMP(), '{$body}')";
			
	mysql_query($sql);
	
	$values = array("({$conversation_id}, {$_SESSION['user_id']}, UNIX_TIMESTAMP(), 0)");
	
	foreach ($user_ids as $user_id){
		$user_id = (int)$user_id;
		
		$values[] = "({$conversation_id}, {$user_id}, 0, 0)";
	}
	
	$sql = "INSERT INTO `conversations_members` (`conversation_id`, `user_id`, `conversation_last_view`, `conversation_deleted`)
			VALUES " . implode(", ", $values);
			
			mysql_query($sql);
}

// Checks to see if the given user is a member of the given conversation.
function validate_conversation_id($conversation_id){
	$conversation_id = (int)$conversation_id;
	
	$sql = "SELECT COUNT(1)
			FROM `conversations_members`
			WHERE `conversation_id` = {$conversation_id}
			AND `user_id` = {$_SESSION['user_id']}
			AND `conversation_deleted` = 0";
			
	$result = mysql_query($sql);
		
	return (mysql_result($result, 0) == 1);
}

// Adds a message to the given conversation.
function add_conversation_message($conversation_id, $text){
	$conversation_id 	= (int)$conversation_id;
	$text				= mysql_real_escape_string(htmlentities($text));
	
	$sql = "INSERT INTO `conversations_messages` (`conversation_id`, `user_id`, `message_date`, `message_text`)
			VALUES ({$conversation_id}, {$_SESSION['user_id']}, UNIX_TIMESTAMP(), '{$text};')";
	
	mysql_query($sql);
	
	mysql_query("UPDATE `conversations_members` SET `conversation_deleted` = 0 where `conversation_id = {$conversation_id}");
}

// Deletes (or marks as deleted) a given conversation.
function delete_conversation($conversation_id){
	$conversation_id = (int)$conversation_id;
	
	$sql = "SELECT DISTINCT `conversation_deleted`
			FROM `conversations_members`
			WHERE `user_id` != {$_SESSION['user_id']}
			AND `conversation_id` = {$conversation_id}";
			
	$result = mysql_query($sql);
	
	if (mysql_num_rows($result) === 1 && mysql_result($result, 0) == 1){
		mysql_query("DELETE FROM `conversations` WHERE `conversation_id` = {$conversation_id}");
		mysql_query("DELETE FROM `conversations_members` WHERE `conversation_id` = {$conversation_id}");
		mysql_query("DELETE FROM `conversations_messages` WHERE `conversation_id` = {$conversation_id}");
	}else{
		$sql = "UPDATE `conversations_members`
				SET `conversation_deleted` = 1
				WHERE `conversation_id` = {$conversation_id}
				AND `user_id` = {$_SESSION['user_id']}";
				
		mysql_query($sql);
		
	}
}
?>
view_conversation.page.inc.php
<?php

$errors = array();

$valid_conversation = (isset($_GET['conversation_id']) && validate_conversation_id($_GET['conversation_id']));

if ($valid_conversation === false){
	$errors[] = 'Invalid Conversation ID.';
}

if (isset($_POST['message'])){
	if (empty($_POST['message'])){
		$errors[] = 'You must enter a message.';
	}
	
	if (empty($errors)){
		add_conversation_message($_GET['conversation_id'], $_POST['message']);
	}
}

if (empty($errors) === false){
	foreach ($errors as $error){
	}
}

if ($valid_conversation){
	if (isset($_POST['message'])){
		update_conversation_last_view($_GET['conversation_id']);
		$messages = fetch_conversation_messages($_GET['conversation_id']);
	}else{
		$messages = fetch_conversation_messages($_GET['conversation_id']);
		update_conversation_last_view($_GET['conversation_id']);
	}
}
?>
<a href="index.php?page=inbox">Inbox</a>
<a href="index.php?page=logout">Logout</a>

	<form action="" method="post">
		<p><textarea name="message" rows="10" cols="110"></textarea></p>
		<p><input type="submit" value="Add Message" /></p>
	</form>
	
	<?php
	foreach ($messages as $message){
	?>
	<?php if ($message['unread']) echo 'unread'; ?>
	<p>Username: <?php echo $message['user_name']; ?></p>
	<p>Date: <?php echo date('d/m/Y H:i:s', $message['date']); ?></p>
	<p>Message: <?php echo $message['text']; ?></p>

<?php

}
?>

Re: Private Message Errors

Posted: Mon Jun 18, 2012 9:09 pm
by jacek
Try outputting the errors here
if (empty($errors) === false){
        foreach ($errors as $error){
        }
}
instead of ignoring them all. Something it probably making the conversation invalid.

If the conversation is invalid the $messages variable will never be defined, so you need to make sure that it is before you try to use it further down the page.

It's probably meant to be that the foreach loop is only meant to happen if there have been no errors. Something like this
if (empty($errors) === false){
    foreach ($errors as $error){
        echo '<p>', $error, '</p>';
    }
}else{
    // show messages.
}

Re: Private Message Errors

Posted: Tue Jun 19, 2012 10:04 am
by AndrewD92
Doing that outputs "Invalid Conversation ID" at the top of the page. I literally cant see where I have gone wrong!

It must be one of these functions

validate_conversation_id
function validate_conversation_id($conversation_id){
	$conversation_id = (int)$conversation_id;
	
	$sql = "SELECT COUNT(1)
			FROM `conversations_members`
			WHERE `conversation_id` = {$conversation_id}
			AND `user_id` = {$_SESSION['user_id']}
			AND `conversation_deleted` = 0";
			
	$result = mysql_query($sql);
		
	return (mysql_result($result, 0) == 1);
}
function fetch_conversation_summary
function fetch_conversation_summary(){
	$sql = "SELECT
				`conversations`.`conversation_id`,
				`conversations`.`conversation_subject`,
				MAX(`conversations_messages`.`message_date`) AS `conversation_last_reply`,
				MAX(`conversations_messages`.`message_date`) > `conversations_members`.`conversation_last_view` AS `conversation_unread`
			FROM `conversations`
			LEFT JOIN `conversations_messages` ON  `conversations`.`conversation_id` = `conversations_messages`.`conversation_id`
			INNER JOIN `conversations_members` ON `conversations`.`conversation_id` = `conversations_messages`.`conversation_id`
			WHERE `conversations_members`.`user_id` = {$_SESSION['user_id']}
			AND `conversations_members`.`conversation_deleted` = 0
			GROUP BY `conversations`.`conversation_id`
			ORDER BY `conversation_last_reply` DESC";
			
	$result = mysql_query($sql);
	
	$conversations = array();
			
	while (($row = mysql_fetch_assoc($result)) !== false){
		$conversations[] = array(
			'id' 				=> $row['conversation_id'],
			'subject' 			=> $row['conversation_subject'],
			'last_reply' 		=> $row['conversation_last_reply'],
			'unread_messages'	=> ($row['conversation_unread'] == 1),
		);
	}

	return $conversations;
}
fetch_conversation_messages
function fetch_conversation_messages($conversation_id){
	$conversation_id = (int)$conversation_id;
	
	$sql = "SELECT
				`conversations_messages`.`message_date`,
				`conversations_messages`.`message_date` > `conversations_members`.`conversation_last_view` AS `message_unread`,
				`conversations_message`.`message_text`,
				`users`.`user_name`
			FROM `conversations_messages`
			INNER JOIN `users` ON `conversations_messages`.`user_id` = `users`.`user_id`
			INNER JOIN `conversations_members` ON `conversations_messages`.`conversation_id` = `
			s`.`conversation_id`
			WHERE `conversations_messages`.`conversation_id` = {$conversation_id}
			AND `conversations_members`.`user_id` = {$_SESSION['user_id']}
			ORDER BY `conversations_messages`.`message_date` DESC";

	$result = mysql_query($sql);
	
	$messages = array();
	
	while (($row = mysql_fetch_assoc($result)) !== false){
		$messages[] = array(
			'date' 		=> $row['message_date'],
			'unread'	=> $row['message_unread'],
			'text' 		=> $row['message_text'],
			'user_name' => $row['user_name'],
		);
	}
	
	return $messages;
}
Create_conversation
function create_conversation($user_ids, $subject, $body){
	$subject	= mysql_real_escape_string(htmlentities($subject));
	$body		= mysql_real_escape_string(htmlentities($body));
	
	mysql_query("INSERT INTO `conversations` (`conversation_subject`) VALUES ('{$subject}')");
	
	$conversation_id = mysql_insert_id();
	
	$sql = "INSERT INTO `conversations_messages` (`conversation_id`, `user_id`, `message_date`, `message_text`)
			VALUES ({$conversation_id}, {$_SESSION['user_id']}, UNIX_TIMESTAMP(), '{$body}')";
			
	mysql_query($sql);
	
	$values = array("({$conversation_id}, {$_SESSION['user_id']}, UNIX_TIMESTAMP(), 0)");
	
	foreach ($user_ids as $user_id){
		$user_id = (int)$user_id;
		
		$values[] = "({$conversation_id}, {$user_id}, 0, 0)";
	}
	
	$sql = "INSERT INTO `conversations_members` (`conversation_id`, `user_id`, `conversation_last_view`, `conversation_deleted`)
			VALUES " . implode(", ", $values);
			
			mysql_query($sql);
}

Re: Private Message Errors

Posted: Tue Jun 19, 2012 1:32 pm
by jacek
Well that error will only be caused by this bit
$valid_conversation = (isset($_GET['conversation_id']) && validate_conversation_id($_GET['conversation_id']));
 
if ($valid_conversation === false){
        $errors[] = 'Invalid Conversation ID.';
}
So there are a few things to check based on that.
  • Do you have a conversation_id=<number> in the URL ?
  • Is there a conversation correctly in the database ?
  • Is your validate_conversation() function returning the correct result, which is looks like it should be so do the first two first ;)