php / mysql members and marking function

I’m creating a messageboard for a team of volunteers. On this board people can write messages. These messages can be marked as read. Underneath each message a table with photos of the members is shown. The url of this photo is stored in a database. If a member clicks on his photo this photo changes to another image, so he know he has red the message. This function is working just fine.

But all these photo’s are added manually into the script. This means that whenever a new volunteer joins our club, I have to change the code (add his name) in order to have him marking too.

What I need is that the volunteers are automatically connected to the table. So, if I add a volunteers name into the database (without editing the code), his photo will be displayed too. And whenever I delete a volunteer, his photo won’t be displayed anymore.

I can achieve this by creating a database holding all volunteers names and create a mysql_fetch_array function right beneath the message. But when I do this and volunteer A clicks his photo, all photos of volunteer A changes, not just fot the message he just has read, also all the other message are marked too. I need that every message gets a unique row of photos that can be marked, so that the user knows he has marked that single message, not all of them.

How can this be achieved?

What I have right now:

The database db_users

id (AI), primary
name (varchar), 255
address (varchar), 255
email (varchar), 255
stillActive (varchar), 5 //if `value` is set to yes, his photo is displayed beneath a message. If `value` is set to no, his photo won't be visibile anymore.

The database db_messages

 id (AI), primary
 name (varchar), 255 //the name wo entered the message
 message (varchar), 999 //the message itself
 urlUserA // the url of the photo of volunteer A
 urlUserB // the url of the photo of volunteer B
 urlUserC // the url of the photo of volunteer C

The mark_read.php

$sql2 = "SELECT * FROM $tbl_name WHERE id = ".$_GET['id']; //to get the specific message
$result2 = mysql_query($sql2);
$url = $_GET['url']; // the url of the MARKED image				
$recover = $_GET['recover']; // the url of the UNMARKED image		
$tabel = $_GET['tabel'];
$id = $_GET['id'];
$date = $_GET['date'];
$row = mysql_fetch_assoc($result2);			
$tabel_content = $row[$tabel];

if ($tabel_content == $url){
	$sql = "UPDATE " . mysql_real_escape_string($tbl_name) .
       " SET ".$_GET['tabel']." = '".$_GET['recover'].
       "' WHERE id = ".$_GET['id'];
  $result = mysql_query($sql);
} 
elseif ($tabel_content == $recover) {
	$sql = "UPDATE " . mysql_real_escape_string($tbl_name) .
       " SET ".$_GET['tabel']." = '".$_GET['url'].
       "' WHERE id = ".$_GET['id'];
  $result = mysql_query($sql);
}

The if code above is used to see whether the user already marked the message or not. If it is marked and he’ll click his photo again, the photo will be unmarked again.

As you can see, if I need to add a new volunteer, I have to add a table to the database, change the code of add_message.php. A lot of work. I need something that whenever I add a user into the db_user and save it, he’ll be able to mark messages too, without having to create a new table urlUserD before he can use it.

Any help on this will be very much appreciated.

The message is added using this page:

addMSG.php

mysql_connect("$host", "$username", "$password")or die("cannot connect");
mysql_select_db("$db_name")or die("cannot select DB");

$subject = $_POST['subject'];
$date = $_POST['date'];
$message = $_POST['message'];
$name = $_POST['name']; // the name from the person who posted the msg

$sql="INSERT INTO $tbl_name(
date,
archive,
year, 
message, 
name,
subject
)
VALUES(
'$date',
'no',
'2014', 
'$message', 
'$name',
'$subject'
)";

$result = mysql_query($sql);

How (and where) do I add code in order to bind all the users to the newly created message?

Well, first, you do not want to store a picture inside of a database. It just is not practical as it causes a lot of overhead on the database and slows things down. But, there are many solutions.

The easiest is to store the name of the picture in the database or just hard code the name for the pictures.
So, in your code, you assign an ID to each and a name. These would not change unless you delete them.
You can use a simple upload system to upload their picture on the same form where your create their ID.
(I am assuming you are uploading them manually at this point.) This can be done with just a few lines
of code. Here is a tutorial on how to do this part:
http://www.w3schools.com/php/php_file_upload.asp

But before you code it, think of the picture. You should set a standard on the size, type, etc of them.
Next, when you move the picture to your folder on the server, you should rename them to match the
ID or the name of the user. Since you do not have the ID number until after the user is created, you can
use the name. So, my picture would be changed from “Ernie On Vacation.jpg” to “Ernie.jpg” or whatever
my name is entered as. In this way when you display the picture back, when a user logs in, their pix can
be loaded from the set folder location by just adding .jpg to the end of their name.

So, if you handle it this way, you do not need to alter your code for storing a newly added message.
You already store the person’s name in that table. But, when you display the message, load this name
and create the picture name using that. Something loosely like:
$pix_location = “\images” . $name . “.jpg”;

This would point at the folder where you save your pictures on the server plus the name of the user
and the extension for the the images. (To make it simpler, use the same type of pixes.)

Then, just load and display the picture as you normally would, but, use the $pix_location variable to
steer to the one you want to display.

Hope that is what you were looking for. Good luck…

yeah, thanks. My mistake. Didn’t explain it well… The images isn’t the problem, because they are loaded exactly the way you describe it. What I need is this:

Message 1
A-U | B-U | C-U | D-U

Message 2
A-U | B-U | C-U | D-U

etc.

in this example, the first capital is the user (user A, user B, etc) and the second capital is the state (U= Unread, R = read)

If I’m user B and I’ve red the first message, I click on B-U beneath the first message (these are originally the url of the photo). B-U changes after clicking it to B-R (so I know I’ve red the first message). If user C clicks on C-U beneath message 2, this is changed to C-R (just for the second message, the state of C for the first message stays unchanged.

This way everybody will know who has red which messages.

Well, since you have the message stored inside the database, you just have to mark it read or not read there.

Add a field called “read” to the message records. Make it, let’s say varchar(6) which would give plenty of room for expansion later on if needed.

When the message is created, enter “unread” in that field.
Displaying the message, you have to load the message data anyways. Just check this value if the “read” field contains “unread” show the U part. If it does not show “unread” then display the R part.
Once the user has clicked on the message and read it, you “UPDATE” the database and change that field to “read” or “seen” or “viewed” or whatever you want to indicate it has been viewed.

So, remember, you can use an “UPDATE” query to alter data already stored inside the database. You would just need to know when to run that query. In this case it would be in the form you display when a user is reading his message. There would be a button that says “Go back to message list” or whatever. When the user presses that after reading the message, it should run a short script to mark the message as “read” and then go back to the message list.

Did that make sense? If not ask away… Good luck…

Yes, it does make sense. But my question is not about the marking-section. This works just fine.

If a user creates a new message, I need a table beneath this message. Inside this table all photos will be shown (the pictures which can be clicked). But I need the page to see which users (and how many) it needs to create. I have a table with all users. Let’s say it contains

user A | user B | user C | user D | user E

if some of these users creates a new message, the code needs to see which users are stored and display them (the existing users) beneath the newly created message.

If I add user F to the table, all messages are updatet, so user F will see his photo from then on too. If I delete i.e. user C from the table, the next time I open the page the list of user will be

user A | user B | user D | user E | user F

Now, then, after this is done, every message needs to have a unique row of users, otherwise if user B clicks on his message, all photo’s of user B will change, not just the one beneath the clicked message.

Hope I explained it better now? Appreciate your help!

Well, not really exactly sure, but, getting further in what you want.
Let’s back up… Messages and users are displayed like:
Message#1
user1-R/U user2-R/U user3-R/U
Message#2
user1-R/U user2-R/U user3-R/U

To handle this, you would need a list of all users and messages first.
But, to show it, the higher-level group is message number, so that needs to be first.

So, when your page loads, it first runs a query to load all of the messages.
Something like "SELECT * FROM message_table WHERE status=‘active’ " or similar.
(However you mark a live message different from an archived one would be in the WHERE part!)

This creates the list of all active messages. You would loop thru this list displaying each message.
foreach($row as $message) {handle message display…}
This would display all your messages in your table as one entry inside the table row and col.

Now, here inside the brackets for displaying the message, you would need to add another loop.
This loop lets you build your A-B-C-D-F or A-B-D-F if user C is deleted.
For this part, you do another query something like “SELECT * FROM users_table” or similar.
This gets all your users. (Actually, you only need to do this once, so do it just after retrieving messages.)
In the message record which was pulled out of the first query and placed into the $row array and which
we are inside of with the one message in a variable called $message, there would be a list of user ID’s
that have already viewed this message. You would have to see if the current user ID is in the list of the
message’s viewed list. If so, set it as read. When you display it, display R/U depending on this variable.

Did that help? I have to leave for an hour or so. If you need more help, I will check when I get back.

By the way, do you have a test page set up for us to peek at? I mean just the output of this small part so we can see what it should look like live? Might help if you create one small test page. Just don’t post any passwords or ID’s or whatever.

I do, it’s written in Dutch though, so I hope you’ll manage your way through :wink: but it’s a very basic page with googled images, just to give you an idea. Click and write as you want, it’s a demo page. “bericht opstellen” means “write message” . “onderwerp” = “subject” and “bericht” = “message”. :smiley:

http://www.entertainyou.nl/whatsup/demo/berichten.php

b.t.w. the extra line beneath each message is a comment line, this doesn’t involve the problem. Comments don’t need to be marked, just the messages, which are entered using the blue box on the right side which says “Bericht opstellen”.

Okay, now I see. If the user has read the message, their picture changes to a greenish-thumbsup pix.

Nice, simple layout, very easy on the eyes. And, looks like it will be fun to use.

So, it takes us back to how to you mark the message as read or unread. You have many ways to do this.
But, first, I would suggest doing some design work before we jump into a big change.

The first two questions are how many messages might be live at any one time? And, what happens to them when all the users have read them. Do they just dissappear? Also, how many users might be active at any one time?

Why? Well, if there are a small number of users, you could save all of the unread ones in a simple array inside each of the messages. (In the format user1~user2~userD~userETC) then, this can be read out with ease into a temp array and each one that is not there is READ. That would be quite easy to do.

If a lot of users will be using the system, you would have to do it a different way. Give me an idea of user count and I can help you work out a solution…

Well, what’re a lot of users… approx. between 5 and 25. The number of messages I really can’t say. Sometimes just 4, but there are days (like today) that 40 messages are online. If the last user clicks it, nothing happens. The last user has to delete it manually, because sometimes the message needs to stay online because of the comments. If you can help me to the solution I definitely own you a beer :slight_smile:

LOL, 25 max users? That is not much… And, 40 messages is not much… Lots of ways to handle your project.

I have an easy way that is great for 25 users. My worry was if you had 100 or 200 or whatever…
25 is not an issue.

So, I will map something out for you to try. The only problem is it is midnight here now and I need to get to bed soon. I will send you some ideas tomorrow. Should not take long to sort it all out. easy enough.

And, for closing it after everyone sees it, I have a couple questions on how you handle comments.
More on that too tomorrow. We can get you all fixed up in another day or two… More then…

Okay, lets discuss what you are trying to attempt first and then I will explain the greatest downfall of programmers learning database usage. (Most people fall into that trap and I can explain it quickly for you!)

First, since I do not know your overall system and it’s use, I am just guessing on how it all works. I really do not need to know all the details as we are working on one issue here. So, you have member’s that create messages. They ‘post’ them and your system displays them. As other members read them, their icons change to show they have read the message. (A type of receipt verification system.) Now how do you indicate that they have read the message inside of your database. Am I correct up to this point on the problem?

Assuming so… Most programmers learning databases tend to deal with data in groups and store the data in odd ways. We could create an array of each of the members and place “have-read-message” markers into the array. Then, we can easily store the array into a database record. We would save this array inside of the message record itself as it would be useful to pull the “have-read-message” markers at the time we are displaying the message. (And just test each member’s marker as we display their icons.)
The second way would be to create multiple message records for each message and let the SQL system handle grouping them. Actually this is the way it should be done, but, most people do not understand how database systems actually work. In this manner, you would have a different record for each message/user combo. There would actually be two tables used, one for the messages and one for the user’s markers.

Now that I have totally mixed you up… Each way is good for different reasons. The first, storing all user-markers in an array is great if you have a low number of entries. (Which you do) The second way which is really the correct way, is more complicated due to having an extra table and links from that table back to the message table. This is not needed for your use since you have a very small number of entries in both the number of messages and users. I have one database with an artificial memory system I am building that has 3 million entries and is parsed using hundreds of users, so 25 users and 50 messages is just a drop of water in the ocean.

Therefore, I think for you use, the array version is easiest. Sorry if explaining the other version, but, as you progress it is good to know about it and you did seem interested in the learning process.

Now, how it will work. Just a couple simple steps to add to what you have already in place.

First, in your current setup, you have the message as the main item. So, when the message is created, you would add a new array field in the database. Let’s name it “viewed”. You can call it whatever you want but for my explanation, “viewed” works. This array will hold the ID’s of each and every member/user you have. You can create that using a query from the user’s table and loading each ID into the array. Your user’s table correctly has an “autoincremented” ID field. Therefore every user has a number. So, at the beginning of your message creation code, you query the user table and pull the ID’s out. You do NOT care how many, or who they are attached to at this point. Just something like “SELECT id FROM user_table” which would grab all of the id’s for you. This gives you a list of “current” id’s for all user’s. If a user is deleted, then this list is always correct as it grabs only the live ones. Should make sense to you up to this point. Now store that list of ID’s into an array. Lets call it “user_ids” which explains what it is.

So, this would be the steps when a new message is created…

1 - get the message, creator, whatever other data you need from the posted form
2 - create a new (up-to-date) list of all users using the select I just explained
3 - write the new message out placing the new “user_ids” array into the new field “viewed”

So, this is different from your old routine as it adds a list of ID for everyone. The next step is to alter the message display code. In that area, when the message is displayed and you go to display the icons for the users, you would have already loaded the data for the message. In reading the message text data from the database, you would also retrieve the “viewed” field storing it in the “user_ids” array. (Our list of ID’s) While looping thru the display of the icons, you check that user’s ID# and see if it is inside the “user_ids” array. If it is there, display their icon, if it does not exist in the array, then display the thumbs-up icon.

The last step is when a user clicks their icons to read the message. In that code, you “UPDATE” the message record to show they read the message. To do this, you get the “viewed” field for that message and delete their ID# from the array. Then, “UPDATE” it back.

What this does is keep a list of NOT-READ user id’s inside the message. As user’s read the message, their ID’s are removed from the saved array inside the message dataset. Once all of the members have read them, the array will be empty and you can test. Since you have to load the array when preparing to display the message, you can just check for an empty array and not display the message or delete it or whatever you wish to do with it once everyone reads it.

Now the last item to discuss is the comment made to messages. You mentioned that there are possible comments made back to messages. I assume that these comments should be read also. If you are not forcing members to read ALL comments, then do nothing more. If you want everyone to read the comments, too, then it is like a new message and if someone comments, they reload the “viewed” array with all the ID’s and everyone has to read them again.

Hope all of that makes sense. Now onto programming it all. I suggest you give it a try first and we can help sort it out as you run into walls. This is actually quite simple with little code needed. It just needed to be explained in detail as you have never attempted it before.

Try it out, first by just getting a list of all user ID’s saved into the message records and read back out again.
Post your routines if you have a problem with them.

Good luck. And, sorry for such a long post…

You’re sorry? I should thank you for taking all the effort helping me! I’m still new to this “array thing” so thank you for explaining it both ways.

I’ll do this steep by step, so I don’t get mixed up.

Now, I have:

[php]mysql_connect("$host", “$username”, “$password”)or die(“cannot connect”);
mysql_select_db("$db_name")or die(“cannot select DB”);

$subject = $_POST[‘subject’];
$date = $_POST[‘date’];
$message = $_POST[‘message’];
$name = $_POST[‘name’];

$query=“SELECT id FROM user_table”;
$result2 = mysql_query($query) or die(mysql_error());
$user_id = array();
while($row = mysql_fetch_assoc($result2))
{
$user_id[] = $row;
}

$sql=“INSERT INTO $tbl_name(
date,
archive,
message,
name,
subject
)
VALUES(
‘$date’,
‘no’,
‘$message’,
‘$name’,
‘$subject’
)”;

$result = mysql_query($sql);[/php]

If I echo the $user_id it echoes:

Array ( [0] => Array ( [id] => 1 ) [1] => Array ( [id] => 2 ) [2] => Array ( [id] => 3 ) [3] => Array ( [id] => 4 ) [4] => Array ( [id] => 5 ) [5] => Array ( [id] => 6 ) [6] => Array ( [id] => 8 ) [7] => Array ( [id] => 9 ) [8] => Array ( [id] => 10 ) [9] => Array ( [id] => 13 ) [10] => Array ( [id] => 14 ) [11] => Array ( [id] => 16 ) [12] => Array ( [id] => 17 ) [13] => Array ( [id] => 18 ) [14] => Array ( [id] => 19 ) [15] => Array ( [id] => 20 ) )

all the id’s that are inside the user_table. So this seems to work for me.

Where do I add this array? Will it be something like:

[php]$sql=“INSERT INTO $tbl_name(
date,
archive,
message,
name,
subject,
viewed
)
VALUES(
‘$date’,
‘no’,
‘$message’,
‘$name’,
‘$subject’,
‘$user_id’
)”;[/php]

Am I right till this point?

Or do I need to make a foreach loop?

You are getting there. I was just sorry because some people can explain a lot in a few words, but, I like to be thorough so the reader gets it all. Just as you seem to be able to…

So, if you loop thru your $user_id and print each ID one at a time, does it print all of the live ID’s now?

Saving the should work as-is. The best way is to try it and log into your database control panel and view the live data inside the data base. (Just create a new message, view live data and see what is in the “viewed” field!)

Basically stored in the database should be the actual output of the array you showed in your post.

Now, with those behind you… Next, in the section where you pull the message out of the database, you should define the $user_id array before you load it. You want PHP to be aware it is an array before you load it with the data inside the database field “viewed”. Makes sense…

So, you can save the full list of users. You can save it inside a message. And, we just talked about retrieving it out. Just left is when the icon is checked or however you do it, to remove that one ID from the array. This is quite easy, but, here is a link that removes “strawberry” from an array of fruit. It is easy to do it this way as you already know the ID of the user and you don’t have to do much work to remove one ID from the list…
Should help: http://stackoverflow.com/questions/2448964/php-how-to-remove-specific-element-from-an-array

Oh, also, when you pick an icon to display, first you check the user_id array to see if they are in it. If they are, then, they have NOT read the message. Use this for testing: if ( in_array($the_id, $user_id))… This is used in the format in_array(needle, haystack) (actual PHP.net words, not mine.) or in_array(item, array)…
If it does NOT exist in the array, then they have already read the message.

Lastly, once they do read the message, you just have to remove their id number from the array and UPDATE to the database.

So, you have made some headway… Nearly done by the looks of it. Good luck…

Just to be sure, do I store the whole value of the array in 1 table? And if yes, what is this table gonna be like? A varchar?

Or do I need to create a for each function, so when a message is created, this message will be inserted as many times as the number of users?

I would say option 1, this seems the easiest way (to me) for php to put it back in an array as soon as the value will be loaded again.

So, the size might make a difference in the varchar size if you use that or you could use text.
But, the issue is how is it handled. Well, an array is just text basically ! So, saving the data into
the database in any type of text format will work. When you read it back out, you must ( MUST )
save place it back into the format it was originally set up as. So, if it is just an array, then, load it
into an array. So, save the array as text. Then, when you retrieve it, you load it into an array and
it should be the same array you started with.

I would suggest you doing some off-project testing on this. Just use a test table in your database
and load and save an array of “fake” or “test” data and try to read it back and display both the
test array before saving and after you retrieve it from the saved database version. They should
be the same. So, in this way, you can save just about any type of data array and retrieve it for
future use.

Since it will still be an array of ID’s, you can parse thru it to show items in it or in our case just use
in_array functions to check if some ID is inside it…

This is actually simpler than it seems. But, if you create a test page to see how it works, it will make
much more sense to you. I always suggest that anyone learning tools, programming, routines or
just code, well, test it and make sure you understand it before you put it into your “live” code.

So, the answer is… It should be the same as before you store it. But, TEST it so you understand it!

Good luck and let us know what you need next…

I might look like a complete fool now but,

if I add a message using this piece of code:

[php]$query=“SELECT id FROM db_users”;
$result2 = mysql_query($query) or die(mysql_error());
$user_id = array();
while($row = mysql_fetch_assoc($result2))
{
$user_id[] = $row;
}

$sql="INSERT INTO $tbl_name(
viewed
)
VALUES(
‘$user_id’
)
";

