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.
Related
I have 2 functions, let's call them login and doSomething and currently, I implemented them this way,
$member=$this->login();
$this->doSomething($member);
//show welcome page
When a user logs in, I want to do some stuff but it takes around 20 seconds or more to complete. Is there any ways where after login() is run, it will show the welcome page immediately while the method doSomething() is being executed separately. The method doSomething() doesn't return any values thus does not affect the welcome page.
Please try the following.
ob_start();
$member = $this->login();
ob_end_flush();
ob_flush();
flush();
$this->doSomething($member);
If you do not want to print anything after login, you can use:
ob_start();
$this->doSomething($member);
ob_end_clean();
Also using Ajax from the front site's login page(after loading), you can start processing
$this->doSomething($member);
in another ajax call in the back end silently.
There are other ways for achieving threading, pseudo threading like behaviour.
But these are the easiest one for your scenerio :)
You can check WorkerThreads also.
Their implementation example documentation are available in the net.
If you really, really want to run it in parallel, then you need to run it in a sperate process. That means you are running it in different scope, so while the code you invoke might contain $this->doSomething($member), that "this" won't be this "this".
Assuming that is possible, then your question is a duplicate of this one (but beware - the accepted answer is not good). Note that you will run in blocking problems if both parts of the script depend on a session.
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
I have a PHP script that I need to execute from inside another PHP webpage. However for the second one to run properly the first needs to have fully completed. Essentially I need the first page to spawn a new process/thread for the second script which will wait 1 second before starting.
Doing an include causes blocking which prevents it from working and I can't get it to start using exec
Edit:
Should have clarified. These pages have no output and are not interfaced with through a web interface. All pages are called by POST requests from another server.
Edit 2:
Solution: make server requesting the page send a request directly to the second page 1 second after the first returns.
proc_open is the correct choice, as #ChristopherMorrissey pointed out. I want to elaborate a little here, as there are some caveats to using proc_open that aren't entirely obviously.
In the first code example # http://php.net/manual/en/function.proc-open.php, it shows the overall usage and I will reference that.
The first caveat is with the pipes. The pipes are file streams in PHP that link to STDIN, STDOUT and STDERR of the child process. In the example, pipe index 0 represents a file stream from the parent PHP processes perspective. If the parent process writes to this stream, it will appear as STDIN input to the child process.
On POSIX compliant OSes, STDIN to a process needs to close before the process can terminate. Its very important to call fclose on the pipe from the parent, or your child process will be stuck. That is done with this line in the example:
fclose($pipes[0]);
The other caveat is on checking the exit code of the child process. Checking the exit code is the best way to determine if the child process has exited correctly, or if it erred out. At the very least, you will need to just know when the child process has completed. Checking this and the exit code are both done with http://www.php.net/manual/en/function.proc-get-status.php
If you want to ensure the process exits correctly, you will need to look at the exitcode field returned in the array from proc_get_status. Keep in mind this exit code will only return a valid value once. All other times it will return -1. So, the one time it returns > -1, this is your actual exit code. So, the first time running == false, check exitcode.
I hope this helps.
One option would be to redirect the page after the first script has finished.
You could do it this way:
//first script here
sleep(1); //wait one second
echo "<meta http-equiv=\"refresh\" content=\"0;URL='yoursecondscript.php'\" />"; //redirect
or even:
//first script here
//redirect after one sec
echo "<meta http-equiv=\"refresh\" content=\"1;URL='http://thetudors.example.com/'\" />";
You might be able to write a header going to the second page when you want it, then putting a header back to the original page at the end of the second page. Though there are many reasons this fix wouldn't work, like the PHP code being required to be in the HTML.
Headers reference
So something like: header(Location: seconddocument.php)
Or maybe you could put the PHP to execute in a function, and then call it from the original PHP document. I can't be exactly sure of your requirements here, but those would be my two best answers.
I am using Codeigniter for a project and i usually call a series of models (let's say controllerA -> modelA -> modelB -> modelC) for some work. I want the php to stop executing when it reaches some exception where i invoke the exit() command. Now, if the command exit() is invoked in modelB, will it stop execution of only the script of modelB and continue executing rest of the modelA? Or will it stop the entire execution flow.
I really don't know how to put this question here. The question looks quite messy. Please let me know should i need to revise the question itself.
Yes, exit stops all script execution immediately, regardless where you call it.
The opposite is return which only stops execution of the current function (or current file when used at global level in an included file)
Read more here: https://stackoverflow.com/a/9853554/43959
Wherever you call the exit() function, all code will stop executing. This includes the other files because codeigniter just 'requires' them.
It stops the execution from that line.
I'm not sure if what you want, but maybe you can use exceptions to control PHP code execution.
http://es.php.net/manual/en/class.exception.php
Regards!
Like someone mentions above you should return from a function, or If your in a loop you could use continue or break
I'm creating a app that requires me to run a second php script while the first script is still running.
I'm new to php programing so I'm sure there's a simple function I can use that I'm just not aware of.
Looking forward to any help...
Shane
Since you are new to PHP I'm guessing you're looking for the include/require (and include_once/require_once) language constructs which will execute another PHP script as if it is part of the current script.
Otherwise if you want it to run as a separate process look into exec, shell_exec, or backticks. If you need the other PHP script to run as a background process make sure to redirect stdout somewhere (a file or maybe /dev/null if you don't need it) so that your currently executing script doesn't have to wait for it to finish to continue executing.
This will actually require us to use some Javascript for an ajax call to execute our PHP and return it's data.
I prefer Jquery, which will look similar to this:
function callPHP(){
$.post('./filetocall.php', {variableid: 'id'}, function (response) {
$("#div_for_return_data").val(response);
});
}
filetocall.php can look like anything. It's output will populate the #div_for_return_data
eg:
<?php echo $_GET['variableid']; ?>
Then just call the Jquery function from anywhere.