php and mysqli actions in cron jobs? - php

I usually update my site "by hand", entering in one page called "enterheretoupdate.php". This page refreshes every minute to do all the job I need, so while this page is "open", my site keeps refreshing every minute.
What does "enterheretoupdate.php" do? It makes things related to mysql: create tables, selects from tables, add rows to tables, etc. Apart from that, it also make calculations on php and updates .json files.
I would like to create a cron job, so that it is not necessary for me to visit "enterheretoupdate.php" on my computer for updating my site every minute.
I am quite new on this, but I have learned how to create a cron job (I use 1and1). The example cron job I have created, consisting on sending an email every minute, works fine.
But then, I tried to save "enterheretoupdate.php" as a cron job and it does not work. Is there a "limitation" on the things a cron job can do? How should I "translate" my php file to make it work as a cron job?
Any help is really welcome.
This is how my .php file looks like:
<?php
$page = $_SERVER['PHP_SELF'];
$sec = "10";
//Change 1 to reload, 0 to not to reload;
$reload=1;
$gamecode=7;
$cmp="EL";
$year=2017;
if ($reload==1) echo"<head><meta http-equiv='refresh'content=".$sec.";URL='".$page."?gamecode=".$gamecode."&cmp=".$cmp."&year=".$year."'></head>";
include("../newcon.php");
include("../formulas.php");
include_once("funLightCreateTables.php");
include_once("funLightFirstFive.php");
include_once("funLightChanges.php");
include_once("funLightLiveJsons.php");
if ($cmp=="EC") {$l="U";}
if ($cmp=="EL") {$l="E";}
//Check
$q="SELECT * FROM LightLiveSchedule WHERE year=".$year." and cmp=".$cmp." and gamecode=".$gamecode."";
$res=mysqli_query($link,$q);
while ($r=mysqli_fetch_assoc($res)){
$started=$r['started'];
}
if ($started==0){
LightCreateTables($cmp,$year,$gamecode);
$q="UPDATE LightLiveSchedule SET started=1 WHERE year=".$year." and cmp=".$cmp." and gamecode=".$gamecode."";
mysqli_query($link,$q);
}
//Read
$pbp=file_get_contents("http://thesite.com/data.json?gamecode=".$gamecode."&seasoncode=".$l.$year."");
$pbp = json_decode($pbp,true);
//Insert
mysqli_query($link,"Truncate P_Live_Temp_".$cmp."_".$year."_".$gamecode."");
$lres=0;
$vres=0;
$n=0;
for ($i=0;$i<=4;$i++){
$nplays[$i]=count($pbp[$qtitle[$i]]);
$ii=0;
for ($j=0;$j<=$nplays[$i];$j++){
//change results
if ($pbp[$qtitle[$i]][$ii]['PUNTOS_A']!=null) {
$lres=$pbp[$qtitle[$i]][$ii]['PUNTOS_A'];
}
if ($pbp[$qtitle[$i]][$ii]['PUNTOS_B']!=null) {
$vres=$pbp[$qtitle[$i]][$ii]['PUNTOS_B'];
}
//clean
if (strpos($pbp[$qtitle[$i]][$ii]['CSDESCWEB'],"(")==0) {$play=$pbp[$qtitle[$i]][$ii]['CSDESCWEB'];}
if (strpos($pbp[$qtitle[$i]][$ii]['CSDESCWEB'],"(")>0) {$play=substr($pbp[$qtitle[$i]][$ii]['CSDESCWEB'],0,strpos($pbp[$qtitle[$i]][$ii]['CSDESCWEB'],"(")-1);}
//count
$points=0;
if ($play=="Three Pointer") {$points=3;}
if ($play=="Two Pointer" or $play=="Lay Up" or $play=="Dunk") {$points=2;}
if ($play=="Free Throw In") {$points=1;}
//ntconsole=00:00 at End Game
if ($play=="End Game") {$pbp[$qtitle[$i]][$ii]['NTCONSOLA']="00:00";}
//insert
$q="INSERT INTO P_Live_temp_".$cmp."_".$year."_".$gamecode."
(orden,shteam,shloc,shvis,quarter,minute,ntconsole,pcode,play,locres,visres,points)
VALUES
(".$n.",'".$pbp[$qtitle[$i]][$ii]['NTEQUIPO']."','".$pbp['ca']."','".$pbp['cb']."',".($i+1).",
".$pbp[$qtitle[$i]][$ii]['MINUTO'].",'".$pbp[$qtitle[$i]][$ii]['NTCONSOLA']."',
'".str_replace(" ","",substr($pbp[$qtitle[$i]][$ii]['NTJUGD'],1,10))."','".$play."',".$lres.",".$vres.",".$points.")";
mysqli_query($link,$q);
$ii++;
$n++;
}
}
Do you think it is suitable for a cron job? How should I proceed? Thanks a lot!

