Asked  7 Months ago    Answers:  5   Viewed   34 times

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!

 Answers

10

Problems:

  1. 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.
  2. 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.

Wednesday, March 31, 2021
 
borrible
answered 7 Months ago
11

Yes, you have to place session_start() at top of every php page (before any output was generated, no headers must have sent before) to tell php to accept / start session, expect your php.ini is setup, that sessions start automatic.

I asked it because new session creates every time I use this instruction.<<

That is a hint, that your browser ignore (disallow) session cookies

Wednesday, March 31, 2021
 
EzzDev
answered 7 Months ago
71

1st problem But actually it seems that mysqli->query will not execute 2 statements at once. Isn't it?

That's right, if you want to execute multiple statements you need to use mysqli->multi_query. You can find a good explanation about multiple statements here: http://www.php.net/manual/en/mysqli.quickstart.multiple-statement.php

But this problem arise and I'm missing the trick to get rid of it

The problem arises because you are using multiple statements, and mysqli->query does not support them.

About your queries:

$result = $mysqli->query("SELECT  * from myTable where field='".$_GET['var']."');

You can inject this using for example 1' OR 1=1; that would return all entries of myTable on the query result.

"SELECT * from myTable where field='".$_GET['var']."' AND field2 IS NOT NULL"

Here you could use 1' OR 1=1 UNION ALL SELECT * FROM myTable WHERE '1'='1

Nowadays there are tools that can automatically check SQL injection for you, take a look at SQL Inject Me (Firefox Addon) for example.

Friday, May 28, 2021
 
Axalix
answered 5 Months ago
97

Regarding to TerryE's example and the advice to use multi_query(!), I checked the manual and changed the script to fit my needs.. finally I got a solution that looks like this:

$sql  = 'SELECT COUNT(cat1_id) as `cat1` FROM `cat1`;';
$sql .= 'SELECT COUNT(cat2_id) as `cat2` FROM `cat2`;';
$sql .= 'SELECT COUNT(cat2_id) as `cat2_b` FROM `cat2` WHERE `date` >= DATE(NOW());';
$sql .= 'SELECT COUNT(cat3_id) as `cat3` FROM `cat3`;';
$sql .= 'SELECT COUNT(cat4_id) as `cat4` FROM `cat4`;';
$sql .= 'SELECT COUNT(cat5_id) as `cat5` FROM `cat5`;';
$sql .= 'SELECT COUNT(cat6_id) as `cat6` FROM `cat6`;';
$sql .= 'SELECT COUNT(cat7_id) as `cat7` FROM `cat7`;';

if ($db->multi_query($sql))
{ 
    do
    {
        if ($stmt = $db->store_result())
        {
            while ($row = $stmt->fetch_assoc())
            {
                foreach ($row as $key => $value)
                {
                    $count[$key] = $value;
                }
            }
            $stmt->free_result();
        }
    } while ($db->more_results() && $db->next_result());
}

There are some differences to TerryE's example, but the result is the same. I'm aware that there are 7 line at the beginning that are almost identical, but as soon as I need a WHERE clause or something else, I prefer this solution to a foreach loop where I'd need to add queries manually or use exceptions with if { ... } ...

As far as I can see, there should be no problem with my solution, or did I miss something?

Saturday, May 29, 2021
 
SuperString
answered 5 Months ago
75

I found the problem - the save directory for the PHP sessions was a root apache directory, and I'm runnin nginx fastcgi. I just changed the root permissions for the folder and it works. Thanks a ton for all of your help.

Friday, August 13, 2021
 
kat_indo
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :