"viewed" system - once per user - php

I need to implement "viewed" system.
How it can be done, so that pressing F5 would not increase viewed number for more than 1 per user?
SO also has such system.
Cookies, sessions, db? How it is usually done?

You will need a combination of technologies here. Each user needs to be identified uniquely (using sessions, cookies, whatever works best in your scenario). From there, you will need to be maintaining a database of hits for an item with the user's unique key (stored in their cookie or session or whatever).
When the user accesses the page, check the database to see if that user's unique key already has a hit on that page. If not, add it. Regardless, once done, pull the total number of hits that the item has had from the database. Tahdah.

Just store in your database user_id, resource_id (eventually timestamp) and before you increase viewed value check whether SQL like this:
SELECT COUNT(*) FROM ... WHERE user_id = ? AND resource_id = ? (AND timestamp > NOW() - 7 DAYS or sth)
doesn't return 1.

This depends a lot on the situation. For example, if each user is logged in with a user ID, it would be very different then if you are doing a splash page where users are not expected to be logged in.
I will assume you are in the latter category, and that users are not logged in to your page. If this were the case, I would recommend setting a cookie using the setcookie command, this could be accomplished like this:
if (empty($_COOKIE['hasViewed'])) {
//increment the total number of views in the
//database or wherever we are storing it.
$viewer->incrementViews();
}
//make sure they have a cookie for next time
setcookie("hasViewed", "1", time() + 60*60*24*30);
Note that in this example, the user would be able to cause your view to increment again if they haven't seen the page in 30 days.

Related

Laravel Session Query Unique Users

I noticed a bug in my application when a user logs into my site from multiple computers, they are displayed twice in the list of logged in. I managed to fix this by adding the groupBy('user_id') to my query, however I noticed something else wrong now: the user's last active field only updates for 1 of them.
return $query->whereNotNull('user_id')->with('user')->groupBy('user_id')->get();
To make this a bit clearer, prior to adding groupBy, lets say a user Bob logged in at 2 locations. My logged in users would look like this:
Bob Last Active 1 hour ago, Bob Last Active 6 minutes ago
However, with the groupBy, it might show this:
Bob Last Active 1 hour ago
Even though the latest activity is 6 mintues ago. I tried running a sortBy('last_activity'), however both ascending and descending have failed to fix this issue. Does anyone have any ideas?
Thanks.
It's hard to say with the question as-is because you don't explain what you're storing in that table and how you store it. I'm guessing you use a database session driver?
Anyhow, each user session is unique to a given location. This is why you get 2 entries when a user is logged in at multiple locations. A "location" here is considered different if it doesn't share cookies with another location (e.g. a private browsing window is enough). The session in Laravel is identified by the session cookie laravel_session.
What I suggest for your "last active" timestamp is to store it in your User model directly and update it when a user accesses your site. It makes much more sense to persist this uniquely with the user than trying to reconstitute the information from active sessions. Also, stale sessions are eventually removed and the information for a user would be lost.
update
group by works with aggregate functions. What you want is something like this:
SELECT user_id, MAX(last_activity)
FROM SessionTable WHERE user_id IS NOT NULL
GROUP BY user_id
With query builder:
\DB::table('session_table')
->select('user_id', \DB::raw('max(last_activity) as last_activity'))
->whereNotNull('user_id')
->groupBy('user_id')
->lists('user_id', 'last_activity');
should return something like this:
[
'user_id1' => 'last_activity1',
'user_id2' => 'last_activity2',
...
]

requesting unique id every page load