$result = mysql_query($sql);[/php]

it just insert the word “Array”. Nothing else. No ID’s, no values, just the word “Array”. The structure of the table is set to “text”. But if I add this line of code:

[php]if($result){
print_r($user_id);
}[/php]

it prints all ID’s, all values and everything on screen. Why can’t it INSERT the same values into the database?

Well, never like to use the word foolish when programming. Everyone, including me has those days…

So, your insert is invalid.
You have " INSERT INTO $tbl_name(viewed) VALUES($user_id)"

What is the name of the messages table where you are inserting the viewed ID’s?
I mean, if I remember correctly, you have a table named “messages?
And, that is where you are planning on saving the live messages, correct?
So, when you create a new message there, it is something like, just roughly as I did not see your code:
INSERT INTO messages (message_owner, message_date, viewed) VALUES (“Jeff”,“5-21-2014,””)
That inserts a new record into your “messages” table with the 3 values for the 3 fields listed…

So, in your code: INSERT INTO $tbl_name (viewed) VALUES( ‘$user_id’) , you it should work, but,
what is the table name? It should not be a variable $tbl_name unless you set that up on purpose
for some reason.

Since the data is accurate inside of the $user_id variable, I will assume it is not finding the correct name
of the database table. Which I thought was “messages”.

Did that explain it? Hope that was the problem. Let me know…

