Update counter using php and mysql in a session - php

Problem: I want to connect two tables files and counter according to the paper_id column from files table connecting with the visitors column from counter table.
There are two pages; publicationView.php and profile.php.
When a reader clicks publicationView.php, php code should count the view of the page according to the publication id and only update using session.
When a user visits his profile.php, then he can see his publications in a table with the publications' views relatively.
There are two tables; files where all the publications are and counter where the counter are. I am trying to update using the URI of the publication and the URI is saved in counter table.
Implementation:
The publicationView.php includes
$webpage=htmlspecialchars($_SERVER["REQUEST_URI"]);
$sql = "CREATE TABLE IF NOT EXISTS counter (
id int(4) NOT NULL auto_increment,
webpage varchar(90) NOT NULL,
visitors int(11) NOT NULL default '1',
PRIMARY KEY (id)
) ENGINE=MyISAM AUTO_INCREMENT=1";
mysql_query($sql);
$result=mysql_query("SELECT * FROM counter WHERE webpage='$webpage'");
$num_rows = mysql_num_rows($result);
if ($num_rows == 0){
mysql_query("INSERT INTO counter (id, webpage, visitors)
VALUES ('','$webpage','1')");
}else{
if (!isset($_SESSION['webpage'])){$_SESSION['webpage'] = 0;
mysql_query("UPDATE counter SET visitors=visitors+'1' WHERE webpage='$webpage'");}}
The profile.php includes
The code to echo our the visitors column from counter table.

Change '1' to simply 1 in,
if (!isset($_SESSION['webpage'])){$_SESSION['webpage'] = 0;
mysql_query("UPDATE counter SET visitors=visitors+'1' WHERE webpage='$webpage'");}}
Change it to
if (!isset($_SESSION['webpage'])){$_SESSION['webpage'] = 0;
mysql_query("UPDATE counter SET visitors=visitors+1 WHERE webpage='$webpage'");}}

Related

PHP update mysqli only works until closing browser

I have a question about the update function in mysqli.
For school, I'm trying to create a click counter for my website which counts how many times a user has visited a certain page.
So far I've come up with this:
<?php
/*
* ToDo: Check why number of clicks goes back to two when completely
* refreshing page.
*
*/
include("init.php");
session_start();
//Count variable
$clicks = 0;
//Query for checking if there are any entry's in the database
$query = "SELECT * FROM `beoordelingen`.`clickcounter` WHERE `game_id`={$id}";
$result = $conn->query($query);
//If query returns false
if (!mysqli_num_rows($result)) {
//Create entry in database
$insert = "INSERT INTO `beoordelingen`.`clickcounter` (`ID`, `game_id`, `clicks`) VALUES (NULL, '1', '1');";
$createEntry = $conn->query($insert);
}
//If query returns true
else {
//Setting the number of clicks equal to $clicks
while ($data = $result->fetch_assoc()) {
$clicks = $data['clicks'];
}
//Insert new number into database
$sql="insert into `clickcounter` set `clicks`='{$clicks}', `game_id`='{$id}'
on duplicate key update
`clicks`=`clicks`+1;";
$insertInto = $conn->query($sql);
//Echo current number of clicks
echo $clicks;
}
?>
The actual problem is that my update statement doesn't seem to work properly. If anyone would be able to spot why it doesn't work I'd be very happy.
The database is as following;
Beoordelingen <- Database
clickcounter <- Table which has the following three columns:
1. ID
2. game_id
3. clicks
The scripts does add an entry into the databse with click count 2. So when I reload the page it says 2. And when refreshing it counts up, but doesn't update the table.
Thanks! If anything is unclear please ask me!
Theoretically you should be able to do all of it in one query if game_id is unique.
Given the following table structure the sql query below will insert if the relevant record does not exists and then update if it does.
create table `clickcounter` (
`id` int(10) unsigned not null auto_increment,
`game_id` int(10) unsigned not null default '0',
`clicks` int(10) unsigned not null default '0',
primary key (`id`),
unique index `game_id` (`game_id`)
)
engine=innodb;
The trick is setting the indices on your table correctly ~ initially you don't know the value of the ID and I would guess that is an auto increment primary key? So, set a unique key on game_id...I hope it helps!
/* Could even change `clicks`='{$clicks}' to `clicks`=1 in initial insert */
$sql="insert into `clickcounter` set `clicks`='{$clicks}', `game_id`='{$id}'
on duplicate key update
`clicks`=`clicks`+1;";
<?php
include("init.php");
session_start();
/* Where / how is "$id" defined? */
/* insert new record / update existing */
$sql="insert into `clickcounter` set `clicks`=1, `game_id`='{$id}'
on duplicate key update
`clicks`=`clicks`+1;";
$result = $conn->query( $sql );
/* retrieve the number of clicks */
$sql="select `clicks` from `clickcounter` where `game_id`='{$id}';";
$result = $conn->query( $sql );
while( $rs=$result->fetch_object() ) $clicks=intval( $rs->clicks );
echo 'Total clicks: '.$clicks;
?>

