PHP Unique pageviews counter not working correctly - php

The following script updates the pageviews if its from a unique visitor. The page retrieves blog posts from databases and prints on the screen. When a blog post is visited first time the script should update its pageview field by 1. But the script is updating the pageview on every page refresh rather than recording only unique views.
if($_SESSION[$isPostID] != $isPostID)
{
try
{
$updatePageViews = $db2->prepare("UPDATE articles SET pageviews = pageviews+1 WHERE id = :id");
$updatePageViews->execute(array(':id' => $isPostID));
if($updatePageViews->rowCount() != 1)
{
#createLog("Unable to update pageviews.","Unable to update pageviews!!! Title = [".$istitle."].");
}
else{ $_SESSION[$isPostID] = $isPostID;}
}
catch(PDOException $updatePageViewsERR)
{
$subject = "Pageviews Updation--Update data into database. [PAGE= ".$istitle."]. Error Code: #15";
$text = $updatePageViewsERR->getMessage();
#createLog($subject,$text);
}
}
$isPostID is the unique ID assigned to every blog post in the database table.
Note: Session is already started in the script.

You have two errors in the first line.
First: you have no closing parenthesis in the condition. I guess it's just a typo, otherwise it would throw you fatal errors.
Second: you are comparing $isPostID to $isPostId which are two different variables. This may be exactly why it doesn't work.
See if it solves the problem

Related

php script hanging for a large data set

I am building a website which scrapes data from another website,stores it in a database and shows it in the form of a table. Everything works fine as long as the number of rows are less (around 100), but when the data set increases, say 300 rows or more the data gets stored in the database (phpmyadmin) but nothing shows on the screen and the site just keeps loading. Below is a section of the php script i am running:
<?php
// configuration
require("../includes/helpers.php");
// initializing current page and number of pages
$page = 0;
$pages = 1;
// scrape data from each page
while($pages--)
{
// next page
$page++;
// scrape data from shiksha.com
$string = #file_get_contents("http://www.shiksha.com/b-tech/colleges/b-tech-colleges-".urlencode($_POST["city"])."-{$page}");
if($string === false)
apologize("Please enter a valid city name");
if($page === 1)
{
// counting total number of pages
preg_match_all('/class=" linkpagination">/',$string,$result);
$pages = sizeof($result[0]);
}
// passing the string for scraping data and storing in database
get_college_info($string,$page);
// delay for 2s
sleep(2);
}
// querying the infrastructure table for facilities of all colleges
$infra = query("SELECT college_id,facilities FROM infrastructure ");
// preparing query and selecting data from table college_info
$result = query("SELECT * FROM college_info");
// render(output) results
render("result.php",["title" => "result","infra" => $infra,"result" => $result]);
}
}?>
interestingly, if i already have the data stored in my db and I just retrieve and print it , everything works fine and all the data ,however large it is,gets printed. I have no clue whats the problem.
PS : I have already tried set_time_limit().
you are creating an infinite loop. so to fix the issue change the criteria for your while loop to the below.
while($page<$pages)
{
//your same code here
}

Query isn't inserting into database [duplicate]

