Mysql Pageviews update only per session - php

just got help with making my code for pageviews work... and now i would like the pageviews only count 1 for each session / ip.
In my users (news.users) table i have these cells available for use: (tried to set up something earlier that didnt work out so these are not in use)
ip_reg, ip_visit, dtreg, dtvisit, visits, pass
The code i have that is now working looks like this :
//Adds one to the counter
mysql_query("UPDATE news SET posts = posts + 1, published=published, last_edit=last_edit WHERE id=$id");
//Retreives the current count
$count = mysql_fetch_row(mysql_query("SELECT posts FROM news WHERE id=$id"));
//Displays the count on your site print
echo "<label>Viewed: ";
echo $count[0];
echo " times</label>";
?>
Can i use some of the unused cells in users to stop a user from reloading the page to get higher views on a page? And how do i do it :P

Like I suggested I would put the read news articles in the user's session. Try this:
if (!isset($_SESSION['read_news']) || !is_array($_SESSION['read_news'])) {
$_SESSION['read_news'] = array();
}
if (!in_array($id, $_SESSION['read_news'])) {
$_SESSION['read_news'][] = $id;
mysql_query("UPDATE news SET posts = posts + 1 WHERE id=$id");
}
If this doesn't work, you don't have sessions enabled and you should put session_start(); somewhere in the top of your project. Make sure that line is called in each request.

Related

PHP session for tracking unique page views

I want to use sessions to track unique page views. Not a very robust method, I know, but sufficient for what I want to do.
On the first page load the session variable is set and a field in the database increments. On subsequent page views it does not increment, because the increment is conditional on the session variable not being set.
This is my code:
$pagenumber = 1;
//other stuff here...
session_start();
if (!isset($_SESSION[$pagenumber])) {
$storeview = mysqli_query($dbconnect, "UPDATE tblcount SET views=views+1 WHERE id='$pagenumber'");
$_SESSION[$pagenumber] = $pagenumber;
}
echo $_SESSION[$pagenumber];
$Recordset1 = mysqli_query($dbconnect, "SELECT views FROM tblcount WHERE id = '$pagenumber'");
$row_Recordset1 = mysqli_fetch_assoc($Recordset1);
echo "Viewed ".$row_Recordset1['views']." times";
The first echo is only there for testing. It echoes the value just fine on page refresh and the increment works the first time, but the view count continues to increment on every page refresh, which it shouldn't. I can't see why.
I found a similar question:
PHP: Unique visits/hits to specific items using cookies/ip but I ran into a similar issue with the solution offered there.
Help appreciated!
Problems:
You are updating in tblCount EACH time, because your session is closed each time your script finishes.
SO: Put the session_start()call as the FIRST LINE in code.
It's not permitted to set an integer as $_SESSION variable. So if you set $_SESSION[$pagenumber] = 'something', then you gain the following notice:
( ! ) Notice: Unknown: Skipping numeric key 1 in Unknown on line 0
Quite... not understandable. For details see this answer.
Solution:
Add your $pagenumber as index in an array (here pagenumbers) and that array inside the $_SESSION variable. No notice anymore.
session_start();
$pagenumber = 1;
if (!isset($_SESSION['pagenumbers'])) {
$_SESSION['pagenumbers'] = array();
}
if (!isset($_SESSION['pagenumbers'][$pagenumber])) {
updateViews($pagenumber);
$_SESSION['pagenumbers'][$pagenumber] = $pagenumber;
}
echo 'Page number: ' . $_SESSION['pagenumbers'][$pagenumber] . '<br/>';
$views = getViews($pagenumber);
echo '<pre>Viewed ' . print_r($views, true) . ' times</pre>';
Note: I used my functions to test. They just replace your db-processing code.
Just tested. This also works.
session_start();
// Get page name
$page_url = $_SERVER['REQUEST_URI'];
// Create the session ID. Will act as visitor username
if(!isset($_SESSION['id'])){
$_SESSION['id'] = session_id();
// For the visit to the first page
$visit_id = $_SESSION['id'];
}else{
// For subsequent visits to any page
$visit_id = $_SESSION['id'];
}
/******************
Query DB. Insert only one visit per page per session.
It means we need a count for each page to get its total visits.
Or a count for all records to get site total visits.
************************************/
$query_visits_table = mysqli_query($db_connect, "SELECT * FROM tblcount WHERE (visit_id='$visit_id') AND (page_name='$page_url')");
if(mysqli_num_rows($query_visits_table) > 0){
// Do nothing if this page has been visited during this session
}else{
mysqli_query($db_connect, "INSERT INTO tblcount (visit_id, page_name, visit) VALUES('$visit_id', '$page_url', '1')");
}
// Get site total visits
$query_site_visits = mysqli_query($db_connect, "SELECT * FROM tblcount");
// For a specific page
$query_specific_page_visit = mysqli_query($db_connect, "SELECT * FROM tblcount WHERE page_name='$page_url'");
if(isset($query_site_visits) && isset($query_specific_page_visit)){
$site_total_visits = mysqli_num_rows($query_site_visits);
$specific_page_visit = mysqli_num_rows($query_specific_page_visit);
echo 'Site total visits is '. $site_total_visits . '<br />';
echo 'Total visits for ' . $page_url . ' is ' . $specific_page_visit;
exit();
}