MAX id from Primary Key and add 1 in PHP

I'm trying to obtain the max primary key in the REDES table in order to add one but it's not working. I was also wondering if this would be the best way to do it and if it's secure.
// mysql inserting a new REDES field
//$redes_maxid = mysql_query("SELECT MAX(id_redessociales) AS id FROM REDES");
//$newmaxid = $redes_maxid + 1;
$redes_maxid = mysql_fetch_row(mysql_query("SELECT max(id_redessociales) AS id FROM REDES"));
$newmaxid = $redes_maxid[0] + 1;
mysql_query("INSERT INTO REDES(id_redessociales, facebook, twitter, linkedin, pinterest) VALUES ('$newmaxid', NULL, NULL, NULL, NULL");
Thanks!
What you're doing is very unsafe and wrong.
This is why we have auto increment fields in databases, just set the id field in your table to auto increment then when inserting a new row simply pass in NULL for the id, MySQL it will automatically do this increment for you safely.
here's a link to the documentation
You can get last id by ordering in descending order and limiting 1 row result
replace this line
$redes_maxid = mysql_fetch_row(mysql_query("SELECT max(id_redessociales) AS id FROM REDES"));
with
$redes_maxid = mysql_fetch_row(mysql_query("SELECT id_redessociales AS id FROM REDES order by id_redessociales DESC limit 1"));
exactly what A.B said
But shouldn't you be making the ID's row in the database auto incremented?
you can set it to auto increment and when you insert a record just make the inserted ID NULL, the database will automaticly number it to the last ID+1
if you are ysing mySql then you can use this SQL statement
ALTER TABLE `myTable` CHANGE `id` `id` TINYINT( 3 ) PRIMARY KEY UNSIGNED NOT NULL AUTO_INCREMENT

How to store Profile Views to show each user who's viewed their profile?