I had similar issues but the following worked for me.
See the link to change default mysql permission
How to allow remote connection to mysql
Now change your db_server value in the sql connection file from
localhost to 127.0.0.1
In your case the you need to edit the file ../newcon.php it seems.

Related

Save SQL data to PHP file

I've faced a problem that I can't solve. Thing I want to do, to "save" all output SQL data to file (which should renew at timed interval ex. 5 mins) and print the file out on the website.
This is my example script, which shows data... but it makes connection each time web is loaded.
<?php
mysql_connect($dbserver, $dblogin, $dbpass);
mysql_select_db($dbname);
mysql_query("SET NAMES 'utf8'");
$rektanrekt = mysql_query("SELECT * FROM characters WHERE (accesslevel < '1') order by pkkills desc LIMIT 10");
$i = 1;
echo '<table id="top_table"><tr id="table_title"><td></td><td> </td><td>Nick</td><td></td><td>Kills</td></tr>';
while($row = mysql_fetch_array($rektanrekt))
{
echo '<tr><td id="skaiciai">' . $i . '.</td><td></td><td id="nickas"><font>';
echo $row["char_name"];
echo '</font></td><td> </td><td id="kills"><font>';
echo $row["pkkills"];
echo '</font></td></tr>';
$i++;
}
echo '</table>';
?>
And it does the job done -> http://prntscr.com/a3hpmx
But is it possible to make "backup" of this file, and show it if SQL is offline ... or even better - if SQL is ON update the file each time interval, if SQL is OFF just show latest one?
Saving output data to file:
The simplest way is to output the results in a text file using code similar to the following:
$timeStamp = time();
$pathName = "/gameLog/".$timeStamp.".txt";
$myFile = fopen($pathName, "w");
//+++++++++++++++++++++++++++++++++++
/*here you place your previous code, and inside the while
loop you use the fwrite() function to include the information
you want to save. For example:
fwrite($myFile, ($info."\n"));
where $info is the data you want to include in the file, and
"\n" is the line break.
*/
//+++++++++++++++++++++++++++++++++++
fclose($myFile);
Note: I used $timeStamp = time(); as the name of the file you are saving with the information you wanted because it will consistently generate a new value, hence you won't be overwriting your log files. Also it can help track at what time this log was saved. You could make this cleaner of course.
Doing this in intervals:
As jeroen mentioned, a cron job is probably your best solution to doing so. If you are using CPanel (linux), when you go to the CPanel homepage of your webhosting account (I am assuming your have an account with godaddy or another provider), there should be an option called "Cron Jobs" or something similar. What a Cron Job does is that it is a "Scheduled Event" that is told to execute some file in an interval you specify (you also specify the directory of your file). I found an example on youtube for you, however the video is a bit out of date, though the process should be similar:
https://www.youtube.com/watch?v=bmBjg1nD5yA
Edited: I noticed you are working on L2Aria, if you need any help, let me know! :)

CakePHP MYSQL issue reading the recent updated row

