php while loop where functions are ran based on time of day - php

I have created two functions in a separate php file and want them to run over and over.
After function A completes, I want it to compare the current time, relative to the last time function B ran, and if more than 24hrs has elapsed (or whatever value I set it to), it runs function B, resets the next time for when it should be trigger to run, and continues to run function A. They need to run separately and not parallel since values altered in function A will affect function B and thus need to be separate. The ideal scenario is I have a config.php file where I set the time delay (in hours), but I can sort that out later!
I am stumped on how to get this while(true){} loop organized... any ideas?

Regardless of whether you end up doing it this way (because I think the comments about cron make some good points, and there are some other issues you may run into with a continuously running PHP script like this) here's a basic logic for executing the alternate function based on a defined delay.
// define the delay and initialize the timestamp
$delay = 86400; // 24 hours, for example
$last_time = time();
while (true) {
functionA();
// the next time functionB should execute is the timestamp for the last run + the delay
if (time() > $last_time + $delay) {
functionB();
$last_time = time(); // reset the timestamp
}
}

Would something of this nature be similar to what you're looking for?
while ($time > 13 && $time < 21)
You could have flags involved in each function as well. If a boolean flag is fired and is = 1, then continue on?

Related

Efficiency: setting a var or calling method?

Would it be more efficient to declare a var:
$datetime = Carbon::now();
and use the var in a method twice:
$toDate < $datetime && $fromDate > $datetime
Or set no var and call something like Carbon::now() twice:
$toDate < Carbon::now() && $fromDate > Carbon::now()
I would follow the DRY principle and follow the first solution:
$datetime = Carbon::now();
if ($toDate < $datetime && $fromDate > $datetime) ...
In theory, method calling could be slightly more expensive due to pushing/popping context from the stack. However, I think the difference is negligible.
Someone brought up a valid point about race conditions that could occur if you call now() method twice. The second call may return a different value than the first call.
The answer and almost everything in the programming world depends on 2 things- Time and Space and every programmer has to choose one between them when it comes to optimisation.
These 2 things are the time taken to execute a program and Space (memory) used during the execution.
So your question which is whether to save the value of Carbon::now() in a variable or call it directly depends on what you want to optimise. Time or the space.
If your php script would have been very long i.e. took more time, then it is good to call the function once and save its value to save execution time i.e. use -
$datetime =Carbon::now();
Whereas, if you wanted your program to minimise the usage of memory, which seems obvious for servers because they need to respond to multiple requests simultaneously, you can directly call the method.
But again, you can optimise only one thing either time or memory. So choose the one that you want to achieve.

How to check if time intervals are overlapping in Laravel 4.2/php?

So i have in a table tm_timekeep(id(pk), start(varchar), end(varchar)) [and a model for it] in a database with some time intervals in HH:MM format. For example:
id|start|end |
---------------
0 |10:00|10:30|
1 |11:23|11:55|
2 |13:15|15:39|
i would like to insert new rows and modify the existent ones if there are no overlappings between intervals.
if i would like to add as interval 11:57-12:40 would be ok, but 09:00-10:20 wouldn't because of 10:00-10:30, same for updateing a row. And if i would like to update a row, I need a function to check the condition before modifying the row. How should i do this?
My current code snippet:
public function checkInterval($start, $end){
$counter = 0;
$timekeepArray = Timekeep::all();
$start = date('H:i',Input::get('start'));
$end = date('H:i',Input::get('end'));
foreach($timekeepArray as $timekeep)
{
if($start <= $timekeep->end && $end>=$timekeep->start){
counter++; //in range
}
return counter;
}
}
After this i check the value of counter, but my problem is, that i always get 0 even if there are overlappings from input.
It's quite trivial - convert your time intervals to minutes, eg. 10:00 becomes 10 * 60 + 0 = 600 minutes, ends at 630 correspondingly.
Then, when you are trying to insert or update, and I would suggest you do it in Timekeep model, bound to 'saving' model event (see Model Events), you check whether:
1) Pick the last end time in minutes that is less than your new start time (that's a trivial SQL query)
2) See if there is any existing time in between that end time and your new end time - if there is, we have overlapping. Throw an exception, cancel model saving
There are several ways you could convert strings to minutes - you could store integers in MySQL (eg. 600) and then convert them to human readable hours either by defining getAttribute() or making your own methods. Or you could keep storing data as VARCHARs and do simple string manipulations (remove ':', multiply first part by 60) either in SQL or in PHP

Execute a php script everyday at different time

