I'm using DHTMLX Scheduler on the front end and DHTMLX Connector on the backend as part of my radio automation app. Every time a user edits the calendar, an AJAX call is made to a file that looks like this:
require_once("dhtmlxScheduler_v4/connector/scheduler_connector.php");
require_once('QDRAconf.php');
$res = mysql_connect($QDRAconf['mysqlHost'], $QDRAconf['mysqlUser'], $QDRAconf['mysqlPass']);
mysql_select_db($QDRAconf['mysqlDb']);
// init the schedulerconnector
$conn = new SchedulerConnector($res);
// render the table
$conn->render_table("events","id","start_date,end_date,text");
This file is my "shim" that hooks up the fronted to the back end. I want to run another PHP script that writes the changes to my crontab, but it needs to happen after the DHTMLX library has updated the database. Trouble is, the DHTMLX library will automatically exit whenever it thinks it's done: sometimes it might not get past the first require_once('...') line so I can't just put require_once('cronwriter.php'); at the last line of the script.
My solution to this was to create a class with a destructor that updates the crontab with the latest changes. Since the php manual states that destructors will still be run if the exit() or die() function is called, I added a dummy class with a destructor that runs cronwriter.php script: (I added this to the beginning of the file.)
class ExitCatcher
{
function __destruct()
{
require_once('cronwriter.php');
}
}
//init the class
$ExitCatcher = new ExitCatcher;
For some reason, it doesn't work.
register_shutdown_function may offer a quick solution; but, you might save yourself some future trouble by inspecting the cause of that library's sporadic process haltings.
A good place to start might be...
your browser's JS console for JS errors
your JS console's network tab for AJAX errors
your server's error logs for PHP errors
Related
I am using CodeIgniter framework with RabbitMQ for doing time consuming activities such as sending emails, generating PDFs.
Whenever I change a code in the PHP files, say library or controller, until I restart the Apache, the old code is being executed by the RabbitMQ. How to resolve this?
The function in Controller,
public function receive()
{
$this->db->reconnect();
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare('generate_pdf', false, false, false, false);
echo "[*] Started listening to connections... To exit press CTRL+C\n";
$generate_pdf = function ($data)
{
$this->generatepdf->generate($data); // Generatepdf.php library -> generate() function
};
$channel->basic_qos(null, 1, null);
$channel->basic_consume('generate_pdf', '', false, true, false, false, $generate_pdf)
while ($channel->is_consuming())
{
$channel->wait();
}
}
Starting this in termimal,
php index.php Controllerfile.php receive
This works fine as expected. So when a job is pushed to the queue, the generate() function in the library file Generatepdf.php is called and the execution is done.
However, if I modify the generate() function thru an editor or I re-upload the file with changes, the changes does not reflect until I restart the Apache server.
Function definition before changes:
public function generate()
{
echo "Hello the data is 250";
}
Output: Hello the data is 250
Function definition after the change:
public function generate()
{
echo "Hello the data is 251";
}
Output before restarting Apache: Hello the data is 250
Output after restarting Apache: Hello the data is 251
Why does this happen? How can I made the execution to refresh the changes in the file?
The code you've shown contains this loop:
while ($channel->is_consuming())
{
$channel->wait();
}
What that's saying is "unless the connection to RabbitMQ breaks, wait for a new message, process it, and then wait again, forever". In other words, it's an infinite loop, and the PHP process running it won't exit unless you kill it.
Contrary to some descriptions I've seen, PHP is a compiled language, not an interpreted one: when a PHP process is asked to load a file of PHP code, it looks at it once, compiles it to a machine-friendly representation (called "op codes") and then doesn't need to look at it again to execute the code in it any number of times. So when you edit the file, a process that's already running won't notice, and won't compile your new code.
If you want to have the new code loaded, you need to exit the infinite loop, so the process ends, and then start a new one, which will compile your new code. For instance, you can have a check in the loop for a particular file, measure the time it's been running, or listen for a special message telling it to exit. You can then use something like "supervisord" to ensure the script is re-run whenever it exits, or just have a "cron" task to regularly start a new copy.
As one extra point: there is a feature of PHP called "OpCache" which reuses the compiled version of files even between processes, for better performance. By default, it will look at the timestamp of the file to decide whether to recompile it, so will "notice" if you edit a file, but that check can be turned off, for maximum performance. If that was the problem, you'd see this with all PHP code, though, not just your RabbitMQ loop.
How would I possible use or create a runtime environment in php that will communicate constantly with the backend of HTML XML and JS XML? Basicly, how would I make a php script not die but continually running and respond to the HTML XML events requesting the php script, example <form method="post"> is html and is using XML to send the script serverside (to php or other languages) then it refreshes to get a return statement. Normally php would die within' less then a second, but how would I make a runtime which will continually gonna stay open?
Note: Using a runtime is not the same as loading the script in with the javascript interval function!
Using the javascript interval and JQuery/AJAX to simply call the php script makes no different and would not be considered as a correct answer OR be correct at all, cause the interval function and the JQuery load function is calling the file each requested ms, so using those functions would not solve the php runtime mysterium!
This will also mean if there is a way for php to run at a html runtime and create the php runtime to work together (multitasking) then php could be a whole new type of php.. I know that didn't make any sense, but it means you can extend php so much to literally create a timer event to extend multitasking from the php side (class timer {public function start(){ ... } public function stop(){ ... } public function interval($interval /* As Integer */){ ... } public function ON_TICK /* The event running the multitasking from php side */(){ timer::event('on_tick'); } private function event($event){ if($event==='on_tick'){ timer::executeEvent()}}; private function executeEvent($script){/*Script can include if statements and db upload, and conditions, etc*/ /* This will run the script that was called from the function, example $timer1 = new timer;$timer1->interval(1/*In ms*/);$timer1->script("if(1=1){$timer1->stop();}") */}})
I have PHP application, that runs about 2-3 minutes before it return something to browser (some database processing stuff).
I want to know, if I can change php file with it while script is running. I assume, there is a buffer in Apache/PHP.
I have situation like this:
// This is index.php
include "DatabaseController.php"; // class inside, I create instance at start
include "ImagesController.php"; // class inside, I create instance at start
include "helpers.php"; // there are just functions, no classes
$db = new Database();
$img = new Images();
// for loop doing job here (2-3 minutes)
// end
What will happen, when I replace "DatabaseController.php" file while script is running?
I tried to test it, and it looks like "job part" is still using old version of DatabaseController, when I replace.
But... what will happen, when I replace "helpers.php" file? It contains only functions, without classes that may be instantiated at the beginning of script.
How this buffering works in general?
Its not really being buffered. You should read up on Compilers. In summary, the code you write will first need to be compiled before it can be executed. Changes you make to the source after it has been compiled will not take effect until the next request when it will be recompiled again.
I have a JavaScript functions which calls a PHP function through AJAX.
The PHP function has a set_time_limit(0) for its purposes.
Is there any way to stop that function when I want, for example with an HTML button event?
I want to explain better the situation:
I have a php file which uses a stream_copy_to_stream($src, $dest) php function to retrieve a stream in my local network. The function has to work until I want: I can stop it at the end of the stream or when I want. So I can use a button to start and a button to stop. The problem is the new instance created by the ajax call, in fact I can't work on it because it is not the function that is recording but it is another instance. I tried MireSVK's suggest but it doesn't worked!
Depending on the function. If it is a while loop checking for certain condition every time, then you could add a condition that is modifiable from outside the script (e.g. make it check for a file, and create / delete that file as required)
It looks like a bad idea, however. Why you want to do it?
var running = true;
function doSomething(){
//do something........
}
setInterval(function(){if(running){doSomething()}},2000); ///this runs do something every 2 seconds
on button click simply set running = false;
Your code looks like:
set_time_limit(0);
while(true==true){//infinite loop
doSomething(); //your code
}
Let's upgrade it
set_time_limit(0);
session_start();
$_SESSION['do_a_loop'] = true;
function should_i_stop_loop(){
#session_start();
if( $_SESSION['do_a_loop'] == false ) {
//let's stop a loop
exit();
}
session_write_close();
}
while(true==true){
doSomething();
should_i_stop_loop(); //your new function
}
Create new file stopit.php
session_start();
$_SESSION['do_a_loop'] = false;
All you have to do now is create a request on stopit.php file (with ajax or something)
Edit code according to your needs, this is point. One of many solutions.
Sorry for my English
Sadly this isn't possible (sort of).
Each time you make an AJAX call to a PHP script the script spawns a new instance of itself. Thus anything you send to it will be sent to a new operation, not the operation you had previously started.
There are a number of workarounds.
Use readystate 3 in AJAX to create a non closing connection to the PHP script, however that isn't supported cross browser and probably won't work in IE (not sure about IE 10).
Look into socket programming in PHP, which allows you to create a script with one instance that you can connect to multiple times.
Have PHP check a third party. I.E have one script running in a loop checking a file or a database, then connect to another script to modify that file or database. The original script can be remotely controlled by what you write to the file/database.
Try another programming language (this is a silly option, but I'm a fan of node). Node.js does this sort of thing very very easily.
I am trying to call a function after the page has been sent to the browser, but I haven't found a way to do so.
I have tried both register_shutdown_function and __destruct but it does not work.
This is the structure I have:
register_shutdown_function('MyClass::Save');
MyClass::Initialize();
CreateAllOutput();
MyClass::Save has a sleep(20) inside.
The shutdown function gets called after the CreateAllOutput(), but the truth is that the loading bar on the browser only finishes after the Save function has been executed, waiting 20 seconds... I tried the same using a non static class and __destruct having a sleep(20) inside, and the same happens.
Is there a way of getting the function to only be executed after the output has all been sent to the browser?
Thank you in advance.
Generally: no. There is no possibility except to flush all output and then call it, but the loading bar in the browser won't finish either.
The only thing I can think of is putting an iFrame into the page to call a PHP file with the save function. Or you could make an Ajax call.
A third possibility would be to call exec() (Documentation). After making a php file executeable you can run it with that method. As mentioned in the documentation:
If a program is started with this
function, in order for it to continue
running in the background, the output
of the program must be redirected to a
file or another output stream. Failing
to do so will cause PHP to hang until
the execution of the program ends.