Guys I am using CakePHP and having an issue related to fetching the recent updated flag I set in the DB.
Here is the code
$this->loadModel('Setting');
$s=$this->Setting->find('first');
if($s['Setting']['inprogress']==1)
{
echo "still working...";
exit;
}
$s['Setting']['inprogress']=1;
$this->Setting->Save($s);
//// Some code that is using db table and process data for like 30-40 seconds
$s['Setting']['inprogress']=0;
$this->Setting->Save($s);
exit;
This code is run by the cron job and the check is to make sure the next cron job doesn't touch the data before the first one finishes. But apparently the cron jobs are running in parallel as they don't getting the inprogress=1 at all.
However, If I check the record manually using PHPMyAdmin the inprogress flag goes 1 immediately but somehow it won't be available for the next http call.
Any idea?
Why don't you just use saveField?
So, instead of
$s['Setting']['inprogress']=1;
$this->Setting->Save($s);
you can have
$this->Setting->saveField('inprogress', 1);
or better, to be sure, in case other finds are done on the Setting model between your saved, you can do
$id = $s['Setting']['id'];
$this->Setting->id = $id;
$this->Setting->saveField('inprogress', 1);

Prevent PHP from sending multiple emails when running parallel instances

This is more of a logic question than language question, though the approach might vary depending on the language. In this instance I'm using Actionscript and PHP.
I have a flash graphic that is getting data stored in a mysql database served from a PHP script. This part is working fine. It cycles through database entries every time it is fired.
The graphic is not on a website, but is being used at 5 locations, set to load and run at regular intervals (all 5 locations fire at the same time, or at least within <500ms of each-other). This is real-time info, so time is of the essence, currently the script loads and parses at all 5 locations between 30ms-300ms (depending on the distance from the server)
I was originally having a pagination problem, where each of the 5 locations would pull a different database entry since i was moving to the next entry every time the script runs. I solved this by setting the script to only move to the next entry after a certain amount of time passed, solving the problem.
However, I also need the script to send an email every time it displays a new entry, I only want it to send one email. I've attempted to solve this by adding a "has been emailed" boolean to the database. But, since all the scripts run at the same time, this rarely works (it does sometimes). Most of the time I get 5 emails sent. The timeliness of sending this email doesn't have to be as fast as the graphic gets info from the script, 5-10 second delay is fine.
I've been trying to come up with a solution for this. Currently I'm thinking of spawning a python script through PHP, that has a random delay (between 2 and 5 seconds) hopefully alleviating the problem. However, I'm not quite sure how to run exec() command from php without the script waiting for the command to finish. Or, is there a better way to accomplish this?
UPDATE: here is my current logic (relevant code only):
//get the top "unread" information from the database
$query="SELECT * FROM database WHERE Read = '0' ORDER BY Entry ASC LIMIT 1";
//DATA
$emailed = $row["emailed"];
$Entry = $row["databaseEntryID"];
if($emailed == 0)
{
**CODE TO SEND EMAIL**
$EmailSent="UPDATE database SET emailed = '1' WHERE databaseEntryID = '$Entry'";
$mysqli->query($EmailSent);
}
Thanks!
You need to use some kind of locking. E.g. database locking
function send_email_sync($message)
{
sql_query("UPDATE email_table SET email_sent=1 WHERE email_sent=0");
$result = FALSE;
if(number_of_affacted_rows() == 1) {
send_email_now($message);
$result = TRUE;
}
return $result;
}
The functions sql_query and number_of_affected_rows need to be adapted to your particular database.
Old answer:
Use file-based locking: (only works if the script only runs on a single server)
function send_email_sync($message)
{
$fd = fopen(__FILE__, "r");
if(!$fd) {
die("something bad happened in ".__FILE__.":".__LINE__);
}
$result = FALSE;
if(flock($fd, LOCK_EX | LOCK_NB)) {
if(!email_has_already_been_sent()) {
actually_send_email($message);
mark_email_as_sent();
$result = TRUE; //email has been sent
}
flock($fd, LOCK_UN);
}
fclose($fd);
return $result;
}
You will need to lock the row in your database by using a transaction.
psuedo code:
Start transaction
select row .. for update
update row
commit
if (mysqli_affected_rows ( $connection )) >1
send_email();