I'm creating a page that needs to select a Unique ID for every page load. It's basically a purchase order system, but the PO will be just the UID, so it's important that no user can get the same ID. I tried doing just calling upon last ID, then adding 1 and submitting, but that could create conflict if two or more users are entering at the same time. What's the best way to pull a UID for each page load? Any solutions?
Thanks
Lloyd
UniqId() is one way, but results in large numbers. As V Patel says, there's also "Auto Increment" and this is probably the option you want.
In MySQL set up a table (say "PurchaseOrders") with a field "po_id" and set that to be the primary key and auto increment. Add another field "po_status" (TinyInt*1) and another "po_lastused" (Date*1). Status will be 0=draft, 1=final, 2=shipped etc. LastUsed is the last time the user accessed the details.
When you want to create a new purchase order, INSERT INTO PurchaseOrders(po_status, po_lastused) VALUES(0, NOW()); Note: you've not specified the actual purchase order
You can get the po_id through asking for the "last insert id" (http://php.net/manual/en/mysqli.insert-id.php, http://php.net/manual/en/function.mysql-insert-id.php, http://www.php.net/manual/en/pdo.lastinsertid.php, depending on your coding library)
Store the po_id in a session variable so that when the user returns, you know their po_id(*2)
Each time a user access a purchase order, if "last updated" was more then 5 minutes ago, update the timer.
Periodically deleted all purchase orders that are draft and where last updated is older than your session (e.g. after a day)
This way, you'll end up with nice purchase order numbers that are easily quotable.
*1 For the purists, You can also use Enum for the status, and int for dates - depends on your preference. You can also set the date to be automatically updated. But I'm keeping it simple.)
*2 Again, for the purists, there is more security you could implement here to ensure the "other" users can't access someone else's purchase order, but this is enough to start.
You can use the uniqid function to get a unique key. Run it through hexdec if you need an integer.
PHP has one:
http://php.net/manual/en/function.uniqid.php
Use auto increment feature of the database in use, especially if you like it to be a number and don't need it till you want to persist it.

How to limit number of searches per user in PHP

I am trying to develop an application where a guest user can see search results only 10 times after which he should be directed to payment page. I can use sessions on the search results page, but how can i put a counter on that. Can any please help me on that.
Every time a search request is created you just do
$_SESSION['counter']++
Altough he can just get rid of the limit by deleting cookies. An other approach would be, to store the number of search requests in a database table including the IP address, but this can also be bypassed, while it takes more work to do so.
If you should put search limit on current running session than you can use $_SESSION['count']++.
And if you should put search limit per day than you can use 'UPDATE users SET search_count = search_count+1'
It depends whether you would allow him to search again when he comes to your website or just those 10 times even after he visits after a year.
For temporary bases, you can use cookies (see setcookie function) but if you want to restrict him once and for all, you will have to ssave that information in database.
You would code something like:
<?php
session_start();
$_SESSION['counter'] += 1;
// more logic/code
Now you will have to save the value of $_SESSION['counter'].
If your users can search only while logged in, then I see no problem - you definitely have db table with users, so just add another column to it, say 'search_count' and increase it by one each time user attemps a search.
For example:
UPDATE `users` SET search_count = search_count+1
You can also use a counter in the table user of your db and call a function everytime the user looks for the result, that increments the value by one, so a simple UPDATE.
I think maintaining database will be much better then maintaining SESSION because may be due to some reason session removed or erased.
add a field within users table name for example visit with default value 0 and update this field on every visit of search result page..
"update usertablename set visitfield = visitfield + 1 where user_id = ".$current_user_id
thanks

effective counter for unique number of visits in PHP & MySQL

I am creating a counter for unique number of visits on a post, so what I have until now is a table for storing data like this;
cvp_post_id | cvp_ip | cvp_user_id
In cases a registered user visits a post, for the first time a record is inserted with cpv_post_id and cvp_user_id, so for his next visit I query the table and if the record is available I do not count him as a new visitor.
In cases of an anonymous user the same happens but now the cvp_ip and cpv_post_id are used.
My concerns is that I do a query every time anyone visits a post for checking if there has been a visit, what would be a more effective way for doing this?
Create a unique index containing your three columns and execute your insert using IGNORE keyword:
INSERT IGNORE INTO your_table (cvp_post_id, cvp_user_id)
VALUES(1, 1);
Most users will only visit once so you avoid a SELECT followed by an INSERT.
There is a very simple way that can help you to save a lot of queries using sessions, it's should be something like that:
if(!isset($_SESSION['visited_post'][$yourPostID]))
{
//Perform your code
$_SESSION['visited_post'][$yourPostID] = true;
}
Make a session for the user and while the session is on you need to check but once (when opening the session). From now on when the user visits a post you already know he is in the database.

script to tell me who, and how many users, are online

In my research to find a way to make PHP tell me how many people are 'online' on my site I've discovered that there are ways to 'estimate' this.
I've chosen to log everything that happens on the site, also for error-management sake, but now i'm stuck at writing my SQL query.
Basicly I have a database with 'IP', 'userid' and 'datetime' and I figured that a query like this would do the trick:
SELECT distinct(IP), datetime
FROM `bigBrother`
WHERE datetime BETWEEN DATE_SUB(NOW(), INTERVAL 3 MINUTE) AND NOW()
The problem is that my site is mostly viewed and used by students on the school network, and well... they all have the same IP.
So the question is, am I doing this right, and can I select two distinct rows from my database, so that I can sort out the registered users (who will have a 'userid' - others will have userid = 0)?
Just use the session id instead of the IP.
Use cookies instead of IP addresses.
PHP makes it very easy with it’s session mechanism. On each you first do a session_start() and then you use the value returned by session_id() as a identifier of the visitor that you can put in your database.
I created a system for a school site that asked for this feature as well and here's how i did it.
I had a table of users, in that table there was a field called "online_time"
On every page a function was called if the user was logged in that updated the "online_time" to the current time of that user. (unixtime)
Then i had an "Who is online" function that looked at the "online_time" and displayed all the users with the online time of the last 5 minutes.
EDIT to the comment:
You could make the same function save the session id in another table and the time it was saved. The session id is unique to that user browsing, so you could get the number of session id's active within the last 5 minutes.
session_id()

Categories