No, not really :-[ To keep it clear and simple I didn’t post the other values, because it is actually inserting all the other values, like name / postdate / etc. But the values of the array (so the ID’s of all users) aren’t inserted. Here’s just the word Array.

So instead of (what I want)

ID NAME DATE_OF_MSG VIEWED
1 Jeff 2014-05-22 Array ( [0] => Array ( [id] => 1 ) [1] => Array ( [id] => 2 ) [2] => Array ( [id] => 3 ) [3] => Array ( [id] => 4 ) [4] => Array ( [id] => 5 ) [5] => Array ( [id] => 6 ) [6] => Array ( [id] => 8 ) [7] => Array ( [id] => 9 ) [8] => Array ( [id] => 10 ) [9] => Array ( [id] => 13 ) [10] => Array ( [id] => 14 ) [11] => Array ( [id] => 16 ) [12] => Array ( [id] => 17 ) [13] => Array ( [id] => 18 ) [14] => Array ( [id] => 19 ) [15] => Array ( [id] => 20 ) )

it looks like this

ID NAME DATE_OF_MSG VIEWED
1 Jeff 2014-05-22 Array

all the other ID’s (which are inside of the array), which I need the most, aren’t inserted, like I said, just the word “Array”.

Well, I guess you can not do it that way as arrays have been altered from the way I had done in the past.

So, I found solutions of various levels. If you have a one-dimensional array, you can use
IMPLODE and EXPLODE to save and recreate them. Such as changing your array into 1,2,3 text.

Or, for all arrays including multi-dimensional ones, you can “serialize” the data and recover it the
same way. This seems the simplest way. Here is a link that explains how to do it…
http://99webtools.com/how-to-store-array-mysql.php

I think it should fix that issue. Let us know how it did for you.

Sponsor our Newsletter | Privacy Policy | Terms of Service