Tracking Votes and only allowing 1 vote per member - php

What I'm trying to do is count the votes when someone votes on a "page". I think I lost myself trying to figure out how to track when a member votes or not. I can't seem to get the code to tell when a member has voted.
//Generate code ID
$useXID = intval($_GET['id']);
$useXrank = $_GET['rank'];
//if($useXrank!=null && $useXID!=null) {
$rankcheck = mysql_query('SELECT member_id,code_id FROM code_votes WHERE member_id="'.$_MEMBERINFO_ID.'" AND WHERE code_id="'.$useXID.'"');
if(!mysql_fetch_array($rankcheck) && $useXrank=="up"){
$rankset = mysql_query('SELECT * FROM code_votes WHERE member_id="'.$_MEMBERINFO_ID.'"');
$ranksetfetch = mysql_fetch_array($rankset);
$rankit = htmlentities($ranksetfetch['ranking']);
$rankit+="1";
mysql_query("INSERT INTO code_votes (member_id,code_id) VALUES ('$_MEMBERINFO_ID','$useXID')") or die(mysql_error());
mysql_query("UPDATE code SET ranking = '".$rankit."' WHERE ID = '".$useXID."'");
}
elseif(!mysql_fetch_array($rankcheck) && $useXrank=="down"){
$rankset = mysql_query('SELECT * FROM code_votes WHERE member_id="'.$_MEMBERINFO_ID.'"');
$ranksetfetch = mysql_fetch_array($rankset);
$rankit = htmlentities($ranksetfetch['ranking']);
$rankit-="1";
mysql_query("INSERT INTO code_votes (member_id,code_id) VALUES ('$_MEMBERINFO_ID','$useXID')") or die(mysql_error());
mysql_query("UPDATE code SET ranking = '".$rankit."' WHERE ID = '".$useXID."'");
}
// hide vote links since already voted
elseif(mysql_fetch_array($rankcheck)){$voted="true";}
//}

You are making it too hard. Use a numeric value for the vote, +1,-1, and enforce a unique constraint on the table:
Expanded a bit:
create table votes (
pageId int references pages (pageId)
,memberId int references members (memberId)
,value int check (value in (-1,1))
,constraint votes_unique unique (pages,members)
)
Now you can "Select sum(value)..." to get what a user is up to, what's going on with a page, etc.

something like this should work for you - just replace all things image with all things code.
PHP: Star rating system concept?

Your first query is invalid as it has two WHERE clauses.

Related

Avoid data redundancy in a friends table

I am trying to design a very simple table that stores the data of friends in a community.
Therefor I store the userId of 2 friends respectively.
Goal
User wants to load his/her friends list.
t_friends Option 1:
Query
SELECT * FROM t_friend WHRE user_id = 10
10 is the current userId of the user which is looking for his friends list and he has 1 friend userId(20)
This way userId (10) finds his friend (20) BUT what if userId(20) were looking for his friends?
The query is coupled with userId.
That leads me to another design that contains redundant data:
t_friends option 2:
userId (10) loads now:
SELECT * FROM t_friend WHRE user_id=10
Similiar to that the query for userId(20) would then be:
SELECT * FROM t_friend WHRE user_id=20
But what about the redundancy? That leads me then to that query using table design option 1:
SELECT * FROM t_friend WHERE user_id=10 OR friend_id=10
I have a feeling that there is a smarter way to solve that. Do You have any experiences with that structure?
Thanks
Add field friendship_key:
ALTER TABLE t_friend ADD friendship_key decimal(22,11);
CREATE UNIQUE INDEX friendship_key_unique ON t_friend (friendship_key);
And php part:
$friends = [$userId, $friendId];
$key = min($friends).'.'.max($friends);
$q = "SELECT * FROM t_friend WHERE friendship_key = ".$key;
insert:
$friends = [$userId, $friendId];
$key = min($friends).'.'.max($friends);
$q = "INSERT INTO t_friend (friendship_key, userId, friendId) VALUES (".implode(',', [$key, $userId, $friendId]).")";
Instead of using VARCHAR for friendship key I've used decimal to minimize data for relation key.
To keep it simple just create functions:
function insertFriendship($user1, $user2) {
$key = min([$user1, $user2]).'.'.max([$user1, $user2]);
$q = "INSERT INTO t_friend (friendship_key, userId, friendId) VALUES (".implode(',', [$key, $user1, $user2]).")";
mysql_query($q);
}
function getFriendsOf($user) {
$q = "SELECT * FROM t_friends WHERE ".$user." IN (userId, friendId)";
return mysql_query($q);
}
function areFriends($user1, $user2) {
$key = min([$user1, $user2]).'.'.max([$user1, $user2]);
$q = "SELECT 1 FROM t_friends WHERE friendship_key = ".$key." LIMIT 1";
$q = mysql_query($q);
return (mysql_num_rows($q)>0);
}
I think this is the only way to store data about the relationships. When you are storing the relationship try to store the min value as the userId and max value as the friendId. make both values altogether unique and you will not get any duplicate values. When you search for users use something like below
SELECT * FROM t_friend WHERE user_id=10 OR friend_id=10
You may want to use the following query which verify if your user is not already a friend of another first :
INSERT INTO t_friend (userId, friendId)
SELECT 10, 20
WHERE NOT EXISTS ( SELECT userId
FROM t_friend
WHERE userId = 20
AND friendId = 10)
Thanks to this (french) topic about redundancy verification here.