while inside another while in php

I have created a blog in php. Users can view posts of their friends and they can "like it", like you do in facebook. Under each post there is a link that when a user press it, the user can see all users like this certain post. Table comments holds all posts: comments(comments_id, comment, user) and table likes(like_id, user, the_comment_id) holds all likes for each post.
I have the following problem. Lets say that users 23, 30 like first post. User 30 likes second post. If I press on link for the first post to see pleople like it, it gives me 23 and 30. But if I click on second post, it gives 23, 30 and 30 and not only 30 as it should give me.
Probably the problem is with "while"... any idea how to fix this?
This is my php code for this:
<?php
$sql = mysql_query("SELECT * FROM comments");
// starts a while loop that prints all posts...
while ($row= mysql_fetch_assoc($sql)) {
$comment_id = $row['comments_id'];
//... prints post details succesfully
$comments .= ".$row['comment'].";
// here starts the process for the link, that user will press it, it will get all users likes this certain post
$favorites = mysql_query(" SELECT * FROM `likes` WHERE `the_comment_id`='{$row['comments_id']}' ");
while($e = mysql_fetch_array($favorites)){
$like_users = $e['user'];
$array[]=$like_users;
}
$arstring = implode('</br>',$array);
$comments .= <<<EOD
// here starts link, that press and see all people like this comment
$arstring
EOD;
} //end while
You should section off your like-array to be per-comment. Right now it's a single array for all comments/posts. So basically just clear it before starting the 2nd while loop.
You can do it like this:
<?php
$sql = mysql_query("SELECT * FROM comments");
// starts a while loop that prints all posts...
while ($row= mysql_fetch_assoc($sql)) {
$comment_id = $row['comments_id'];
//... prints post details succesfully
$comments .= ".$row['comment'].";
// here starts the process for the link, that user will press it, it will get all users likes this certain post
$favorites = mysql_query(" SELECT * FROM `likes` WHERE `the_comment_id`='{$row['comments_id']}' ");
$array = array(); // empty the list of any earlier users
while($e = mysql_fetch_array($favorites)){
$like_users = $e['user'];
$array[] = $like_users;
}
$arstring = implode('</br>',$array);
$comments .= <<<EOD
// here starts link, that press and see all people like this comment
$arstring
EOD;
} //end while
On a sidenote: you really should not use the mysql extension anymore. It is officially deprecated. Instead use the MySQLi or PDO extensions. These are both faster and safer.

Random pictures in two pages

I have a table that stores images of three categories: cars, bikes, buses. These images appear on two pages. On the first page, you should see an image of each category, defined so random. On the second page, you should see the remaining pictures. How can I do this using php?
I would prefer to do this in MySQL, you can set the order to:
ORDER BY MD5(ImageNo+UserRandomNumber)
SQL FIddle
You can generate a single random number per user, store this in the session then apply this to the ordering and as long as the number supplied stays the same, the order will remain the same too.
You can indeed use a session to store which images were shown on the first page, and then leave them out on the second page. Without knowing your exact table structure, something like this should work:
<?php
// page 1
session_start();
function get_random_image_id($category)
{
// SELECT id FROM images WHERE category = $category ORDER BY RAND() LIMIT 1
}
function show_image($id)
{
// SELECT * FROM images WHERE id = $id
// echo <img ...>
}
$_SESSION['image_ids'] = array(
get_random_image_id("cars"),
get_random_image_id("bikes"),
get_random_image_id("buses"),
);
foreach($_SESSION['image_ids'] as $image_id)
{
show_image($id);
}
?>
<?php
// page 2
session_start();
function show_images($exclude_ids)
{
$ids = implode(",", $exclude_ids);
// SELECT * FROM images WHERE id NOT IN ($ids)
}
$exclude = array();
if(isset($_SESSION['image_ids'])) // has the user visited page 1?
{
$exclude = $_SESSION['image_ids'];
}
show_images($exclude);
?>

Infinite Scroll with MySQL Data

