Update sql post on specific date "behind the scenes"? - php

I have a php website with a news section and the posts are stored in an SQL database. Each post has an expiration date (i.e. 2016-03-01) and an active column that is set to true or false. Active = true shows post.
I want the active column to change from true to false on the expiration date so that the post is no longer visible on the page. I know how to do this with basic php but that requires an input from the website, i.e. a push of a button or the page to be loaded, for it to update.
Is there a way for the database (or php) to do this behind the scenes and update the post on that specific date?

I suppose you are using MySQL server. If this is the case, you can use events. You can define events to execute queries every hour, minute, etc.
CREATE EVENT remove_expired_posts
ON SCHEDULE
EVERY 1 DAY
DO
UPDATE posts SET active = 0 WHERE expiration_date <= NOW();
More generally though, you can avoid this and add an additional condition when selecting the posts to be shown:
SELECT * FROM posts WHERE active = 1 AND expiration_date > NOW();

The tip from #YUNOWORK worked fine. My web hotel didn't have crontab installed but I am now testing a web service that does the same thing. Works really great!
I'm using www.cronless.com right now. It's free and does what I want.

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();

Multiple DB users updating at the same time

I am curious what path I should take to accomplish the following. I want multiple computers at one location to be able to view and make changes to data inside a mysql DB with a web browser. I dont have extensive knowledge in this area, but from what I do remember this was very difficult if not impossible.
Example: Lets say I have a record for John and I want 2 computers to be able to edit Johns record. Please note that the computers will not be editing the same portion of Johns record. Lets say one record is changing a status from need to be called to called and the other computer is changing the status of need to be ordered to ordered.
I want a solution that could natively handle this.
My current knowledge is building web interfaces with PHP and SQL. I would like to use these languages as I have some prior knowledge.
So my question: Is this possible? If, so exactly how would it work(flow of info)?
There are several ways that you can accomplish this. There's already some great PHP database editing software packages out there (phpMyAdmin).
To handle this in code though you can either use Transactions (depending on what flavor of SQL you're using this would be done differently)
One of the easier ways to ensure that you don't have people's data clashing with one another is just by adding additional where clauses to your statement.
Lets say you have a user record and you want to update the last name from Smith to Bill, and the user ID is 4.
Instead of writing
UPDATE users SET lastName='Bill' WHERE id='4'
You would add in:
UPDATE users SET lastName='Bill' WHERE id='4' AND lastName='Smith'
That way if someone else updates the last name field while you're working on it, your query will fail and you'll have to re-enter the data, thus faking a transaction
Use Transactions. Updating a single record at the exact same time isn't really supported, but applying one transaction followed immediately by another certainly is. This is native to MySQL.
START TRANSACTION;
SELECT #A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=#A WHERE type=1;
COMMIT;
One other thing to do is the old desktop approach. Wich is almost mannualy control the flow of modifications. I will show:
Say that you have a client table with the fields id, firstname, lastname, age. In order to control multiple users updates you will add the version integer default 0 field to this table.
When you populate the object on the form to an user you will also store the actual version that the user has selected.
So lets assume that your client table is like this:
id firstname lastname age version
1 Tomas Luv 20 0
2 Lucas Duh 22 0
3 Christian Bah 30 0
When the user select the client with the id=1 the version of this row is, in this moment, 0. Then the user update the lastname of this client to Bob and submit it.
Here comes the magic:
Create a trigger (before update) that will check the current version of that registry with the version that the user previously selected, something like this (this is just pseudo code, as I'm doing it from my head):
create trigger check_client_version on client before update as
begin
if new.version != old.version then
throw some error saying that a modification already was done;
else
new.version = old.version + 1;
end if;
end;
On the application you check if the update has this error and inform to user that someone else made change on the registry he try to change.
So with the given example it would be like:
1 - The user A selected the row 1 and start editing it
2 - At the same time the user B selected the row 1 and save it before the user A
3 - The user A try to save his modifications and get the error from the application
On this context the user A has the version field pointed to 0 also is the user B but when the user B save the registry it now is 1 and when the user A try to save it it will fail because of the check trigger.
The problem with this approch is that you will have to have a before update trigger to every table in your model or at least the one you are concerned with.

Queries at the same time using MySQL

I'm designing a chat application using AJAX, PHP, MySQL and am having a problem.
MySQL table is like this username[varchar11]-taken[enum-0,1](coloumns) generally a user who wants to talk to userX, firstly checks if taken value of userx is 0 or 1
SELECT * FROM usertable WHERE username=userX
If it is 0 the user updates taken as 1:
UPDATE usertable SET taken=1 WHERE username=userX
and starts to talk to userX.
But when there are two users who want to talk to userX and check the taken value at the same time unconsciously, they both get 0 response. As a result of it, both of their updates are taken as 1 afterwards and start to talk to userX at the same time. Effectively, 3 users will be talking each other. This chat site is supposed to allow a user to talk to maximum one user at the same time. I'm trying to design it like that.
I'd appreciate any suggestions. What I need is something which is going to stop other users from checking and updating taken value until one finishes to check and update taken value.

How to generate statistics on article views last week

I see on sites that they sometimes have a statistic showing how many views an article or downloads a file had over the last week. I think download.com does something like this. I was wondering how they go about doing this. Are they actually keeping track of every days downloads or am I missing something really basic?
Are they doing something like having three rows called total_downloads, last_week_downloads, this_week_downloads. Then every week, copying the value of this_week_downloads to last_week_downloads and then resetting this_week_downloads to 0?
There are a couple of ways to do it, depending on what your trying to get out of the stats.
One way is to include a visits column on your table, then just increase that number by 1 each time that article's page is loaded.
This however isn't very good for giving the past weeks number of views. You can do this in 2 ways:
1) another column in your table doing the same as visits, but run a cron job to put it back to 0 every week.
2) create another table which holds article_id, ip_address and timestamp, you would insert a record each time someone visits the article, storing their IP address (allowing you to roughly get page views and unique page views), and of course the timestamp allows you to query for only a sub-set of those records. Note: using this method you could store more information for stats, but it does require a lot more server resources.
The most basic way you can do this is associate a MySQL field alongside your article on the database and just increment it.
Assuming you we're retreiving article 123 from your database you would have something like this on your code:
<?php
// this would increment the number of views
$sql = "UPDATE table SET count_field=count_field+1 WHERE id=123";
...
?>

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.

Categories