I have a script PHP which do requests on MYSQL server, and I want to execute itself once a day!
The first time, I execute the script myself.
And I want the script, at the end of the execution, choose a random time in the day, between 8:30AM and 7:30PM, and reexecute itself automatically the day after, at this time. Is it possible?
To choose a time randomly I have coded like this:
$tomorrow = new DateTime(date('Y-m-d H:m:s', time()+86400));
$tomorrow1 = $tomorrow -> setTime(8,30,0);
$tomorrow2 = $tomorrow -> setTime(19,30,0);
$min_time = strtotime($tomorrow1->format('Y-m-d H:m:s'));
$max_time = strtotime($tomorrow2->format('Y-m-d H:m:s'));
$rand_time = rand($min_time, $max_time);
But then I don't know how to do an automatic execution for the script at this time. Maybe I can pause like this:
sleep ($rand_time - time());
But I don't know how to reexecute the script after that. And I don't think sleep is the best solution. Do you if there is a way and how to do this?
Allright, I can use cron, but the issue still remains: I need to be able to modify the task scheduler for the day after everyday by the php file itself!
The approach taken by e.g. APT::Periodic is to start the job at a fixed time (in your case 08:30) and sleep for a random period of time as the first command in your job (in your case for $(($RANDOM % 39600)) seconds, assuming your shell is Bash).
This avoids the need to write anything to the crontab.
I don't know PHP, but I think it would look something like:
#/usr/bin/php
// Wait 0-11 hours before starting (invoked by cron at 0830)
sleep(rand(0, 39600));
// It's now a time between 0830 and 1930
// rest of your code here
and your crontab would be simply
30 8 * * * /path/to/my/script
Alternatively, don't sleep at all in your script, but do the sleep in the crontab command:
SHELL=/bin/bash
30 8 * * * sleep $(($RANDOM % 39600)) && /path/to/my/script
This may be preferable if you ever need to execute the script by hand (and not want to wait up to 11h for it to start).

PHP server side incremental counter

sorry I am new to PHP and need some help/guidance on creating a counter that will work server side, so I guess update an initial value?
I need for example to start with a base number of 1500 and have that number increase by 1 every 2 minutes, obviously so any visitors will see an increased number each time the visit.
Would the initial value need to be stored in sql or can a txt file be updated?
Any help would be great,
Thanks
It can be done in SQL if you want it but a text file is OK too, just save a value (1500), then create a cronjob and let it execute a PHP file where you'll have to set up the code that executes an SQL query which updates that value OR the code to update that text file every 2 minutes.
Example:
# Every two minutes
*/2 * * * * /your/path/too/this/file/updatecode.php
In your PHP file:
$SQL = "UPDATE table SET columnname = columname + 1";
// etc...
// OR the text file update code
If you don't need to store it specifically for some reason, then you don't need to run cron etc... Take a time stamp of a specific point in time you want to start at. Then calculate minutes since and add it to your start number (1500)
//Start Number
$n = 1500;
$cur_time = time();
$orig_time = strtotime("2013-10-21 10:00:00");
//New Number + difference in minutes (120 seconds for 2 mins) since start time
$newn = $n + round(abs($cur_time - $orig_time) / 120,0);
// Output New Number
echo $newn;
And if you wanted it in one line for copy/paste
echo 1500 + round(abs(time() - strtotime("2013-10-21 10:00:00")) / 120,0);
You could do this without a database just using dates. work out the difference in time between two dates (the current date and the starting date when you created the script), then divide that down into the correct amount of milliseconds for 2 minutes, and add that to your initial 1500.
If storing it is needed a SQL database for this is probably overkill.
Create you number, serialize it and store it to a file. Load it from the file next time, unserialize, increment, serialize and save.
You can save a time stamp along with the number to the file to avoid having to run some job every 2 minutes and instead calculate the correct value when you load the number back from the file.
Something like this (but error checking etc should be added and I haven't actually tried it to make sure the calculation is correct... but the main idea should be visible).
<?php
if(file_exists('mydatafile')) {
$data = unserialize(file_get_contents('mydatafile'));
// Calculate correct value based on time stamp
$data['number'] += round((time() - $data['timestamp']) / 120);
}
else {
// Init the number
$data["number"] = 1500;
}
// Print it if you need to here
// Update time stamp
$data["timestamp"] = time();
// Serialize and save data
file_put_contents('mydatafile', serialize($data)));

How do i run a php script every second?

I am currently writing a online game. Now I have to check if an event happen (checking timestamp in database) and depending on that execute some actions. I have to check for an event every second.
I wanted to use a cronjob but with cron you can run a script only every minute.
My idea was to use cron and loop 60 times in my php script. But I think this isn't the best solution.
So whats the best way to run a script every second?
I searched for a better solution but it seems that my first idea, with clean code, is the best solution.
This is my current code:
<?php
set_time_limit(60);
$start = time();
for ($i = 0; $i < 59; ++$i) {
// Do whatever you want here
time_sleep_until($start + $i + 1);
}
?>
Why not modify the script so that it just repeats the code every second? This will reduce the parsing overhead and be less complicated.
You should probably run the script once, and use a loop with delay to accomplish your desired timing.
The side benefit is that this is more efficient, and you would only have to open resources (ie, databases) once.
You shouldn't want this :P. No host will accept your cronjob is running every second every minute?
You can save the time it runned in a database, and the next time you run it calculate the time between both runs and do the calculations you want. every second is a very bad idea.
$total_time = 0;
$start_time = microtime(true);
while($total_time < 60)
{
//DoSomethingHere;
echo $total_time."\n";
//sleep(5);
$total_time = microtime(true) - $start_time ;
}
add this in crontab to run every minute.

Categories