Change record automatically - php

On the website i'm developing i'm making a system for ban and unban users.
In my database i have a table 'banned' with fields about the bans (userID, active, date was made, reason ecc).
What i want to do is:
Add another field for expire date, and when this date occur, change automatically the field 'active' to 0.
How i can do that?

I would not use two fields like you did -- because I would not want to depend on a task to change back the active field when the un-ban date is reached.
Instead, I would only use one datetime field, called like banned_until; and this field would either:
Be NULL when the user is not banned,
Or contain the date until which the user is banned.
Then, when the user tries to do something (log-in, post, ...), I would check that :
This field is NULL, in which case the user is not banned
Or that the date contained in this field is in the past, in which can the user has been banned, but is no longer.
In the second case, you could even reset the field to NULL, as the un-ban date has been reached.

Its either you use a cron script or when getting banned users, you apply a where clause to check if the the ban has expired

Create a php script that will check if time is passed the expiration date. SQL will be something like this:
UPDATE banned SET active=0 WHERE expire_date<=NOW()
Save it as a for example task.php
Then create a cron task with crontab -e
*/10 * * * * php /path/to/your/taks/task.php
And this will cause this script to be executed every 10min and unban all banned ppl.
--
There are other ways, perhaps better ones, like e.g. Pascal described, but this answer is for your idea.

You can compare expiry_date value with current_date to check if a user is active or not on his login.
SELECT
( DATE_FORMAT( expiry_date_field, '%Y-%m-%d' )
<
DATE_FORMAT( CURRENT_DATE, '%Y-%m-%d' )
) AS isActive
FROM
banned
WHERE
user_id=?;
A 0 returned represents in-active status and 1 as active.
But irrespective of a user's login, if you want to maintain active status of users, you can achieve this using the Event Scheduler.
Following example gives you an idea in implementing one.
drop event if exists event_user_bans_scheduling;
delimiter //
create event if not exists event_user_bans_scheduling
-- on schedule every 86400 second starts 00:00:00
-- at timestamp( adddate( current_date, 1 ),'00:00:00' )
on schedule every 1 day starts timestamp( current_date + 1, '00:00:01' )
comment 'Scheduler to update active status of users'
do
UPDATE my_app_db.banned
SET ACTIVE=0
WHERE
date_format( expiry_date_field,'%Y-%m-%d' ) = date_format( CURRENT_DATE, '%Y-%m-%d' );
;
//
delimiter ;
Note:
The global event_scheduler system variable determines whether the Event Scheduler is enabled and running on the server. Read complete notes on Event Scheduler Configuration before working on MySQL events.

Related

Count active users per hour based on two datetime entries

I have a MySQL query question.
In my web app I record the active listeners on my Shoutcast server in a MySQL database table, which includes "created", a datetime field for when they tuned in, and an "updated", a datetime field for the latest time the server polled the Shoutcast server (each minute). Plus, I also retrieve the duration in seconds of there listening session, plus the uid (aka session id) which is unique to each session.
What I would like to do is count the amount of listeners per hour, for example 13:00 = 20 listeners, but I would like to include not only those who are tuned in, so "created" datetime field, but also any listeners who where still listening from the previous hour, so the "update" datetime field.
What query would I need to achieve this. I would only generate 1 days worth of results at a time.
I understand how it would use something similar to "COUNT(id) AS hits" and "GROUP BY", but I'm not sure how to factor in the datetime fields, as the "update" datetime field is constantly updated, as long as the user is still listening. And some users can remain listening for 3 hours+.
Edit
The the main parts of the database schema is: id (int 20), created (datetime), updated (datetime), uid (int 20), duration (int 10).
The desired result would look something similar to:
(Time / hits) 0900 => 10, 1000 => 15, 1100 => 5, 1200 => 8, 1300 => 25
and so on...
This is a query I've used to filter results by country, which uses group by and count():-
SELECT country, COUNT(id) AS hits FROM listeners_log WHERE YEAR(created) = YEAR(NOW()) AND MONTH(created) = MONTH(NOW()) AND duration >= 60
The query also has an added filter on the end, to filter out session that are less than 60 seconds long.
To elaborate a little more, the created field reflects when a user connects/starts a listening session. For example, they tune in at 2016-03-21 15:00:00 that is reflected in the created field. But if they're still listening in 1 hour's time, the update field will read 2016-03-21 16:00:00, but the created field will remain the same.
Update:
I've come up with the following SQL, but this only counts the inital connection, indicated by the created field, and ignores if a use remains connected from one hour to a next.
SELECT HOUR(created), COUNT(id) AS hits FROM listeners_log WHERE DATE(created) = CURDATE() group by HOUR(created)
So you will be only needing to query on 'update' datetime field, because even if a new user comes its entry gets created with 'created' datetime as well as in next update under 'update' datetime, so now your concern will be only to query on 'update' datetime for any particular hour.
SELECT COUNT(id) FROM TABLE_NAME
WHERE update_Field BETWEEN DATE(NOW() - INTERVAL 1 HOUR);
This is a sample query to help you out, I don't have schema now to test it.
Modify it in your way and
Let me know if it doesn't work.

MySQL event scheduler refresh error PHP

