249 votes

Des appels PHP asynchrones?

Existe-t-il un moyen en PHP pour faire des appels HTTP asynchrones? Je ne me soucie pas de la réponse, je veux juste faire quelque chose comme file_get_contents() , mais n'attends pas que la requête se termine avant d'exécuter le reste de mon code. Cela serait super utile pour déclencher des "événements" d'une sorte dans mon application, ou déclencher de longs processus.

Des idées?

43voto

UltimateBrent Points 6167

La réponse que j'avais précédemment acceptée n'a pas fonctionné. Il attendait toujours des réponses. Cela fonctionne bien, pris de Comment puis-je faire une requête GET asynchrone en PHP?

 function post_without_wait($url, $params)
{
    foreach ($params as $key => &$val) {
      if (is_array($val)) $val = implode(',', $val);
        $post_params[] = $key.'='.urlencode($val);
    }
    $post_string = implode('&', $post_params);

    $parts=parse_url($url);

    $fp = fsockopen($parts['host'],
        isset($parts['port'])?$parts['port']:80,
        $errno, $errstr, 30);

    $out = "POST ".$parts['path']." HTTP/1.1\r\n";
    $out.= "Host: ".$parts['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";
    if (isset($post_string)) $out.= $post_string;

    fwrite($fp, $out);
    fclose($fp);
}
 

30voto

Christian Davén Points 4527

Si vous le contrôle de la cible que vous voulez l'appeler de manière asynchrone (par exemple, votre propre "longtask.php"), vous pouvez fermer la connexion à partir de cette fin, et les deux scripts s'exécutent en parallèle. Il fonctionne comme ceci:

  1. quick.php ouvre longtask.php via cURL (pas de magie ici)
  2. longtask.php ferme la connexion et continue (magique!)
  3. cURL renvoie à quick.php lorsque la connexion est fermée
  4. Les deux tâches en parallèle

J'ai essayé, et ça marche très bien. Mais quick.php ne savez rien à propos de la façon dont longtask.php est en train de faire, sauf si vous créez des moyens de communication entre les processus.

Essayez ce code dans longtask.php avant de faire quoi que ce soit d'autre. Il va fermer la connexion, mais continuent à exécuter (et réprimer toute la puissance de sortie):

while(ob_get_level()) ob_end_clean();
header('Connection: close');
ignore_user_abort();
ob_start();
echo('Connection Closed');
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();

Le code est copié à partir du PHP, du manuel de l'utilisateur contribué notes et quelque peu améliorée.

25voto

Bruce Aldridge Points 1498

cela a besoin de php5, je l'ai volé sur docs.php.net et j'ai édité la fin.

Je l'utilise pour surveiller quand une erreur se produit sur un site client, il m'envoie des données sans bloquer la sortie

 function do_post_request($url, $data, $optional_headers = null,$getresponse = false) {
      $params = array('http' => array(
                   'method' => 'POST',
                   'content' => $data
                ));
      if ($optional_headers !== null) {
         $params['http']['header'] = $optional_headers;
      }
      $ctx = stream_context_create($params);
      $fp = @fopen($url, 'rb', false, $ctx);
      if (!$fp) {
        return false;
      }
      if ($getresponse){
        $response = stream_get_contents($fp);
        return $response;
      }
    return true;
}
 

24voto

Internet Friend Points 811

Vous pouvez le faire par la ruse d'utiliser exec() pour appeler quelque chose qui peut faire des requêtes HTTP, comme wget, mais vous devez en direct tous les résultats du programme à quelque part, comme un dossier ou /dev/null, sinon le processus PHP va attendre pour cette sortie.

Si vous voulez séparer le processus de apache fil entièrement, essayez quelque chose comme (je ne suis pas sûr à ce sujet, mais j'espère que vous voyez l'idée):

exec('bash -c "wget -O (url goes here) > /dev/null 2>&1 &"');

Ce n'est pas une belle entreprise, et vous voudrez probablement quelque chose comme une tâche cron en invoquant un battement de coeur script qui les sondages d'une base de données en cas de file d'attente pour l'utilisation réelle des événements asynchrones.

17voto

cruizer Points 4821

Wez Furlong a démontré comment le faire:

http://netevil.org/blog/2005/may/guru-multiplexing

il a fourni des implémentations compatibles PHP4 et PHP5.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X