automatically update mysql field based on value of other field - php

I have a mysql table for subscription details
It has a start_date, end_date and status field
Now, what i would like to do is whenever end_date of subscription is reached, i would like the status field to change from active to inactive
for example when end_date > curdate, update subscription table set status=inactive
Is there a way to run a check at the end of each day to check and update this?
how can i do this?

Why not just create a view and calculate the status. Then use the view instead of the table:
CREATE VIEW vwSubscription
AS
SELECT
start_date,
end_date,
IF(end_date > curdate, 'inactive', status) as status
FROM subscription

you can use the cron job in linux based server to check and manipulate the data in db with php

what you need to write is a script that runs in the background like this
while (true) {
echo 'updating';
//check rows here
echo 'done';
sleep(10);
}
Just execute it in the shell (php -f script.php) and put that in the background and it will do what you want. Just remember that memory is important. Make sure you unset($var) everything on each cycle so your memory usage doesn't go through the roof.

Related

How to detect when a user is not online?

Well I've a admin dashboard which is PHP-Coded.
Now I want to know about my ONLINE users. For which I created a table in data base called "ONLINE". When a visitor/user comes to my site its IP is save on my database & on dashboard, show me 1 user online.
The problem starts from here. I want that when a visitor/user leave my site (close the site, close the tab, and whole browser). This saved IP (in ONLINE table) of the user, migrate or transfer to another table in data base named "VISITORS".
Detecting a user exit is a bit fuzzy. You can use javascript to send an exit notification to your server such as:
window.onbeforeunload = function() {
... insert your ajax code here ...
}
There are a lot of conditions where that won't fire though, so a better way is to use check-in code. You can make a php script that inserts/updates the ONLINE table(assumes the IP field on your table is set to be a UNIQUE or PRIMARY key, also requires you to create a TIMESTAMP field on the table - I named it last_check_in):
<?php
... connect to database ...
$statement = $db->prepare("INSERT INTO `ONLINE` SET `IP` = ?, `last_check_in` = NOW() ON DUPLICATE KEY UPDATE `last_check_in` = NOW()");
$statement->execute([$_SERVER['REMOTE_ADDR']]);
Then you can put an ajax call on a timer(here's jquery's ajax page: http://api.jquery.com/jquery.ajax/ and you can use setTimeout in your callback to schedule the next update) to make the page check in.
Then you can change your query that shows online users to only show users who have checked in recently:
<YOUR QUERY> WHERE <your WHERE stuff> AND `last_checkin` > NOW() - INTERVAL 1 MINUTE
This would actually allow you to just use one table instead of two, but if you're set on using two tables, you can write another script that moves users who haven't checked in over and put that on a cron timer.
So, to "figure out if a user left" you need to store some kind of last-activity-timestamp and determine a threshold time period for what you consider "active". This could be 30 minutes, or 15, or an hour; it's really up to you.
You can accomplish two goals with one task by using MySQL to handle your sessions. Whenever you create or update a session, you can also store the IP Address and the timestamp when the session is being updated. If the user logs out, session_destroy() will be called, which will call destroy() in your session handler, where you can "move" the IP to the table for non-logged-in users. Using a custom session handler gives you a straightforward place to put all of the logic.
Use one table "VISITORS".
For Example, period is 1 hour.
Add field:
FirstActivityInHour (DateTime, TimeStamp or Int (minutes part))
LastActivityInHour (DateTime, TimeStamp or Int (minutes part))
If visitors leave site - you can not track this action, no action. You can track last action.
If LastActivityInHour near now moment - visitor online. Non-optimal query example (FirstActivityInHour, LastActivityInHour - DateTime):
SELECT ...
FROM "Visitors"
WHERE
LastActivityInHour > DATE_SUB(NOW(), INTERVAL 10 MINUTE)
AND
DATE_ADD(FirstActivityInHour, INTERVAL 1 HOUR) > NOW();

Send confirmation mail to last inserted row

I am trying to create a simple Support Request system which users can insert their email address in a form though jQuery - Ajax and PHP into MySQL database.
After that I need to send a Confirmation Email to the inserted email owner "
every time that a new request inserted into the database". I was thinking about using the Ajax call from database but I am not sure how to select
1- latest inserted row AND
2- Not selected rows to do this( there might be a situation to have two insert at exact same time then the
SELECT email FROM tbl-request ORDER BY id DESC LIMIT 1;
might return Only the last inserted however there where at least two new entries)?
can you please let me know if there is solution to do this through MySQL Trigger or jQuery Ajax
suffii you can add a new colum to the table eg. status which contain 0 as a default value.
Now every time you send a email then update this value to 1.
so you can select the rows for which an email is not sent yet like this..
SELECT email FROM tbl-request where status=0;
It will select only the latest entry containing status = 0.
There can be many way But as my point of view this also can be a better and simplest way
you can do this using cron job.
Run a cron job line every 5 mins and set a flag to check if mail is sent or not. after sending mail set the flag to 1.
We can easily save the last time we checked in a database or file. This method of doing it would allow you to have the emailer system separate from how the record is inserted, which is what I gather you want given that you're suggesting use of Triggers or AJAX to handle it. This method will work even without access to write the database from the PHP script.
At the end of the email script run:
$fh=#fopen('last-email','w');
if (!empty($fh)){
fwrite($fh,time());
fclose($fh);
}
At the start run
$last_email_time=file_get_contents('last-email');
Then add a timestamp field to your table; this will automatically append the time the record was last edited or added.
Then your query will be:
$last_time_as_sql_date=date('Y-m-d H:i:s', $last_email_time);
$query="SELECT email FROM tbl-request WHERE timestamp>'$last_time_as_sql_date' ORDER BY timestamp DESC LIMIT 1;"
How you actually run the script depends more on your implementation; if on a server back end you could run every 5 minutes using crontab -e
*/5 * * * * php /path/to/script.php
You could send the mail from PHP at the moment the request is inserted, but you may want to keep those processes separated.
To do so, an easy fix would be to add a field 'ConfirmationMailed' or something to indicate that that mail was sent. That way you can just query for requests that weren't emailed yet.
A little bit more flexible would be to create a separate table tblRequestCommunication in which you store the communications about the request.
That table could have:
Id (PK), Date, RequestId
Subject
Content
CommunicationType
The communication type could be an enum or a reference to a separate type table in which you store the types of communication to send. One of those types could be 'Automated confirmation message', and in the table you can even store the exact date time, subject and content of that message.
Now, in your query, all you have to do is search for requests without such a confirmation:
SELECT r.email
FROM
tbl-request r
WHERE NOT EXISTS
( SELECT 'x' FROM tblRequestCommunication c
WHERE c.RequestId = r.RequestId
AND c.CommunicationTypeId = 1 /* Automated confirmation */)
This structure will allow you to expand this system for other types as well, for instance an automated mail when the request was closed:
SELECT r.email
FROM
tbl-request r
WHERE
r.State = 'Closed'
AND NOT EXISTS
( SELECT 'x' FROM tblRequestCommunication c
WHERE c.RequestId = r.RequestId
AND c.CommunicationTypeId = 14 /* Close notification */)
Also, you can store 'manual' e-mails and phone reports that are linked to the request in the same table, so you've got a full history of communication.
So, it's a bit of work to create one or two extra tables and change the query, but the abilities of your system will be a lot larger.

Update a value on specific column on specific time

Let's say I have a table like this
ID | DATETIME | VALUE
1 | 2011-12-10 01:22:46 | NO
and for example real DATETIME now is 2011-12-10 00:22:46
I want the VALUE updated to YES when the DATETIME now is the same with the DATETIME on the table.
how to do this?
use jquery ajax to make a heartbeating to the server each lets say half second in order to work with the delay if happens
1- download jquery or include it online
2- right this in a page that always opened I will give another solution if its not open
function updater()
{
$.post('ajaxChecker.php');
}
setInterval( "updater()", 50 );
the above code send a request to page named ajaxChecker.php
then you need in that page to connect to the database
I will assume you now that
and in that
make a query
$query = mysql_query("UPDATE tlbname SET `value` = 'YES' WHERE `datetime` = NOW()
");
Please check the reserved words for mysql and if you can't modify them make sure they are between ``
read about cronjobs to start it
if you include time hh:mm:ss it's going to be quite dificult to match.. but otherwise it would be like:
update tlbname set value = 'YES' where datetime = #datetime
Perhaps the best way to approach this is not to update a column at all:
ALTER TABLE tblname DROP COLUMN value;
ALTER TABLE tblname RENAME TO basetbl;
CREATE VIEW tblname AS
SELECT id,
`datetime`,
IF(NOW() >= `datetime`, 'YES', 'NO') AS value
FROM basetbl;
Now `value` will never be incorrect, and it will appear to have been updated the very instant the current time matches the yyyy-mm-dd_hh:mm:ss in `datetime`.
Alternatively, this dynamic computation could be pushed into your PHP code, with a query that looks for IF(NOW() >= `datetime`, ...).
The problem with the naive approach, that of issuing an UPDATE every minute or more often, is that you will miss an update. Any periodic UPDATE schedule — crond, an AJAX helper, MySQL's EVENT scheduler, whatever — will eventually miss a beat. Perhaps the OS crashes, or MySQL is restarted, or, very plausibly, MySQL becomes so loaded with other queries that your UPDATE takes more than a minute to complete.
Even if the UPDATE is modified to retroactively correct missed updates, there will still be a window in which `value` is wrong.

set status on record automatically after certain datetime

I have a form that users fill in to post their job advertisements and one of the fields they enter is the number of days to keep job 'open'.
I want to be able to automatically change the status of the job to 'closed' after the days that they have entered have elapsed.
The job table is already set up with status and expiry, I just need to know how to automatically change the status from 'open' to 'closed'.
I have little knowledge of MySQL and the queries that I would need to run.
Suggest that you don't keep status as a field in the database, but rather derive that status from the expiry date in your business or presentation tier. This could be done in your SQL code or in client code(PHP).
Some pseudocode:
INSERT INTO JobAd (Description, ExpiryDate)
VALUES (#Description, #Today + DaysToLive)
...
SELECT *
, CASE WHEN ExpiryDate<#today
THEN 'Expired'
ELSE 'Good to go'
END AS JobStatus
FROM JobAd ORDER BY JobStatus, ExpiryDate
When you pull those jobs out, use PHP to write the status back to the user, based partially on ExpiryDate. Again, this could be done in SQL or PHP.
Having the status derived means you won't have to create a maintenance process/task to go update an attribute in the database.

saving mySql row checkpoint in table?

I am having a wee problem, and I am sure there is a more convenient/simpler way to achieve the solution, but all searches are throw in up a blanks at the moment !
I have a mysql db that is regularly updated by php page [ via a cron job ] this adds or deletes entries as appropriate.
My issue is that I also need to check if any details [ie the phone number or similar] for the entry have changed, but doing this at every call is not possible [ not only does is seem to me to be overkill, but I am restricted by a 3rd party api call limit] Plus this is not critical info.
So I was thinking it might be best to just check one entry per page call, and iterate through the rows/entires with each successive page call.
What would be the best way of doing this, ie keeping track of which entry/row in the table that the should be checked next?
I have 2 ideas of how to implement this:
1 ) The id of current row could be save to a file on the server [ surely not the best way]
2) an extra boolean field [check] is add to the table, set to True on the first entry and false to all other.
Then on each page call it;
finds 'where check = TRUE'
runs the update check on this row,
'set check = FALSE'
'set [the next row] check = TRUE'
Si this the best way to do this, or does anyone have any better sugestion ?
thanks in advance !
.k
PS sorry about the title
Not sure if this is a good solution, but if I have to make nightly massive updates, I'll write the updates to a new blank table, then do a SQL select to join the tables and tell me where they are different, then do another SQL UPDATE like
UPDATE table, temptable
SET table.col1=temptable.col1, table.col2=temptable.col2 ......
WHERE table.id = temptable.id;
You can store the timestamp that a row is updated implicitly using ON UPDATE CURRENT_TIMESTAMP [http://dev.mysql.com/doc/refman/5.0/en/timestamp.html] or explicitly in your update SQL. Then all you need to do is select the row(s) with the lowest timestamp (using ORDER BY and LIMIT) and you have the next row to process. So long as you ensure that the timestamp is updated each time.
e.g. Say you used the field last_polled_on TIMESTAMP to store the time you polled a row.
Your insert looks like:
INSERT INTO table (..., last_polled_on) VALUES (..., NOW());
Your update looks like:
UPDATE table SET ..., last_polled_on = NOW() WHERE ...;
And your select for the next row to poll looks like:
SELECT ... FROM table ORDER BY last_polled_on LIMIT 1;

Categories