Asynchronous PHP call which runs a controller method
Based on this thread I made this for my codeigniter project. It works just fine. You can have any function processed in the background.
A controller that accepts the async calls.
class Daemon extends CI_Controller{ // Remember to disable CI's csrf-checks for this controller function index( ) { ignore_user_abort( 1 ); try { if ( strcmp( $_SERVER['REMOTE_ADDR'], $_SERVER['SERVER_ADDR'] ) != 0 && !in_array( $_SERVER['REMOTE_ADDR'], $this->config->item( 'proxy_ips' ) ) ) { log_message( "error", "Daemon called from untrusted IP-address: " . $_SERVER['REMOTE_ADDR'] ); show_404( '/daemon' ); return; } $this->load->library( 'encrypt' ); $params = unserialize( urldecode( $this->encrypt->decode( $_POST['data'] ) ) ); unset( $_POST ); $model = array_shift( $params ); $method = array_shift( $params ); $this->load->model( $model ); if ( call_user_func_array( array( $this->$model, $method ), $params ) === FALSE ) { log_message( "error", "Daemon could not call: " . $model . "::" . $method . "()" ); } } catch(Exception $e) { log_message( "error", "Daemon has error: " . $e->getMessage( ) . $e->getFile( ) . $e->getLine( ) ); } }}
And a library that does the async calls
class Daemon{ public function execute_background( /* model, method, params */ ) { $ci = &get_instance( ); // The callback URL (its ourselves) $parts = parse_url( $ci->config->item( 'base_url' ) . "/daemon" ); if ( strcmp( $parts['scheme'], 'https' ) == 0 ) { $port = 443; $host = "ssl://" . $parts['host']; } else { $port = 80; $host = $parts['host']; } if ( ( $fp = fsockopen( $host, isset( $parts['port'] ) ? $parts['port'] : $port, $errno, $errstr, 30 ) ) === FALSE ) { throw new Exception( "Internal server error: background process could not be started" ); } $ci->load->library( 'encrypt' ); $post_string = "data=" . urlencode( $ci->encrypt->encode( serialize( func_get_args( ) ) ) ); $out = "POST " . $parts['path'] . " HTTP/1.1\r\n"; $out .= "Host: " . $host . "\r\n"; $out .= "Content-Type: application/x-www-form-urlencoded\r\n"; $out .= "Content-Length: " . strlen( $post_string ) . "\r\n"; $out .= "Connection: Close\r\n\r\n"; $out .= $post_string; fwrite( $fp, $out ); fclose( $fp ); }}
This method can be called to process any model::method() in the 'background'. It uses variable arguments.
$this->load->library('daemon');$this->daemon->execute_background( 'model', 'method', $arg1, $arg2, ... );
You can write in socket:
$fp = fsockopen($_SERVER['HTTP_HOST'], 80, $errno, $errstr, 30);$data = http_build_query($params, '', '&'); //$params - array with POST datafwrite($fp, "POST " . ('/controller/action') . " HTTP/1.1\r\n");fwrite($fp, "Host: ".$_SERVER['HTTP_HOST']."\r\n");fwrite($fp, "Content-Type: application/x-www-form-urlencoded\r\n");fwrite($fp, "Content-Length: " . strlen($data) . "\r\n");fwrite($fp, "Connection: Close\r\n\r\n");fwrite($fp, $data);fclose($fp);