PHP → Как из php скрипта асинхронно выполнить другой скрипт (т.е. не дожидаясь его окончания)

25.01.2011

Например есть скрипт a.php, в котором нужно вызвать тяжеловесный скрипт b.php и не дожидаясь его окончания продолжить работу. Одно из решений это сокеты:

// a.php

function exec_script($url, $params = array())
{
    $parts = parse_url($url);
	
    if (!$fp = fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80))
    {
        return false;
    }
	
    $data = http_build_query($params, '', '&');

    fwrite($fp, "POST " . (!empty($parts['path']) ? $parts['path'] : '/') . " HTTP/1.1\r\n");
    fwrite($fp, "Host: " . $parts['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);

    return true;
}

exec_script('http://example.com/b.php', array('foo' => 'bar'));

В примере, в скрипте b.php будет доступна переменная $_POST['foo'] со значением bar.

Похожие записи

Комментарии

Александр
07.08.2011, 19:03

Если в параметрах передать массив из нескольких элементов, то на странице b.php будет доступна только переменная из первого элемента массива.
Т.е. так
exec_script('http://mysite.com/b.php', array('hello' => 'world', 'hello2' => 'world2'));
будет доступна только переменная $_POST['hello'], а $_POST['hello2'] нет.

будут доступны обе переменные. проверено неоднократно

Александр
07.08.2011, 19:44

Почему-то по умолчанию http_build_query в качестве разделителя ставит &
Поэтому и имя переменной было своеобразным, что-то типа $_POST['amp;hello2']
Принудительно выставил разделителем & и все стало хорошо
$data = http_build_query($params, '', '&')

Спасибо за скрипт, очень помог.

Гость
30.12.2011, 10:08

На действительно тяжеловесный скрипт всё-равно вылетает по тайм-ауту. Поэтому в этом с лучае всё-таки придётся использовать shell_exec()

Гость
15.05.2012, 14:54

добрый день,
добавил этот скрипт в views php , встретился с такой ошибкой
Fatal error: Cannot redeclare exec_script() (previously declared in /sites/all/modules/views_php/plugins/views/views_php_handler_field.inc(223) : runtime-created function:2) in /sites/all/modules/views_php/plugins/views/views_php_handler_field.inc(223) : runtime-created function on line 2

как с этим бороться.. или подскажите как запустить другой скрипт из views
Спасибо.

Гость
15.05.2012, 15:06

переименовать в любое имя ?
переименовал, все то же
Fatal error: Cannot redeclare myfunc() (previously declared in ...

переименовать в любое доступное имя

Гость
15.05.2012, 15:26

переименовал в funcxandex , такой занятой не должно быть
и сново та же ошибка
Fatal error: Cannot redeclare funcxandex() (previously declared..

значит пытаетесь создать функцию в цикле. так делать нельзя

Скрипт работает отлично, долго искал решения, спасибо! Но...
Если требуется авторизация, работать перестает :(
добавление
fwrite($fp, "Authorization: Basic ".base64_encode("user:pass")."\r\n");
не помогает.
Может подскажешь что делать? Спасибо!

Гость
11.12.2012, 15:55

to Deiww
А если сессии использовать?

А чем они помогут? И как это реализовать...

Евгений Диникин
14.03.2014, 04:07

Поставил пример скрипта на сервер - не работает. Поставил на другой сервер - работает. На том сервере - где не работает в логах nginx нашел вот это:

123.465.798.123 - - [14/Mar/2014:03:53:38 +0400] "GET <strong>/a.php</strong> HTTP/1.1" 200 102 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0"
321.654.654.897 - - [14/Mar/2014:03:53:38 +0400] "POST <strong>/b.php</strong> HTTP/1.1" 400 0 "-" "-"

Получается, скрипт b.php выдает ошибку 400 - Bad Request при вызове из a.php

Подскажите, в чем может быть проблема? Может конфиги сервера нужно подкрутить?
Заранее благодарен!

Дмитрий
20.04.2014, 21:20

Хороший скрипт, тока вот с GET не работает. НЕ много доработал:

заменяем строку:

fwrite($fp, "POST " . (!empty($parts['path']) ? $parts['path'] : '/') . " HTTP/1.1\r\n");

на

if(empty($parts['query']))$q="";
else $q="?".$parts['query'];
	 
fwrite($fp, "POST " . (!empty($parts['path']) ? $parts['path'].$q : '/'.$q ) . " HTTP/1.1\r\n");

зачем такие сложности ?

function freelocation($location){
if($location){
        ob_end_clean();
        header("Connection: close\r\n");
        header("Content-Encoding: none\r\n");
        ignore_user_abort(true); ob_start();
		header('location:'.$location);
        $size = ob_get_length();
        header("Content-Length: $size");
        ob_end_flush(); flush(); ob_end_clean();
 }
}

Добавить комментарий