How to schedule dynamic function with cron job?

cron, cron-task, mysql, php

Solution

you have 2 ways, although only one will do exactly what you want to do;

1st way requires that you have access and privileges to change cron-jobs server side (example via PHP or other). Depending on what OS there are tutorials: Win , Nix

2nd way will do something close to what you want but without the minutes precision, you will loose at max 2 minutes each cycle. (see exaplanation below).

1st Way perfect way

- As soon as the user hit the form create a unique cron-task for that user using the desired datatime.

if you don't have those privileges you can use 3d part service like www.easycron.com they also offer a Free version with limited query. they also provide a REST API method to manage (CRUDE) cron-tasks.

2nd Way imperfect way

- add a new `VARCHAR` column, i called it `today` with this we will ensure that the task will run only once per day.

+----+---------+----------+------------+--------+----------+
| iD | timeDay | timeHour | timeMinute | postiD |   today  |
+--------------------------------------+--------+----------+
| 1  | *       | 9        | 0          | 21     | 30-05-04 |
|----|---------|----------|------------|--------|----------+
| 2  | *       | 10       | 30         | 22     |          |
|----|---------|----------|------------|--------|----------+
| 3  | *       | 11       | 0          | 23     |          |
+----|---------+----------+------------+--------+----------+

after that create a php file i called it `crontask.php` we will call it each 5 minutes

add this to your cronjob panel:

`0,5 * * * * /usr/bin/php /www/virtual/username/crontask.php > /dev/null 2>&1`

in the `crontask.php` file

<?php
// include() Database Config file here with mysql_connect etc...
// include() the required files ex. the file where myFunction reside...

$cron_cycle = 5; // set it equal to what used in cron command-line
$today = date('Y-m-d');
if($result = mysql_query("SELECT * FROM postDataTime WHERE today != '{$today}'")){
    while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) { 
        $postID = $row['postID'];
        $timeHour = (int) $row['timeHour'];
        $current_hours = (int) date('H'); // current hours
        $current_minutes = (int) date('i'); // current minutes
        $timeMinute = (int) $row['timeMinute'];
        // force to run at the closest cycle
        $timeMinute = ($timeMinute % $cycle === 0) ? $timeMinute : toCloser($timeMinute, $cron_cycle); 
        if( $current_hours === $timeHour && $current_minutes === $timeMinute ){
            // ensure that we have already runned a cron for this user...
            mysql_query("UPDATE postDataTime SET today = '{$today}' WHERE postID = '{$postID}'");
            myFunction($postID);
        }
    }
}
function toCloser($n,$x=5) {
    $j = (round($n)%$x === 0) ? round($n) : (round(($n+$x/2)/$x)*$x);
    return ($j-$n) >= round($x/2) ? ($j-$x) : $j;
}

?>

Explanation of the function:

Assuming that the cron shedule runs each 5 minutes, lat's say we are at 20:00 o'clock, now the cron will run at 20:05, 20:10, 20:15, 20:20 and so on...

then assuming in our DB we have those time

Jonh  : 20:05, 
Mario : 20:32, 
luke  : 20:48, 
David : 20:57, 
Jimmy : 20:06, 
Eddy  : 20:16

when the script checks against those times it will run as below:

at 20:05 -> run 20:05 Jonh, 20:06 Jimmy
at 20:10 -> run null
at 20:15 -> run 20:16 Eddy
at 20:20 -> run null
and so on....

As you see you would loose in the worst case 2 minutes each time. I think it's fair enough! ;)

Problem

I want to know how I can schedule a dynamic(auto populated data) function to auto run everyday at saved time? Let's say I have a form that once the button is clicked it sends the data to the function, which the posts the data. I simply want to automate that so that I don't have to press the button. ``` <ul> <?php foreach($Class->retrieveData as $data) { <form method="post" action=""> <li> <input type="hidden" name="name">'.$data['name'].'<br/> <input type="hidden" name="description">'.$data['description'].'<br/> <input type="submit" name="post_data" value="Post"> </li> </form> } ?> </ul> ``` Now, the form will pass the data to the function. ``` if(isset($_POST['post_data'])) // if post_data button is clicked then it runs myFunction() { myFunction(); } myFunction() { $name = $_POST['name']; $description = $_POST['description']; } ``` I tried doing the following but the problem is that Cron Job can only run the whole .php file, and I am retrieving the saved time to run from MySQL. ``` foreach($Class->getTime() as $timeData) { $timeHour = $timeData['timeHour']; $timeMinute = $timeData['timeMinute']; $hourMin = date('H:i'); $timeData = ''.$timeHour.':'.$timeMinute.''; if($hourMin == $timeData) { run myFunction. } } ``` `$hourMin` is the current hour:minute which is being matched against a saved time to auto run from Mysql. So if `$hourMin == $timeData` then the function will run. How can I run Cron Job to auto run `myFunction()` if the `$hourMin` equals `$timeData`? So... ``` List 1 = is to be runned at 10am List 2 = is to be runned at 12pm List 3 = is to be runned at 2pm ``` The `10am, 12pm, 2pm` is the `$timeHour` and `$timeMinute` that is retrieved from MySQL but based on each list id's. EDIT @randomSeed, ``` 1) I can schedule cron jobs. 2) $name and $description will all be arrays, so the following is what I am trying to accomplish. $name = array( 'Jon', 'Steven', 'Carter' ); $description = array( 'Jon is a great person.', 'Steven has an outgoing character.', 'Carter is a horrible person.' ); ``` I want to parse the first arrays from both $name and $description if the scheduled time is correct. In database I have the following ``` postDataTime table +----+---------+----------+------------+--------+ | iD | timeDay | timeHour | timeMinute | postiD | +--------------------------------------+--------+ | 1 | * | 9 | 0 | 21 | |----|---------|----------|------------|--------| | 2 | * | 10 | 30 | 22 | |----|---------|----------|------------|--------| | 3 | * | 11 | 0 | 23 | +----|---------+----------+------------+--------+ iD = auto incremented on upload. timeDay = * is everyday (cron job style) timeHour = Hour of the day to run the script timeMinute = minute of the hour to run script postiD = this is the id of the post that is located in another table (n+1 relationship) ``` If it's difficult to understand.. what is quinoa ``` if(time() == 10:30(time from MySQL postiD = 22)) { // run myFunction with the data that is retrieved for that time ex: $postiD = '22'; $name = 'Steven'; $description = 'Steven has an outgoing character.'; // the above is what will be in the $_POST from the form and will be // sent to the myFunction() } ``` I simply want to schedule everything according to the time that is saved to MySQL as I showed at the very top(postDataTime table). (I'd show what I have tried, but I have searched for countless hours for an example of what I am trying to accomplish but I cannot find anything and what I tried doesn't work.). I thought I could use the exec() function but from what it seems that does not allow me to run functions, otherwise I would do the following.. ``` $time = '10:30'; if($time == time()) { exec(myFunction()); } ```

Original source

Related problems