PHP MySQL Negative Value (Balance) Issue

I am developing a desktop software where it charge user per execution the main action. For example say it will charge user 0.1$ for per PDF print.
and my software provide multithreading. .
so, if it run single thread it works fine :)
but the problem is if user run multiple thread at one (say 10/20 threads)
it (php) also continues user to allow the server/execution even balance get below zero..
though my php script check whether balance is positive ..
but after user run multiple threads balance become like -5.95$ or -25.75$ etc
and that is a big security/financial issue..
here is the code I am using:
<?php
$strSQL = "Select * from users where Email = '$strUser'";
$return = mysql_query($strSQL, $strDBConn);
$strDBData = mysql_fetch_array($return, MYSQL_ASSOC);
//checking balance
$strBalance = $strDBData['Balance'];
if($strBalance < 0)
{
// if balance 0 then exit so, my software/thread will not process further
mysql_close($strDBConn);
exit('Balance Exceed');
}
//rest of the codes that realted to service executaion
// code that substract the balnce
$dblCost = 0.25;
$strSQL = "Update users set Balance = Balance - '$dblCost' where Email = '$strUser'";
$return = mysql_query($strSQL, $strDBConn);
//rest finising codes
?>
any help/suggestion would be highly appreciated..
thanks in advance.
best regards
I think, this is a quite similar question:
What is equivalent of the C# lock statement in PHP?
First, try to switch away from the old "mysql" to somethin new, maybe some PDO like DB access ;).
Then, for getting around with multi-thread in php, it can be a good idea, to write a file for every userid (!) and lock this file, when there's a request. When file is locked in another thread, wait for x seconds for the file to be unlocked by the locker-thread. If it is not unlocked within time, something went wrong. When in locked-thread all went good, unlock the file after every operation needed.
Theoraticaly you will be good with then till there's a multi-thread soloution in PHP ;)

How to run a code after a specified time?

I have a big problem:
A user logs in, and the session opens.
After that he clicks a button (in a form) which action is "example.php".
This example.php should increase one record in MySQL database by 1.
How to write this "example.php"?
Please help.
EDIT:
Sorry, I haven't asked what i was supposed to ask.
Main problem:
After a user clicks a button, the example.php script should execute after a specified time, for example, a 600 sec.
The other problem is that the user can click the button and log out, and despite that, the example.php should execute 600 sec later.
EDIT (18:48):
OK, I've read all your suggestions, but dont't have an idea how to make all of this things work together.
I made a form.php, with input type="submit" and action="example.php".
I want to:
1. start a javascript timer;
2. increase a value in database after a time, specified earlier in a variable.
Please, if it is possible, give me an example, how to do this.
In example.php execute SQL:
UPDATE table SET field = field + 1;
Do you need more info to do that ?
EDIT:
I think that there is no other way like jobs mechanism. When user calls example.php, you add to the database new job with a current timestamp + 600 seconds.
Parallel there should be running some job executor that will gather from database all jobs that have timestamp set to timestamp <= NOW().
If it will some records, call specified piece of code and remove/mark as done that jobs.
You may delay the execution of code using sleep
Example:
<?php
echo 'Script Start: '.date('h:i:s') . '<br>';
sleep(5); // delay in seconds (here 5)
echo 'Script Ende: '.date('h:i:s') . '<br>';
?>
I do not know if what you are trying to do makes perfect sense, but your exampl.php would look something like:
<?php
sleep(600); // delay in seconds
// the code to be executed delayed here
?>
There are several ways you could go about doing this...
As mentioned there is the sleep method.
You could have a job - i.e. Add something to a jobs list and have a cronjob check it every so often to see if it is due.
You could use a javascript timer to execute after x number of seconds.
<?php
if( isset($_POST['submit_button']) ) {
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
$sql = 'UPDATE table SET counter_column = counter_column + 1'; // WHERE table_name_id =' . intval($id);
mysql_query($sql, $link);
}
?>
This example.php will only update the value if the submit_button is clicked on and not if you just type in the URL example.php

Categories