How do I SELECT all rows WHERE from a table?

By the way, before it is mentioned, I am well aware I should be using mysqli. Thanks in advance.
This is my code:
$q5 = "select listingid FROM userlisting WHERE userid = '$_SESSION[UserID]'";
$r5 = mysql_query($q5) or die(mysql_error());
$a5 = mysql_fetch_array($r5);
The userlisting table is a 'lookup' table and has two columns:
userid and listingid
It has a many to many relationship. In other words, there could be one userid attached (associated) to multiple listingids and thus having multiple rows in that table.
e.g.
userid|listingid
1|1
1|2
1|3
2|1
etc
To keep things simple: What I want to do is check the following:
$a5['listingid'] == $_GET['id']
And if it is True I will display information and if it is False the information will not be displayed.
So on the page mywebsite.com there will be an id as so, mywebsite.com?id=[id here]. I am trying to see if the user $_SESSION[UserID] has an entry in userlisting table that matches the id of the page (well, it is a property website and the id is that of the property listing).
At the moment the code I have above just searches/checks for the first row for that userid only. In the example I gave above that would be listingid ='1' It is not seeing that row 2 and 3 also have entries in them too, listingid = '2' and '3' respectively. So on mywebsite.com?id=1 it is true, but on ?id=2 and id=3 it is coming up false, but userid = 1 has three rows with entries 1, 2 and 3.
I have been trying to find a solution for a while and I am starting to feel frustrated now. I would much appreciate it if someone could come up with a quick solution for me.
You can check both on SQL with some clause like
WHERE userid=XX AND listingid=XX
And remember to escape the get parameter ;)
PS: You can use too a while for iterate the mysql_fetch_row and search if anyone is correct. Something like:
$correct_check = false;
while($a5 = mysql_fetch_array($r5)) {
if($a5['listingid'] == $_GET['id']) $correct_check = true;
}
if($correct_check) ....
else ....
Try something like this
$page_id = $_GET['id'];
$q5 = "select listingid FROM userlisting WHERE userid = '$_SESSION[UserID]' and listingid = '$page_id' ";
$res = mysql_qury($result);
$num_rows = $mysql_num_rows($res);
if($num_rows > 0)
//your ok code
else
//fail message

Compare columns from multiple tables in one query PHP/SQL