I have this code in my php, but everytime I refresh the page it says Event 'expired' already exist. any way that it would not pop up anymore?
$auto = mysql_query("CREATE EVENT expired ON SCHEDULE EVERY 1 MINUTE DO UPDATE stocks SET status='expired' WHERE expdate < NOW() ") or die (mysql_error());
Thanks
By the looks of it, every time you refresh the page it will attempt to create a new event with the name expired.
If you only want to create one event and never worry about it again (and based on that query, it looks like you do), you should just do it once in the database directly.
However, if you really want to keep it in your code, you could use IF NOT EXISTS: https://dev.mysql.com/doc/refman/5.1/en/create-event.html
CREATE EVENT IF NOT EXISTS expired ON SCHEDULE EVERY 1 MINUTE DO UPDATE stocks SET status='expired' WHERE expdate < NOW()
However, if all you want to do is determine the state of a stock at a give time, it might make more sense to use MySQL's IF logic to derive a status at any point (and not actually have a status field in your table): https://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#function_if
SELECT *, IF(expdate < NOW(), "expired", IF(expdate < NOW() + INTERVAL 10 DAYS), "critical", "fine")) AS status FROM stocks

Daily cron to poll mysql and update status based on timestamp

I have a db full of email users that lists the date and time they signed up in a column called signup_date using the DATETIME type (it uses now() ) and I also have an expire_date column which lists the same format but exactly a year later using ADDDATE(NOW(), INTERVAL 365 DAY)
I have added a status column with values being either 0 or 1. I guess this can be an ENUM type. Upon registration, status is set to 1 for active.
What I want is that if the timestamp of the expire_date is older than the current time, the cron should execute an update on that row of the user setting the status to 0. In postfix, I altered the query and appended the status=1 so that it will select the user with only status of 1. If the status isn't 1, then the user will not be found and won't be able to log in. This cron can run daily. I'm not too anal about having it run every second. Users can renew their emails within the next day. So this is my simple way of expiring emails, if they are not active or so after a year. What I need help with is constructing the cron. Should this be done with just php or does some bash need to be used? Im unclear of how to structure the script. Thanks.
Why maintain an additional flag column? You can calculate the status on the fly
SELECT *
FROM table_name
WHERE expire_date > NOW()
This will return only unexpired rows
If you need status to be produced as a column you can do
SELECT *, (expire_date > NOW()) status
FROM table_name

How to INSERT days to keep a MYSQL calendar table current?

I have a calendar table in my MYSQL database with one field named datefield (type DATE).
Previously I inserted dates from 2008-01-01 to 2010-01-01 but now I want to add every day until the current date. Unfortunately, I'm completely forgotten how I did this.
I'm also wondering if there is any way to automate the process of keeping this table current.
I'm using PHP so I guess I could do a new INSERT every day? Or is there some way to do this directly in MYSQL?
thanks,
tim
Here's a quick hack:
drop table if exists dates;
create table dates(datefield date);
drop procedure if exists insertDates;
delimiter $$
create procedure insertDates(start_date date)
begin
set #days = 0;
set #end_date = str_to_date('1970-01-01', '%Y-%m-%d');
while (#end_date < curdate()) do
insert into dates
select
date_add(start_date, interval #days day)
from (select #days:=#days+1) r
;
set #end_date:=(select max(datefield) from dates);
end while
;
end $$
delimiter ;
call insertDates('2012-06-06');
select * from dates;
For the daily insert you can try a cron job or MySQL offers "EVENTS", something like:
CREATE EVENT yourDB_Schema.insertDateEachDay
ON SCHEDULE EVERY 1 DAY
DO
INSERT INTO yourTable (yourDateColumn) VALUES (CURDATE());
Read more about it here:
MySQL Create Event manual entry
An event is associated with a schema. If no schema is indicated as
part of event_name, the default (current) schema is assumed.
_
Not specifying STARTS is the same as using STARTS
CURRENT_TIMESTAMP—that is, the action specified for the event begins
repeating immediately upon creation of the event.
I think the easiest way to do what you describe is set up a daily recurring task to run a php script, such as a cron job. There is also a web based provider that will call a script from your webserver on a cheap, recurring schedule. http://webcron.org

How do I create a timed ban on an account? (PHP/mysql)

I want to create a function that allows me to ban an account for 10days.
In the dbc, I have a field called "ban" and Boolean of 1=notban, 0=ban. I also have a field called "date_banned" which is just the timestamp of when the user got banned.
My question is how do I create a time frame of 10days from the date the user was banned?
ex: James was banned on "2010-05-03 20:43:48". So how can I go about adding 10days to the timestamp? And after 10days, it would set the "ban" equal to 1(which is not banned).
EDIT: how can i show how many days the user has left of a ban? ex: 8 more days till unban
Can I...do NOW()-$date_banned? or how do I subtract the ban date from the current date?
To add 10 days to your date_banned field in MySQL, you can simply use the DATE_ADD() function. You could do the following check when the user tries to log-in, to see if the ban has expired:
... WHERE NOW() > DATE_ADD(date_banned, INTERVAL 10 DAY);
Then you may want to toggle the ban field when the user tries to log in. Otherwise you can run a scheduled job every day, or at any other rate, that checks for expired bans and updates this field accordingly.
However you do not actually need the ban field to check if a user is banned or not. In fact you may want to consider eliminating it. Actually, I would go further and suggest to use a banned_until instead of date_banned (or use them both). The banned_until field would make your queries simpler, and would allow you to predefine arbitrary ban durations at the time the ban is issued. In this case, when a user logs in, you can simply do the following check:
... WHERE NOW() > banned_until;
UPDATE:
To get the number of days remaining until the end of the ban, you can use the TIMESPANDIFF() function in MySQL:
SELECT TIMESTAMPDIFF(DAY, NOW(), DATE_ADD(date_banned, INTERVAL 10 DAY)) ...
Or if you were to use the banned_until field, it will be even shorter:
SELECT TIMESTAMPDIFF(DAY, NOW(), banned_until) ...
unban_date=DATE_ADD(NOW(), INTERVAL 10 DAY) should do the trick
Then just have a cron that checks to see if anybody's unban_date is in the past, and you can update your banned flag.

Categories