我正在尝试在PHP中创建一种即发即弃的方法,以便我可以将数据POST
到Web服务器,而无需等待响应。我读到这可以通过使用CURL
来实现,如以下代码所示:
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
curl_exec($ch);
curl_close($ch);
但是,我认为它没有像我预期的那样工作。例如,如果我向其发送请求的 URL 有错误,则也会导致我的脚本引发错误。如果是火灾并忘记,我希望这不会发生。
谁能告诉我我是否做错了什么或提供替代建议。我在本地使用 Windows,在开发、暂存和生产环境中使用 Linux。
更新
我在这里找到了另一种解决方案:http://blog.markturansky.com/archives/205
我已经将其清理到下面的代码中:
function curl_post_async($url, $params = array())
{
// create POST string
$post_params = array();
foreach ($params as $key => &$val)
{
$post_params[] = $key . '=' . urlencode($val);
}
$post_string = implode('&', $post_params);
// get URL segments
$parts = parse_url($url);
// workout port and open socket
$port = isset($parts['port']) ? $parts['port'] : 80;
$fp = fsockopen($parts['host'], $port, $errno, $errstr, 30);
// create output string
$output = "POST " . $parts['path'] . " HTTP/1.1'r'n";
$output .= "Host: " . $parts['host'] . "'r'n";
$output .= "Content-Type: application/x-www-form-urlencoded'r'n";
$output .= "Content-Length: " . strlen($post_string) . "'r'n";
$output .= "Connection: Close'r'n'r'n";
$output .= isset($post_string) ? $post_string : '';
// send output to $url handle
fwrite($fp, $output);
fclose($fp);
}
这个似乎更适合我。
这是一个有效的解决方案吗?
是的,如果您不关心来自您正在调用的 URL 的响应,那么使用套接字是可行的方法。这是因为套接字连接可以在发送请求后直接终止而无需等待,而这正是您所追求的 - 即发即弃。
不过有两点说明:
- 它不再是 cURL 请求,因此值得重命名函数。 :)
-
绝对值得检查是否可以打开套接字以防止脚本稍后在失败时抱怨:
$fp = fsockopen($parts['host'], $port, $errno, $errstr, 30); if ( ! $fp) { return FALSE; }
值得链接到您现在使用的 fsocket() 脚本的原始源代码:
http://w-shadow.com/blog/2007/10/16/how-to-run-a-php-script-in-the-background/
这是diggersworld代码的清理版本,它还处理其他HTTP方法,然后POST,并在函数失败时抛出有意义的异常。
/**
* Send a HTTP request, but do not wait for the response
*
* @param string $method The HTTP method
* @param string $url The url (including query string)
* @param array $params Added to the URL or request body depending on method
*/
public function sendRequest(string $method, string $url, array $params = []): void
{
$parts = parse_url($url);
if ($parts === false)
throw new Exception('Unable to parse URL');
$host = $parts['host'] ?? null;
$port = $parts['port'] ?? 80;
$path = $parts['path'] ?? '/';
$query = $parts['query'] ?? '';
parse_str($query, $queryParts);
if ($host === null)
throw new Exception('Unknown host');
$connection = fsockopen($host, $port, $errno, $errstr, 30);
if ($connection === false)
throw new Exception('Unable to connect to ' . $host);
$method = strtoupper($method);
if (!in_array($method, ['POST', 'PUT', 'PATCH'], true)) {
$queryParts = $params + $queryParts;
$params = [];
}
// Build request
$request = $method . ' ' . $path;
if ($queryParts) {
$request .= '?' . http_build_query($queryParts);
}
$request .= ' HTTP/1.1' . "'r'n";
$request .= 'Host: ' . $host . "'r'n";
$body = http_build_query($params);
if ($body) {
$request .= 'Content-Type: application/x-www-form-urlencoded' . "'r'n";
$request .= 'Content-Length: ' . strlen($body) . "'r'n";
}
$request .= 'Connection: Close' . "'r'n'r'n";
$request .= $body;
// Send request to server
fwrite($connection, $request);
fclose($connection);
}