I'm trying to change my user's news feed to only show posts from friends, instead of from all users on the site. I managed to do so doing something like this:
function friend_posts(){
global $session_user_id;
if(friends_exist($session_user_id) === true){
$friends = mysql_query("SELECT * FROM `friendship` WHERE `user_id` = $session_user_id AND `pending` = 0");
while($friend = mysql_fetch_array($friends)){
$friendID = $friend['friend_id'];
$posts = mysql_query("SELECT * FROM `posts` WHERE `userid` = $friendID ORDER BY `timestamp` DESC");
while($post = mysql_fetch_array($posts)){
$friendData = user_data($post['userid'],'username','first_name','last_name');
echo $friendData['username'].": ".$post['status']."<br>";
}
}
} else {
echo "Nothing to display. Try adding some friends!";
}
}
However, this isn't that convenient. For example, if I want to paginate, I don't know how I'd even start to do that using something like this. Also if multiple users post, how would I sort them by 'timestamp' descending?
I'm guessing the only route I can take is accessing columns from multiple tables somehow, then sorting by the timestamp, which is stored in the posts table. The friendship table just has id, user_id, friend_id and pending.
How would I go about doing that? Is there an easier way to do what I'm trying to do?
I'm very new to SQL. I don't know too much other than inserting/deleting/updating.
You could use a single statement like this:
SELECT * FROM posts WHERE userid in
(SELECT friend_id FROM friendship WHERE user_id = $session_user_id AND pending = 0)
ORDER BY `timestamp` DESC
This way you get only the posts of the friends of the current user. If you also need data from the friendship table then use a join.

MYSQL>PHP - Trouble with a query relating to function that checks if a table contains a row of user details