This question already has answers here:
Can I mix MySQL APIs in PHP?
(4 answers)
Closed 6 years ago.
I am attempting to implement a click count system. I am using the following code in this link Click here to see code, but changing it to modern standards. Initially I received errors for the msqli_real_escape_ string, but I believed I resolved it(no errors). Now, I am not receiving any errors at all, but the query is not sending into my database. I am using ini_set('display_errors', 1);
error_reporting(E_ALL); for error checking. Also I have my $con and session in and ini file that I call, so the session and connection are not issues.
Does anyone see what I am doing wrong or is there a good way I can check to see what isn't working?
//create current page constant
$curPage = mysqli_real_escape_string($con,htmlspecialchars($_SERVER['PHP_SELF']));
//set number of clicks variable to 0
$clicks = 0;
//do not recount if page currently loaded
if($_SESSION['page'] != $curPage) {
//set current page as session variable
$_SESSION['page'] = $curPage;
$click_sql = "
SELECT *
FROM click_count
WHERE page_url = ?
";
if (!$click_stmt = $con->prepare($click_sql)) {
$click_stmt->bind_param("s", $curPage);
$click_stmt->execute();
$num_rows = $click_stmt->fetchColumn();
if (!$click_stmt->errno) {
// Handle error here
}
$stmt->bind_result($click_id, $page_url, $page_count);
} elseif ($num_rows == 0) {
//try to create new record and set count for new page to 1
//output error message if problem encountered
$click_insert_stmt = "
INSERT INTO click_count
(page_url, page_count)
VALUES(?, ?)";
if(!$click_stmt = $con->prepare($click_insert_stmt)) {
$click_insert_stmt->execute(array('$curPage',1));
echo "Could not create new click counter.";
}
else {
$clicks= 1;
}
} else {
//get number of clicks for page and add 1 fetch(PDO::FETCH_BOTH)
while($click_row = $click_insert_stmt->fetch(PDO::FETCH_BOTH)) {
$clicks = $row['page_count'] + 1;
//update click count in database;
//report error if not updated
$click_update_stmt = "
UPDATE click_count
SET page_count = ?
WHERE page_url = ?
";
if(!$click_stmt = $con->prepare("$click_update_stmt")) {
$click_update_stmt->execute(array('$clicks', '$curPage'));
echo "Could not save new click count for this page.";
}
}
}
}
Edit: New Updated Code
// ********Page count************
//create current page constant
$curPage = mysqli_real_escape_string($con,($_SERVER['PHP_SELF']));
//set number of clicks variable to 0
$clicks = 0;
//do not recount if page currently loaded
if($_SESSION['page'] != $curPage) {
//set current page as session variable
$_SESSION['page'] = $curPage;
$click_sql = "
SELECT *
FROM click_count
WHERE page_url = ?
";
if (!$click_stmt = $con->prepare($click_sql)) {
$click_stmt->bind_param("s", $_SERVER['PHP_SELF']);
$click_stmt->execute();
$num_rows = $click_stmt->fetchColumn();
if (!$click_stmt->errno) {
// Handle error here
}
$stmt->bind_result($click_id, $page_url, $page_count);
} elseif ($num_rows == 0) {
//try to create new record and set count for new page to 1
//output error message if problem encountered
$click_insert_stmt = "
INSERT INTO click_count
(page_url, page_count)
VALUES(?, ?)";
if(!$click_stmt = $con->prepare($click_insert_stmt)) {
$click_insert_stmt->execute(array($curPage,1));
echo "Could not create new click counter.";
}
else {
$clicks= 1;
}
} else {
//get number of clicks for page and add 1 fetch(PDO::FETCH_BOTH)
while($click_row = $click_insert_stmt->fetch(PDO::FETCH_BOTH)) {
$clicks = $row['page_count'] + 1;
//update click count in database;
//report error if not updated
$click_update_stmt = "
UPDATE click_count
SET page_count=page_count+1
WHERE page_url = ?
";
if(!$click_stmt = $con->prepare("$click_update_stmt")) {
$click_update_stmt->execute(array($curPage));
echo "Could not save new click count for this page.";
}
}
}
}
It looks like you're doing a lot of stuff like this:
$click_update_stmt->execute(array('$clicks', '$curPage'));
I'm not sure where you picked up this habit of quoting variables as strings, but you need to drop it. '$x' and $x are two hugely different things. In the first case it's literally '$x' and in the second case it's whatever the $x variable happens to represent.
Fix it like this:
$click_update_stmt->execute(array($clicks, $curPage));
Also since you're using prepared statements, which by the way is great, you do not need to and should not manually escape your values. Applying them to placeholders with bind_param is the safe way of doing it. Doing any other escaping mangles the data.
Just bind directly to the source:
$click_stmt->bind_param("s", $_SERVER['PHP_SELF']);
Don't arbitrarily run things like htmlspecialchars on input out of paranoia or because you're doing cargo-cult programming and you saw it done in a YouTube tutorial somewhere. That function is intended to be used to display values only, not store them. Data in your database should be as raw as possible.
There's a lot of problems with this code, and one of them that has me confused is why there's so much code. Remember SELECT * and then binding results to arbitrary variables is trouble, your schema might change and then your code is out of sync. Whenever possible fetch rows as an associative array if doing this, then all you have to worry about is renamed ore removed columns.
The biggest problem is this is subject to race conditions because it doesn't use an atomic increment. When writing counters, always do your updates as operations that are a single statement:
UPDATE click_count SET page_count=page_count+1 WHERE page_url=?
Your approach of reading the count, incrementing it, and then writing it back into the database means that you're inviting problems if another operation runs concurrently, something very likely on click-counter code.