If we wanted to show each user which users of the opposite sex have viewed their profile, what would be the best way to keep track of all those views in MySQL?
Each user has a unique userid from the main Users table, which also stores their sex.
We would want to show each user the users that viewed them in order of most recent view to oldest view.
We would obviously not want to show the user themselves if they happened to view their own profile.
We would want to show guys only the girls that viewed them, and the girls only the guys that viewed them.
How would we setup the table of ProfileViews to do that?
What indexes would we use?
What would be the query we would need to show each user who has viewed them?
This is a simple example that I will make for you, hope this helps.
SQL:
CREATE TABLE user
(
user_id BIGINT NOT NULL AUTO_INCREMENT,
sex VARCHAR(10) NOT NULL,
CONSTRAINT PK_USER PRIMARY KEY (user_id)
) ENGINE=INNODB;
CREATE TABLE profileview
(
profileview_id BIGINT NOT NULL AUTO_INCREMENT,
user_id BIGINT NOT NULL,
visitor_user_id BIGINT NOT NULL,
date_time DATETIME NOT NULL,
CONSTRAINT PK_PROFILEVIEW PRIMARY KEY (profileview_id)
) ENGINE=INNODB;
ALTER TABLE profileview
ADD FOREIGN KEY FK_PROFILEVIEW_USER(user_id)
REFERENCES user (user_id);
ALTER TABLE profileview
ADD FOREIGN KEY FK_PROFILEVIEW_VISITOR(visitor_user_id)
REFERENCES user (user_id);
PHP:
This is a simple example of the user profile page - www.domain.com/profile.php?id=xxx.
At this point you need to define two variables in session when the user logs into the site:
$_SESSION['user_id'] (int) / $_SESSION['user_logged'] (boolean)
<?php
if ($_GET && isset($_GET['id']){
if(isset($_SESSION['user_id']){
$profile_user_id = $_GET['id'];
// the user that visits the profile has a session with his/her id on it.
session_start();
$visitor_user_id = $_SESSION['user_id'];
} else {
// if visitor specified an id but there is no session, redirect to login.
header("location: login.php");
}
} else {
// if no id passed redirect to index
header("location: index.php");
}
?>
<html>
<head>
<title>Your title</title>
</head>
<script src="scripts/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
//here you will store the visit with jquery.
$(document).ready(function(){
// store the values from php.
var profile_user_id = <?php echo $profile_user_id ?>;
var visitor_user_id = <?php echo $visitor_user_id ?>;
// here, the user information goes to the visit.php file.
$.post('visit.php' { profile_user_id:profile_user_id, visitor_user_id:visitor_user_id } );
});
</script>
<body>
Here print user information from a SQL select or something of the id passed in the GET.
</body>
</html>
Now, the visit.php file to store data:
<?php
if ($_POST && isset($_POST['profile_user_id']) && isset($_POST['visitor_user_id'])) {
session_start();
// this will end the execution of the script if there is no session from user logged
if ($_SESSION['user_logged'] != true) {
exit();
}
// everything is ok, do the process:
// functions.php contains your SQL connection, I suppose you know how to do it.
include('../cgi-bin/functions.php');
$link = dbconn();
$profile_user_id = mysql_real_escape_string($_POST['profile_user_id']);
$visitor_user_id = mysql_real_escape_string($_POST['visitor_user_id']);
// this will store the data in profileview including date and time if id's are not equal.
if($profile_user_id != $visitor_user_id){
$sql = "INSERT INTO profileview (user_id, visitor_user_id, date_time) VALUES ($profile_user_id, $visitor_user_id, NOW())";
mysql_query($sql, $link);
}
}
?>
EXTRA: if you don't know what functions.php do, here it is:
<?php
function dbconn() {
if(!include_once('db.php')) {
die('Error include file.');
}
if (!$link = mysql_connect($db['hostname'],$db['username'],$db['password'])) {
die('Error connecting.');
}
if (!mysql_select_db($db['database'])) {
die('Error selecting.');
}
return $link;
}
?>
The above file will need this file too: setup here your connection parameters to your db.
db.php
<?php
$db = array(
'hostname' => 'localhost',
'username' => 'root',
'password' => 'mysql',
'database' => 'mydb'
);
?>
I suggest you to put this in the cgi-bin folder of your hosting for better practices as you can see in visit.php file code.
Now, create another file called visitors.php?id=xxx and do a select * from of your profile views according to the user_id. At this point you will be able to:
Get the user_id information and if it is men (for example)...
Select visitors by sex and do a rule to list only female visitors.
List visitors according to the time stored in profileview table.
profileviews:
profile
userwhoviewed
timestamp
Index the profile column.
So when your user views the page, check if it's the profile owner, get the sex of the profile owner, check the sex of the viewer, if different, update the table with the viewer and the timestamp.
When querying the results, just select all rows matching the target profile, ordered by timestamp desc, and iterate to build your links back to those profiles.
I normally use INT data types in these fields (keeps the rows smaller and speeds up the lookups), then have a user table that generates those UID's as an auto_increment primary key. That will hold your gender and preference fields, too, as well as any other ancillary user data, and makes it easier to change login names, if desired.
But you're leaving out your gay users. Better to just log them all and let the user filter based on their preferences. :)
UsersTable
UserID Sex
1 Boy
2 Girl
3 Girl
UsersViewsTable
UserID View Unixtimestamp
1 2 342143243432
1 3 142143243432
2 3 242143243432
3 1 442143243432
When you visite the user profile, you'll use this :
IF CurrentUserSex != UserProfileSex
INSERT INTO UsersViewsTable (UserID, View, Unixtimestamp) VALUES (CurrentUser, CurrentProfileUserID, time)
Now, you want to fetch this on a page to see last seen from opposite sex ?
SELECT * FROM UsersViewsTable LEFT JOIN UsersTable USING (UserID) WHERE Sex != CurrentUserSex GROUP BY View ORDER BY Unixtimestamp DESC
EDIT :
IF CurrentUserSex != UserProfileSex {
$Res = SELECT CurrentProfileUserID FROM UsersViewsTable WHERE UserID = CurrentUserID AND View = UserProfileID LIMIT 1
if($Res['Count'] == 1){
// Exist
UPDATE UsersViewsTable SET Unixtimestamp = time WHERE UserID = CurrentUserID AND View = UserProfileID LIMIT 1
} elseĀ {
// Doesnt exist
INSERT INTO UsersViewsTable (UserID, View, Unixtimestamp) VALUES (CurrentUser, CurrentProfileUserID, time)
}
}
Just check n compare for each user profile page with the visitor id and profile id. If two are different store in a visit table with date and time and your required info. Before inserting just check the table row
if prof id, vistor id already exists then update the time else just insert the data.
Thanks.

JQuery & PHP Star Rating simplified

EDIT: The plugin in question is located here.
PHP beginner here using a JQuery Star Rating snippet and have gotten it to work perfectly. My problem is that it is currently configured to count and display the average of many ratings (for public applications). I'm trying to simplify the plugin so that it allows one to set a personal rating (as if rating your own songs in iTunes). The user may update their rating, but no partial stars would ever exist. I've broken the plugin many times trying to get it working, but to no avail. The mysql database exists as follows:
CREATE TABLE IF NOT EXISTS `pd_total_vote` (
`id` int(11) NOT NULL auto_increment,
`desc` varchar(50) NOT NULL,
`counter` int(8) NOT NULL default '0',
`value` int(8) NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
If I can get it working the way I imagine, I wouldn't require both the counter and value columns, simply a single INT column that holds a value between 1 and 5. Currently counter accumulates the number of votes, while value aggregates the ratings. The stars are then displayed using (value/counter)*20 (as a percentage). The PHP is below (original):
<?php
// connect to database
$dbh=mysql_connect ("localhost", "user", "pass") or die ('Cannot connect to the database');
mysql_select_db ("thenally_pd",$dbh);
if($_GET['do']=='rate'){
rate($_GET['id']);
}else if($_GET['do']=='getrate'){
// get rating
getRating($_GET['id']);
}
// get data from table
function fetchStar(){
$sql = "select * from `pd_total_vote`";
$result=#mysql_query($sql);
while($rs = #mysql_fetch_array($result,MYSQL_ASSOC)){
$arr_data[] = $rs;
}
return $arr_data;
}
// function to retrieve
function getRating($id){
$sql= "select * from `pd_total_vote` where id='".$id."' ";
$result=#mysql_query($sql);
$rs=#mysql_fetch_array($result);
// set width of star
$rating = (#round($rs[value] / $rs[counter],1)) * 20;
echo $rating;
}
// function to set rating
function rate($id){
$text = strip_tags($_GET['rating']);
$update = "update `pd_total_vote` set counter = counter + 1, value = value + ".$_GET['rating']." where id='".$id."' ";
$result = #mysql_query($update);
}
?>
Thanks for a point in the right direction,
Mike
I am unsure as I have no access to the rating system you are using yet just glancing at what you have I guess you could keep the counter set to 1 (if removing it breaks the jQuery Rating System) and have the value updated by the person so when you fetch it they only see their value (make sure value can't go above 5). That way if the value is set to 5 then it will show 5 because it isn't finding other ratings.... (based on my understanding) You will also have to add a user id so you know which persons rating to fetch (since you want it personal). This depends on how dependent the application is a specific database design.

Protect counter views In order not to be manipulated

I have this code :
$id = $_GET['id'];
mysql_query("UPDATE threads SET views = views + 1 WHERE id = '$id'");
but when I click refresh over and over the counter increases with each refresh.
How can I protect this counter from this with sessions or any other way?
You could set a session variable with (hasBeenCounted) and if that is set, you do not increment.
if(!isset($_SESSION['hasBeenCounted'])
{
$id = $_GET['id'];
mysql_query("UPDATE threads SET views = views + 1 WHERE id = '$id'");
$_SESSION['hasBeenCounted'] = "counted";
}
EDIT:
session_start():
will need to be at the very top of any page that you intend to use sessions on.
One way to do this is to use sessions. However, in the end, that's not really scalable. As a user moves through your site, you could potentially have a massive session file. Additionally, every time a user creates a new session, you will record that view anyway.
If you only want to record a single view for a single user, you need to store that that user viewed the thread. Depending on whether your site only allows logged in users to view threads, or if your site is open to the public, you'll have to store something unique about each user in a separate table, structured something like this (your mileage will vary on field types):
CREATE TABLE `thread_views` (
`id` INT( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`thread_id` INT( 10 ) UNSIGNED NOT NULL ,
`user_id` INT( 10 ) UNSIGNED NOT NULL ,
`ts` TIMESTAMP NOT NULL
)
Every time a user views the thread, you'll need to check this table. If there's no record in thread_views, insert one, and the increment the views column in your threads table. If there is a row in thread_views, then you know the user has already viewed the thread.
I think sessions with cookies are your best shot. You would probably want to set the cookie after the first visit, and then if the cookie is already set you don't update your view counter.
The syntax will be similar to this:
$expire=time()+2592000; //This is set to expire in 1 month (in seconds)
setcookie("visitor", "Already Visited", $expire);
This is how I would implement it:
if !(isset($_COOKIE["visitor"]))
{
$expire=time()+2592000; //This is set to expire in 1 month (in seconds)
setcookie("visitor", "Already Visited", $expire);
$id = $_GET['id'];
mysql_query("UPDATE threads SET views = views + 1 WHERE id = '$id'");
}
$id = $_GET['id'];
if(!isset($_SESSION['hasBeenCounted']) || $_SESSION['hasBeenCounted'] != $id)
{
mysql_query("UPDATE threads SET views = views + 1 WHERE id = '$id'");
$_SESSION['hasBeenCounted'] = $id;
}
I've modified the code and it works now.

Categories