I am having trouble with a function that checks if a set of user entered info (username and password) exists within either of the two possible tables where this information is stored.
The first table is the users table. It contains the first set of specific user information.
The last table is the listings table. It contains the second set of specific user information.
I have basically modified my original code to include the new listings table, and hence the trouble coming from within that task. The old code basically counted the number of results in the users table, if the result was greater than 0, then the function returned true, else false.
Now I have been stuck on the best way to go about adding another table to the query, and function. So I have been playing around with a union.
This was the original query:
SELECT COUNT(*) FROM users
WHERE id='$accNum' AND password='$password'
This returned a count of either 0 or 1 based on the info stored in the users table.
This is how I have reworked the query to include a count of the additional listings table:
SELECT count . *
FROM (
SELECT COUNT( * )
FROM users
WHERE id = '$accNum'
AND PASSWORD = '$password'
UNION (
SELECT COUNT( * )
FROM listings
WHERE id = '$accNum'
AND PASSWORD = '$password'
)
)count
This returned a result set of two rows, the first relating to the users table, and the second relating to the listings table. Then a column called COUNT (*) that contained the result count. This is the result set that I see within php myadmin.
Now this is the function:
function databaseContainsUser($accNum, $password)
{
include $_SERVER['DOCUMENT_ROOT'] . '/../../includes/db.inc.php';
$accNum = mysqli_real_escape_string($link, $accNum);
$password = mysqli_real_escape_string($link, $password);
$sql = "SELECT count . *
FROM (
SELECT COUNT( * )
FROM users
WHERE id = '$accNum'
AND PASSWORD = '$password'
UNION (
SELECT COUNT( * )
FROM listings
WHERE id = '$accNum'
AND PASSWORD = '$password'
)
)count
";
$result = mysqli_query($link, $sql);
if (!$result)
{
$error = 'Error searching for user.';
include 'error.html.php';
exit();
}
$row = mysqli_fetch_array($result);
if ($row[0] > 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
The problem that I have, is trying to work out how exactly to check the results to ascertain if the given log in credentials are valid.
I tried this: if (($row[0] > 0) || ($row[0] > 0)) But a var dump on $row showed that only the first row (count of users table) was being added to the array.
So I decided that this was complicated, and a long way to the final result.
So I tried selecting only the id column of the result as in:
...
`COUNT( * )` to `id`
...
$data = mysql_query($sql);
$num_sql = mysql_num_rows($data);
if ($num_sql > 0)
...
But this did not work out for me either.
But in either instance, my hours of trial and error have provided me with no success... So I've decided to seek help from the knowledgeable members of Stack Overflow!
So my question is this, what would be a logical way of going about this task? I am looking for any suggestions, or positive input what so ever here.
As I am fairly new to dabbling with PHP and mysql, if you would like to provide some code to explain your suggestions or input on the matter, it would more than likely help me to better understand the answer.
If you are checking existence only try doing this that way:
select case when
exists (SELECT 1 FROM users WHERE id = '$accNum' AND PASSWORD = '$password') or
exists (SELECT 1 FROM listings WHERE id = '$accNum' AND PASSWORD = '$password')
then 1 else 0
end as itDoesExist
It returns always one row with one column with 1 when record exists in at last one table (else 0).
Do not use count to check whether some specific record/-s exist/-s in table, it's usually slower than simple exists.
Looks like you're going to get two rows in the result no matter what. Try this:
$sql = "SELECT id,password
FROM users
WHERE id = '$accNum' AND password = '$password'
UNION
SELECT id,password
FROM listings
WHERE id = '$accNum' AND password = '$password'
";
Now you can just check mysql_num_rows() to see if there's a match in either of the tables.
There are a couple of ways to go about this; if we are to stick with the approach you started with; you can simplify the query to:
$sql = "SELECT COUNT(1) FROM users
WHERE id = '$accNum'
AND PASSWORD = '$password'
UNION (SELECT COUNT(1) FROM listings
WHERE id = '$accNum'
AND PASSWORD = '$password')";
The reason you are only seeing one result, is because thats the way mysql_fetch_array() works, try doing this to get all results:
while ($row = mysql_fetch_array($result)) {
$data[] = $row;
}
var_dump($data);
Now you should have both values in there to validate with your conditional statements.

Update two ID's at once SQL - PHP

I have a table that's PK is an int field.
My problem is I need to swap two of the values round.
This is my current code:
$newId = (int)$id; $newId = $newId - 1;
$result = mysql_query("UPDATE homeScroller SET id = '$newId' WHERE id = '$id'") or die('error '.mysql_error());
$result2 = mysql_query("UPDATE homeScroller SET id = '$id ' WHERE id = '$newId'") or die('error '.mysql_error());
The table contains at max 3 rows that contain info for an slideshow on the frontpage of the website. The frontpage orders them by their IDs. So to change the order I need to edit the ID's.
The table contains at max 3 rows that contain info for an slideshow on the frontpage of the website. The frontpage orders them by their IDs. So to change the order I need to edit the ID's.
If that's the case, then your application/database is poorly architect-ed, and you need to re-think your database design before you go any further.
Primary keys should be immutable, i.e.: they should never change. What you're talking about doing is changing primary keys.
Fix your application/database, and you won't have this problem. Are you sure you shouldn't just be adding a new field 'sort_order' and ORDER BY sort_order instead or ordering by the ID field?
Assign one with a temporary id (0, because auto_increment usually starts at 1, so 0 should be unused):
$result = mysql_query("UPDATE homeScroller SET id = 0 WHERE id = '$id'");
$result = mysql_query("UPDATE homeScroller SET id = '$id ' WHERE id = '$newId'");
$result = mysql_query("UPDATE homeScroller SET id = '$newId ' WHERE id = 0");
IMPORTANT: However, you shouldn't rely on the primary key for ordering results, if you want to be able to change the order easily. Add a sequence column and sort by that instead.
UPDATE homeScroller
SET id = CASE id WHEN $id THEN $newid ELSE $id END
WHERE id IN ($id, $newid)
Do not use PK for this need.
If you can add timestamp field (shown_at) to this table, do it!
if cant, so update all PKs imultaneously. Just increment them.
For example: suppose we have such strings:
1 photo1
3 myphoto
5 somephoto
than use modulo 3.
1%3 = 1
3%3 = 0
5%3 = 2
increment all records
2 photo1
4 myphoto
5 somephoto
2%3 = 2
4%3 = 1
6%3 = 0
So u can use modulo and increment ids

Categories