My page views counter is incrementing 1 unit on my homapage but is incremented 3 units on secondary pages

Im doing a function to count visitors, views and page_views.
For now Im just trying to count page views but Im having a strange issue.
I have a table stats with this columns: "users,visits,page_views".
And now I just want to increment my page_views when user acess some page.
Every time I acess my homepage my page_views is incremented 1 unit, but when I acess a secundary page my column page_views is incremented with 3 units, and I want just also 1 unit.
Do you know why this can be happening?
I think that problem is in my getHome() function, because If I call my function countViews() before or after my getHome(), I have different behaviors. But Im not finding why.
When I have me countViews() above my getHome(), It seems that Im calling 3 times my function countViews on my secundary pages.
But I only call my function countViews() on my index.php file and below this function I have my getHome() function where I do my navigation to all pages I have in my project.
function countViews(){
$pdo = start();
//if Im not logged as admin
if(!isset($_SESSION['admin'])){
//So at first I read my table stats, if my table dont have any row,
// I create a row with my columns with value of '0'.
$readStats= $pdo->prepare("SELECT * FROM stats");
$readStats->execute();
if($readStats->rowCount()<1){
$insStats= $pdo->prepare("INSERT INTO stats(users, views, page_views) VALUES (?,?,?)");
$insStats->bindValue(1,'0');
$insStats->bindValue(2,'0');
$insStats->bindValue(3,'0');
$insStats->execute();
}
//If my table stats already have one row, I want to increment page_views.
else{
$resultStats= $readStats->fetch(PDO::FETCH_ASSOC);
$incrementPageViews = $resultStats['page_views'] + 1;
$updatePageViews = $pdo->prepare("UPDATE stats set page_views = ?");
$updatePageViews ->bindParam(1,$incrementPageViews);
$updatePageViews ->execute();
}
}
}
My index.php is like:
<?php
ob_start(); session_start();
require_once('dts/db.php');
$pdo = start();
countViews();
?>
<!DOCTYPE>
<!-- here I have my css and js imports -->
<?php getHome(); ?>
My secundary pages:
<title>Untitled Document</title>
</head>
<body>
<!-- here I have my html -->
</body>
getHome() function:
<?php
function getHome(){
$url = $_GET['url'];
$url = explode('/', $url);
$url[0] = ($url[0] == NULL ? 'index' : $url[0]);
if(file_exists('project/'.$url[0].'.php')){
require_once('project/'.$url[0].'.php');
}
elseif(file_exists('project/'.$url[0].'/'.$url[1].'.php')){
require_once('project/'.$url[0].'/'.$url[1].'.php');
}
else{
require_once('project/404.php');
}
}
?>
My table is like:
I have no clue why this is happening but I can help you find.
Do the following inside your countViews():
echo "<pre>";
var_dump("Count Views beeing called from : ".__FILE__);
echo "</pre>";
If you still cannot find why using this, tell me and I will help you setup xdebug and profiling which will tell you exactly the files included and the functions called in the order they were called/included.
Like this:
http://4.bp.blogspot.com/-BGYXo-b-bj8/TvIjJd0pBXI/AAAAAAAAF_0/ZssGFW9Rb7Y/s1600/drupal-6-cacherouter-memcache-fail.png
You route all 404 requests to index.php . It seems you have 2 missed resource on secondary pages.
Try to modify countViews() function as below:
function countViews(){
$tmp = $_SERVER["REQUEST_URI"]; // huge logging: $tmp = print_r($_SERVER, 1);
file_put_contents($_SERVER['DOCUMENT_ROOT'].'/viewslog.txt', $tmp, FILE_APPEND | LOCK_EX );
$pdo = start();
There're two possibilities I can think of.
You have countViews in one of your require_once files
You have some redirect code in your secondary pages.
What I'm actually saying is, I'm sure it's not magic.
What you can do is changing your function into simpler one and check if this problem still occurs.
function countViews(){
$pdo = start();
//if Im not logged as admin
if(!isset($_SESSION['admin'])){
//So at first I read my table stats, if my table dont have any row,
// I create a row with my columns with value of '0'.
$sth= $pdo->query("SELECT * FROM stats LIMIT 1");
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
if(!$result){
$pdo->exec("INSERT INTO stats(users, views, page_views) VALUES (0,0,0)");
}
//If my table stats already have one row, I want to increment page_views.
else{
$pdo->exec("UPDATE stats set page_views = page_views + 1");
}
}
}
If it still doesn't work you should show us what data you have in your stats table.
I would start looking at your server's log, it could tell you wich files are being requested, it seems like some files are being requested more than once.

Updating database according to check-boxes checked

I've the following table layout in my database with some data.
I'm taking input by check-boxes so user can select all applicable accident road conditions and it to database. I would say it is okay if you're adding a new record you just loop through the checkboexs checked and insert them in DB
The first information is now saved in the database, now user decided to change the road conditions for any reasons user came back and change it the to the following.
Now my question, how should I update my table. The first thing that came into my mind was to delete the record that were already there and insert the new one's.
My real issue here is, assume user have choose the 3 items before but changed it two or one then how would i delete the those are not checked you know what I'm saying. Below is some code snippets that I've been trying.
$accidentRoadConditions = AccidentRoadConditions::findAccidentRoadConditions($acc_det_id);
$wc_array = [];
while ($roadConditions = $accidentRoadConditions ->fetch(PDO::FETCH_OBJ)) {
$wc_array[] = $roadConditions ->rc_id;
}
Above I'm selecting all the road conditions that is already stored in the database.
if (isset($_POST['rta_ad_rc'])) {
foreach ($_POST['rta_ad_rc'] as $rc_id) {
//AccidentRoadConditions::save(array(null, $ad_lsid, $rc_id));
// $tmprory = AccidentRoadConditions::findByADAndRCIds($acc_det_id, $rc_id);
// if(!$tmprory){
// AccidentRoadConditions::save(array(null, $acc_det_id, $rc_id));
// }
if(in_array($rc_id, $wc_array)){
$errors[] = "in array <br />";
unset($wc_array[0]);
}
}
}
So my question is how to update values in database according to what was checked by user and deleting those which were unchecked which were checked before. Getting bit complicated so simply how to update database according to above mention scenario.
Any Idea?
I think you need to do the following
Store the selected checks in an array
Check in the database if any of those are already saved or not
if yes, skipped them otherwise add them into an array
$old_rc_array = [];
$new_rc_array = [];
while ($roadConditions = $accidentRoadConditions->fetch(PDO::FETCH_OBJ)) {
$old_rc_array[] = $roadConditions->rc_id;
}
if (isset($_POST['rta_ad_rc'])) {
foreach ($_POST['rta_ad_rc'] as $rc_id) {
if(in_array($rc_id, $old_rc_array)){
unset($old_rc_array[array_search($rc_id, $old_rc_array)]);
}else{
$new_rc_array[] = $rc_id;
}
}
}
foreach ($old_rc_array as $rc_to_delete) {
AccidentRoadConditions::deleteByADIdAndRCId($hidden_acc_det_id, $rc_to_delete);
}
foreach ($new_rc_array as $rc_to_insert) {
AccidentRoadConditions::save(array(null, $hidden_acc_det_id, $rc_to_insert));
}
I think this is what you should do.
Create composite unique constraint on ad_id and rc_id
Delete all the rows not in the selected checkbox ids.
Try to insert all the rows but user INSERT IGNORE. This will insert the record if it does not exist or it will just ignore it. As you are using some framework see how you can do that.
If you can not then just wrap it using try/catch and ignore if the error is related to constraint violation.
This way You don't need to check if the values exist and also there will not be any unnecessary inserts.

PHP check if variable exists in all rows returned

i want to do a check if a user id exists in all of the table rows i search for.
edit sorry i was missleading i think.
I want to check if the user has read all of the articles in a category, i have a forum front end displaying the categories and within the categories are the articles.
On the categories screen i want to display an image ALL ARTICLES READ or NOT ALL ARTICLES READ, so some how i need to loop through all of the articles per category which is what the example query below is doing and check if user id exists in ALL returned rows if yes then then all articles have been read if there are some rows missing the users id then some articles have not been read
This is my sql query
$colname_readposts = "-1";
if (isset($_GET['Thread_Category_Article_id'])) {
$colname_readposts = $_GET['Thread_Category_Article_id'];
}
mysql_select_db($database_test, $test);
$query_readposts = sprintf("SELECT Thread_Article_User_Read FROM Thread_Articles WHERE Thread_Category_Article_id = %s", GetSQLValueString($colname_readposts, "int"));
$readposts = mysql_query($query_readposts, $cutthroats) or die(mysql_error());
$row_readposts = mysql_fetch_assoc($readposts);
$totalRows_readposts = mysql_num_rows($readposts);
How can i check if all of the rows returned contain the users id?
The idea is to check to see if user has read all the articles if yes show READ if no show UNREAD.
The results per row are like so 0,15,20,37 these are id's entered when a user views a post.
i have managed to get this check for a single article to show if the user has read a specific article but unsure how i would check multiple:
here is my single article check:
<?php
$userid = $_SESSION['loggedin_id'];
$userreadlist = $row_readposts['Thread_Article_User_Read'];
$myarray = (explode(',',$userreadlist));
if (in_array($userid,$myarray )){
?>
html image READ
<?php } else { ?>
html image UNREAD
<?php } ?>
Any help would be appreciated.
Carl
First up, forget the mysql_* functions; ext/mysql is a deprecated API as of PHP 5.5 - so it's a really good idea to use mysqli or PDO.
From what I gather you're actually trying to see if any of those results contain a specific user's id? If so, do this in the SQL query:
SELECT Thread_Article_User_Read FROM Thread_Articles WHERE
Thread_Category_Article_id = %s AND UserID = %s
And supply this the User's ID as a second argument. (Syntax may not be 100% correct, but it should prove a point)
If you mean you want to check there there is any user's ID - then once again; do this in SQL:
SELECT Thread_Article_User_Read FROM Thread_Articles WHERE
Thread_Category_Article_id = %s AND UserID IS NOT NULL
This will ensure there is a valid value for 'UserID'.
Naturally replace 'UserID' with your column name if you base your solution on one of these examples.
However, if you're dumping out ALL the results from a table - and you need to see if your user's ID is present in a certain column (like you do!); then you can actually just adapt the logic that you're using on your single article page. Which should give you something like this...
$userid = $_SESSION['loggedin_id'];
$colname_readposts = "-1";
if (isset($_GET['Thread_Category_Article_id'])) {
$colname_readposts = $_GET['Thread_Category_Article_id'];
}
/* connect to db and run query; CHANGE ME TO SOMETHING NOT DEPRECATED */
mysql_select_db($database_test, $test);
$query_readposts =
sprintf("SELECT Thread_Article_User_Read FROM Thread_Articles WHERE
Thread_Category_Article_id = %s", GetSQLValueString($colname_readposts, "int"));
$readposts = mysql_query($query_readposts, $cutthroats) or die(mysql_error());
/* loop through all returned items */
while($row = mysql_fetch_assoc($readposts)) {
/* repeat the check you used on an individual
row on the single article page. i.e: */
$userreadlist = $row['Thread_Article_User_Read'];
$myarray = (explode(',',$userreadlist));
if (in_array($userid,$myarray )){
/* user has read */
} else {
/* user hasn't read */
}
}
If that code you worked for a single page then it should work in the above; as for every iteration of the loop you're working on a single row - just as you were on the single page. If the data is coming from the same table then the column names etc match up and it will work.
Or, if you just want to know if there are any unread posts at all, replace the loop with this one...
/* loop through all returned items */
$read = true;
while($row = mysql_fetch_assoc($readposts)) {
/* repeat the check you used on an individual
row on the single article page. i.e: */
$userreadlist = $row['Thread_Article_User_Read'];
$myarray = (explode(',',$userreadlist));
if (! in_array($userid,$myarray )){
$read = false;
break;
}
}
if( $read ){
/* all pages are read */
} else {
/* there are unread pages */
}

Categories