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.
Related
I've never done this before, so I need some input.
Code (in general):
$cofig = Configure::read('config');
if ($config['stuff'] == 1){
$this->Session->setFlash('it is already done this month');
$this->redirect('/to/some/where');
}
elseif ($config['stuff'] == 2){
$this->Session->setFlash('it is already running');
$this->redirect('/to/some/where');
}
else {
SomeComponent::SomeFunction(); //this I need to launch in background while user continues further
$this->Session->setFlash('you have launched it');
$this->redirect('/to/some/where');
}
"SomeComponent" contains several functions. I need to launch a specific function "SomeFunction()" in the bacground while user continues further.
Function "SomeComponent::SomeFunction()" generates bunch of pdfs, interacts with database and uses Cakephp specific methods'n'crap to do all that. Users receive output via database, so I don't need to retrieve it form the function itself.
So i'm not clear which method can do that, which best to use and what are/may be drawbacks of each one (security issues in particular).
I hope I explained everything in a understandable way. If you have read this far - thanks.
Is that process "SomeComponent::SomeFunction()" taking too long? If the answer is yes then I would wrap that function in a shell and if you want to take it to the next level I would use an Observer in order to dispatch that background process.
Here is an introduction to Event Handling in CakePHP.
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.
Hey i've seen people recommend each of them, One calimed register_shutdown_function to be better but without explination.
I'm talking about which is better to send a response back and still preform other tasks.
I Wondered what really is the better method and why.
EDIT:
In the register_shutdown_function documentation, someone published the following method:
<?php
function endOutput($endMessage){
ignore_user_abort(true);
set_time_limit(0);
header("Connection: close");
header("Content-Length: ".strlen($endMessage));
echo $endMessage;
echo str_repeat("\r\n", 10); // just to be sure
flush();
}
// Must be called before any output
endOutput("thank you for visiting, have a nice day');
sleep(100);
mail("you#yourmail.com", "ping", "im here");
?>
Could it be better then any of the functions i stated?
ignore_user_abort() tells PHP/Apache to not terminate execution when the user disconnects. register_shutdown_function simply allows you to do some cleanup while PHP is in the process of shutting down.
register_shut_down is only useful if you need to do some cleanup that PHP's normal shutdown routines wouldn't take care, e.g. removing a manually created lock file, flipping a bit in a DB record somewhere, etc...
In older versions of PHP (<4.1.0 under Apache), register_shutdown_function() would ensure that the connection was closed before your shutdown functions ran. This is no longer the case. The endOutput() function in your edit should indeed do what you want, provided you don't have any output buffers open. Though, it does set the script to be able to run forever if necessary, which could be annoying if it goes into an infinite loop (especially during debugging). You might want to change set_time_limit() to use a value that actually reflects how many seconds the script should take.
It's probably best to avoid register_shutdown_function() if you don't need it, since it has some other odd behavior (such as not being able to add a second layer of shutdown functions to run if the first shutdown function calls exit()).
How could I make sure that the startProcess(); function is being called, but without halting the execution for myFunction(). I'll guess that there's a way to call a function and prevent it from returning it's value to thereby accomplishing this?
Pseudo-code:
function myFunction() {
startProcess();
return $something;
}
function startProcess() {
sleep(5);
// Do stuff that user doesn't should have to wait for.
}
You can't do it. There are some a few functions in PHP that allow async I/O, but nothing like the concurrency you require.
The reason for existing no language support is that PHP is designed to execute short-lived scripts, while the concurrency is managed by the HTTP daemon.
See also:
cur_mult_init
pcntl_fork (unix only)
http://wezfurlong.org/blog/2005/may/guru-multiplexing
To make a small addition to Artefecto's answer, there are some people who've attempted to recreate a sort of threads situation. You can find some information on it using google, but I doubt it'll be helpful as it's just too experimental and probably pretty unreliable.
Found one link that might be helpful for you.
http://w-shadow.com/blog/2008/05/24/improved-thread-simulation-class-for-php/
As far as I can tell from your question and tags, you want to do some background processing, meaning, essentially, multiple threads.
Unfortunately, PHP doesn't do this. There are some IO functions that are asynchronous, but in general you cannot do concurrent processing in PHP.
What is it you want startProcess() to do? There are many ways to keep the user from having to wait.
Emails are a good example: the thread that runs mail() spins until the message is accepted or rejected; you don't want a user to have to wait for that. So you queue up the task, and then process your queue on cron.
function myFunction() {
addToQueue();
return $something;
}
function addToQueue() {
// add stuff to the queue of tasks
}
function runQueue() {
// process the queue of tasks; called by cron.
}
Have you looked at Gearman for farming out this kind of background task?
I'm going to take a shot in the dark here, but does this function look like it could be a solution for your overall goal ?
http://php.net/manual/en/function.register-shutdown-function.php
If I'm generating a stream of data to send out to a browser, and the user closes the browser, can I tell within PHP that I don't need to bother generating or sending the rest of the stream? I'd like to insert something into this loop:
while (!feof($pipes[1])) {
echo fgets($pipes[1]);
}
My fallback plan is to have the browser use a JavaScript onunload to hit another PHP page to kill the process that's generating the data, but it would be cleaner if PHP could tell when I'm echoing to nowhere.
By default PHP will abort the script if the user navigates away. There are however times where you don't want this to happen so php has a config you set called ignore_user_abort.
http://php.net/manual/en/misc.configuration.php
There's also a function called register_shutdown_function() that is supposedly executed when execution halts. I've never actually used it, so I won't vouch for how well it works, but I thought I'd mention it for completeness.
I believe that script will automatically abort when loaded normally (No ajax). But if you want to implement some sort of long polling via php using xmlhttprequest I think you will have to do it with some sort of javascript because then php can't detect it. Also like to know the precise case.
These answers pointed me towards what I was looking for. The underlying process needed special attention to kill it. I needed to jump out of the loop. Thanks again, Stack Overflow.
while (!feof($pipes[1]) && !connection_aborted())
{
echo fgets($pipes[1]);
}
if (connection_aborted())
{
exec('kill -4 '.$mypid);
}