Maintaining history table for PHP Application - php

I want to maintain the history table for my application to track what all the fields were changed by the user.
The following is my bugs_history table structure -
id, bugsid, userid, field_changed, old_value, new_value, created_on, created_by
So my query is, when I'll update my form and submit, how to get the field name that was changed along with old value and new value. And add the modified changes in the above history table.
I have googled a lot for this but didn't get as per my requirments. Please let me know how to achieve this.

If you know the field names (you have a HTML form containing them, so you probably know the names) then build a list of them that you then loop through, building a new SELECT query to get old_value and then an INSERT query to save it. The select would order on created_on DESC and LIMIT 1.
But I see a clear problem here: concurrency. What happens when two users try to edit the same bug (with the same bugsid) at the same time? They would expect the old_value to be the same for both? Or should the two operations be executed sequentially? Or should the last one to edit be warned that he's trying to edit stale data? Which one would get the "latest" created_on?
This right here is your real problem, not writing the code that generates two SQL queries.

Related

Check for new content with JS/PHP/MySQL?

I have four tables: projects, posts, users and project_users. Some users are connected to some projects via the project_users table. Each project contains a bunch of rows from the posts table. Pretty straight forward.
The users can edit the posts rows and every time an update occurs the user id and timestamp should be saved so other users can see what is new and not. Should I save this information to 1) the post row, keeping a latest editor and time for each row or should I consider 2) a whole separate log table? What are the benefits of each case?
When that is decided, I want to run a script every now and then that refreshes the site content if any rows have been updated by anyone else (poor man's push). To give me some perspective. Is it a big query to ask the database with say 1 million posts: "check if there are any posts in this project where any user other than you have updated after timestamp x"? Just asking because I'd run that query a lot.
A much quicker way would be to log the latest editor to the projects or project users rows, but with multiple people editing at the same time, that would be less accurate and there is also no way to see which rows got updated. Makes sense?
Use solution (1). It's a clean design and easy to work with.
When you fetch post data for the edit form, save the updated_at timestamp in a hidden field. Then run an Ajax request every X seconds to check if the timestamp has been changed. The query is simple:
SELECT updated_at FROM posts WHERE post_id = ?
Since you filter by the primary key, the query will be very fast even with a huge table.
Now compare the fetched timestamp with what is stored in the hidden field. If it has changed - Notify the user (editor).
As you already realized, it's possible that another user will update the post between two Ajax requests. So you should also check for updates just befor saving the form data. Don't forget to use a transaction and lock the row:
Pseudo code:
START TRANSACTION
SELECT updated_at FROM posts WHERE post_id = ? FOR UPDATE
if ($row->updated_at == $form->updated_at)
then update row
else notify the user that he is unlucky ;-(
COMMIT
Of course you can also use solution (2) and add a separate table post_updates(post_id, user_id, updated_at). To get the latest timestamp you would run:
SELECT MAX(updated_at) as updated_at
FROM post_updates
WHERE post_id = ?
It should run pretty fast with an index on (post_id, updated_at). But don't complicate things as long as you don't have any requirements which would benefit from that table.

Tagging pages with PHP and MySQL

I'm fairly new to MySQL and PHP, but I'm getting the hang of it slowly.
I'm working on a site with profile pages. I have a users table in my database and I intend to create a profile table too.
Before I explain my 'problem' I'd like to say I haven't actually began coding an attempted solution. I like to plan my work before I start it, especially when it is going to be complex. Therefore, I can't really display any snippets of code.
What I would like to create is a tagging system for the user profiles. ie. let the profile owner select keywords from an existing list, and associate them with his profile page.
After pondering plenty and reading up on relational databases I gathered I should start by creating two additional tables:
1. tags (tag_id, tag_name)
2. tag_rel (tag_id, user_id)
and create a relationship between each profile to the different tags a user assigned to it, on seperate rows:
(Tag1, UserA)
(Tag2, UserA)
(Tag1, UserB)
etc.
Then when I search for profiles I simply have to select all user_ids with a specific tag_id. Easy enough.
My issue is the PHP and MYSQL Query code when inserting or changing the list.
I would essentially want the user to be able to either choose from a check-list or from a drop-down select list (or anything equivalent) of existing Tags, check or uncheck his selection, and send to enter it to the database.
I can imagine the initial entry of the selected tags is easy enough to achieve with a foreach() function and a simple INSERT query, and enter the array from the form one value at time.
But when the user goes back to change the tags, how would I instruct a query to keep some tags, delete others, and insert new ones in? What is the best method to do something like this?
An Idea:
Should I delete all the existing rows the user has in tag_rel, and insert the new array?
I would use a procedure like this:
at first you fetch the tags a user selected out of the db and pass them to an array (SELECT from tag_rel where user_id = $userId)
then you would go over to let the user operate on the array (adding new tags, deleting old one)
at last you would delete the old entries and insert the completely new ones from the array provided
the simplest method is to delete tag_rel data for that particular user_id then re-insert the new ones

Check for value in CSV MySQL row

I am storing user ID values in a table field separated by a | (user_id1|user_id2|user_id3|user_id17).
A user ID will be added and removed from this field at certain points.
How can I check if the current users ID exists in the field or not using a query?
And it of course needs to be an exact match. Can't look for user_id1 and find user_id17.
I know I could use a SELECT query, explode the field, then use in_array but if there's a way to do it using a query it'd be better.
I guess I'll explain what I am doing: I made a forum for a small private website (7 users), but coding it for larger scale.
My table structure is pretty good: forum_categories, forum_topics, forum_posts. Using foreign keys between the tables for delete and update queries.
What I am seeking help on is to mark Topics as unread for each user. I could create a new table with topic_id & user_id, each one being a new row but that wouldn't be good with alot of users & topics.
If somebody has a better solution I am all for it. Or can prove to me that 1 row per user_id is the best way then I'll be more than willing to do that.
I think you want to track read messages, not the other way around. If you tracked unread messages, every time you add a user you'll have to add that user to every topics "unread list".
I looked into SMF like my comment suggested. They are using a separate table to track read messages.
A simple table that holds user_id and topic_id are you are need. When a user reads a topic, make sure there is a row in the table for that user.
Another reason to use a separate table. It's going to be faster to query against 2 int values in the database than to use LIKE % statements.

update existing entry practices

I have an application that allows users to enter reports, there are multiple tables that keep track of the data.
I am working on making an edit form to allow the user to edit an existing entry.
I need help with handeling the update query. Not the actual query, but understanding the best way to handle this.
For example:
A user adds an entry, they could select multiple departments.
Next, they edit that same entry, and select more departments and unselect a couple departments (from when they originally added that entry).
There is a table that keeps track of the entry and what departments it relates to: entry_id, department_id
When doing an update query, how do I update that table appropriately? Do I delete all entries where entry_id = 4 (just using any old number), and then just do an insert w/ all the departments that were selected? I am looking for best practices.
I am not asking for code that does, but just theory.
That looks like a good strategy to me. The alternative is to get the set of existing IDs, remove the IDs of this set that are not in the new set, and add the IDs that are in the new set but not in the old one.
But unless you need to keep some additional metadata on the association (time of creation, for example), the delete all and recreate approach is much simpler.

Issues in sorting image-wise

I have a table in which there are fields like user name, name, age, activity. In this if new user is added then an image is shown beside that user name.
Until now sorting was done by activity by default, but I want all the newly added users to be shown first in the table by default, how can i sort in this case?
Any hint?
Without knowing, well, anything, about how you're implementing this, it's a bit tricky.
If the data from the table is coming from a database and you're already sorting based on some activity field, then your query just needs to sort on an additional field: instead of ORDER BY activity you might have ORDER BY isnew, activity or ORDER BY image, activity.
Alternatively, if the data is just in a PHP data structure, then you could just do a two stage render of your table - iterate through and write out rows with an image, then again for the ones without.
You need to change your sql query - something like:
SELECT * FROM `users` ORDER BY `created` DESC

Categories