I have followed help located in this topic: Using infinite scroll w/ a MySQL Database
And have gotten close to getting this working properly. I have a page that is displayed in blocks using jquery masonry, in which the blocks are populated by data from a mysql database. When I scroll to the end of the page I successfully get the loading.gif image but immediately after the image it says "No more posts to show." which is what it should say if that were true. I am only calling in 5 posts initially out of about 10-15, so the rest of the posts should load when I reach the bottom of the page but I get the message that is supposed to come up when there really aren't any more posts.
Here is my javascript:
var loading = false;
$(window).scroll(function(){
if($(window).scrollTop() == $(document).height() - $(window).height()) {
var h = $('.blockContainer').height();
var st = $(window).scrollTop();
var trigger = h - 250;
if((st >= 0.2*h) && (!loading) && (h > 500)){
loading = true;
$('div#ajaxLoader').html('<img src="images/loading.gif" name="HireStarts Loading" title="HireStarts Loading" />');
$('div#ajaxLoader').show();
$.ajax({
url: "blocks.php?lastid=" + $(".masonryBlock:last").attr("id"),
success: function(html){
if(html){
$(".blockContainer").append(html);
$('div#ajaxLoader').hide();
}else{
$('div#ajaxLoader').html('<center><b>No more posts to show.</b></center>');
}
}
});
}
}
});
Here is the php on the page the blocks are actually on. This page initially posts 5 items from the database. The javascript grabs the last posted id and sends that via ajax to the blocks.php script, which then uses the last posted id to grab the rest of the items from the database.
$allPosts = $link->query("/*qc=on*/SELECT * FROM all_posts ORDER BY post_id DESC LIMIT 5");
while($allRows = mysqli_fetch_assoc($allPosts)) {
$postID = $link->real_escape_string(intval($allRows['post_id']));
$isBlog = $link->real_escape_string(intval($allRows['blog']));
$isJob = $link->real_escape_string(intval($allRows['job']));
$isVid = $link->real_escape_string(intval($allRows['video']));
$itemID = $link->real_escape_string(intval($allRows['item_id']));
if($isBlog === '1') {
$query = "SELECT * FROM blogs WHERE blog_id = '".$itemID."' ORDER BY blog_id DESC";
$result = $link->query($query);
while($blogRow = mysqli_fetch_assoc($result)) {
$blogID = $link->real_escape_string($blogRow['blog_id']);
$blogTitle = $link->real_escape_string(html_entity_decode($blogRow['blog_title']));
$blogDate = $blogRow['pub_date'];
$blogPhoto = $link->real_escape_string($blogRow['image']);
$blogAuthor = $link->real_escape_string($blowRow['author']);
$blogContent = $link->real_escape_string($blogRow['content']);
//clean up the text
$blogTitle = stripslashes($blogTitle);
$blogContent = html_entity_decode(stripslashes(truncate($blogContent, 150)));
echo "<div class='masonryBlock' id='".$postID."'>";
echo "<a href='post.php?id=".$blogID."'>";
echo "<div class='imgholder'><img src='uploads/blogs/photos/".$blogPhoto."'></div>";
echo "<strong>".$blogTitle."</strong>";
echo "<p>".$blogContent."</p>";
echo "</a>";
echo "</div>";
}
}
Here is the php from the blocks.php script that the AJAX calls:
//if there is a query in the URL
if(isset($_GET['lastid'])) {
//get the starting ID from the URL
$startID = $link->real_escape_string(intval($_GET['lastid']));
//make the query, querying 25 fields per run
$result = $link->query("SELECT * FROM all_posts ORDER BY post_id DESC LIMIT '".$startID."', 25");
$html = '';
//put the table rows into variables
while($allRows = mysqli_fetch_assoc($result)) {
$postID = $link->real_escape_string(intval($allRows['post_id']));
$isBlog = $link->real_escape_string(intval($allRows['blog']));
$isJob = $link->real_escape_string(intval($allRows['job']));
$isVid = $link->real_escape_string(intval($allRows['video']));
$itemID = $link->real_escape_string(intval($allRows['item_id']));
//if the entry is a blog
if($isBlog === '1') {
$query = "SELECT * FROM blogs WHERE blog_id = '".$itemID."' ORDER BY blog_id DESC";
$result = $link->query($query);
while($blogRow = mysqli_fetch_assoc($result)) {
$blogID = $link->real_escape_string($blogRow['blog_id']);
$blogTitle = $link->real_escape_string(html_entity_decode($blogRow['blog_title']));
$blogDate = $blogRow['pub_date'];
$blogPhoto = $link->real_escape_string($blogRow['image']);
$blogAuthor = $link->real_escape_string($blowRow['author']);
$blogContent = $link->real_escape_string($blogRow['content']);
$blogTitle = stripslashes($blogTitle);
$blogContent = html_entity_decode(stripslashes(truncate($blogContent, 150)));
$html .="<div class='masonryBlock' id='".$postID."'>
<a href='post.php?id=".$blogID."'>
<div class='imgholder'><img src='uploads/blogs/photos/".$blogPhoto."'></div>
<strong>".$blogTitle."</strong>
<p>".$blogContent."</p>
</a></div>";
}
}
echo $html;
}
I have tried using the jquery infinite-scroll plugin, but it seemed much more difficult to do it that way. I don't know what the issue is here. I have added alerts and did testing and the javascript script is fully processing, so it must be with blocks.php right?
EDIT: I have made a temporary fix to this issue by changing the sql query to SELECT * FROM all_posts WHERE post_id < '".$startID."' ORDER BY post_id DESC LIMIT 15
The blocks are now loading via ajax, however they are only loading one block at a time. The ajax is sending a request for every single block and they are fading in one after another, is it possible to make them all fade in at once with jquery masonry?
I seen your code in another answer, and I would recommend using the LIMIT functionality in MySql instead of offsetting the values. Example:
SELECT * FROM all_posts ORDER BY post_id DESC LIMIT '".(((int)$page)*5)."',5
This will just take a page number in the AJAX request and get the offset automatically. It's one consistent query, and works independent of the last results on the page. Send something like page=1 or page=2 in your jQuery code. This can be done a couple different ways.
First, count the number of elements constructed on the page and divide by the number on the page. This will yield a page number.
Second, you can use jQuery and bind the current page number to the body:
$(body).data('page', 1)
Increment it by one each page load.
Doing this is really the better way to go, because it uses one query for all of the operations, and doesn't require a whole lot of information about the data already on the page.
Only thing to note is that this logic requires the first page request to be 0, not 1. This is because 1*5 will evaluate to 5, skipping the first 5 rows. If its 0, it will evaluate to 0*5 and skip the first 0 rows (since 0*5 is 0).
Let me know any questions you have!
Have you tried doing any debugging?
If you are not already using, I would recommend getting the firebug plugin.
Does the ajax call return empty? If it does, try echoing the sql and verify that is the correct statement and that all the variables contain the expected information. A lot of things could fail considering there's a lot of communication happening between client, server and db.
In response to your comment, you are adding the html in this piece of code:
if(html){
$(".blockContainer").append(html);
$('div#ajaxLoader').hide();
}
I would do a console.log(html) and console.log($(".blockContainer").length) before the if statement.

Need Associated ID Added to a While Loop (php)

Been trying to get my head around while loops for the last few days but the code seems very inefficient for what I'm trying to achieve. I'm assuming I'm over-complicating this though nothing I've tried seems to work.
Each topic in my forum can have related topic IDs stored in a separate table. A post ID is also stored in this table, as that specific post references why they are considered related.
DB Table contains only: topic_id, related_id, post_id
// Get related IDs and post IDs for current topic being viewed
$result = $db->query('SELECT related_id, post_id FROM related_topics WHERE topic_id='.$id.'');
// If related topics found, put both of the IDs into arrays
if ($db->num_rows($result)) {
while($cur_related = mysql_fetch_array($result)){
$reltopicarray[] = $cur_related['related_id'];
$relpost[] = $cur_related['post_id'];
}
// If the first array isnt empty, get some additional info about each related ID from another table
if(!empty($reltopicarray)) {
$pieces = $reltopicarray;
$glued = "\"".implode('", "', $pieces)."\"";
$fetchtopics = $db->query('SELECT id, subject, author, image, etc FROM topics WHERE id IN('.$glued.')');
}
// Print each related topic
while($related = mysql_fetch_array($fetchtopics)){ ?>
<?php echo $related['subject']; ?> by <?php echo $related['author']; ?>
// Id like to show the Post ID below (from the array in the first while loop)
// The below link doesnt work as Im outside the while loop by this point.
<br />View Relationship
<?php } ?>
The above currently works, however I'm trying to also display the post_id link below each related topic link, as shown above.
if you change the second while loop to something like this:
<?php
$i = 0;
while($related = mysql_fetch_array($fetchtopics)){
//show view link
// [...]
//show the view related link
?>
View Relationship
<?php
//increment the i so that you can get the next post in the next iteration of the loop
$i++;
}
?>
[sidenote]
You probably should not be doing database queries in the same location you are generating the html for future-you's sanity.
[/sidenote]
[edit]
You could also do it all as one query:
SELECT related_topics.related_id,
related_topics.post_id,
related_topics.topic_id,
topics.subject,
topics.author,
topics.image,
topics.etc
FROM related_topics
LEFT JOIN topics ON topics.id = related_topics.topic_id
WHERE topic_id= $id
Then you only have to loop through it once for all of the links.

Categories