Как отправить запрос POST с помощью PHP?

566

На самом деле, я хочу прочитать содержимое, появившееся после поискового запроса, когда это будет сделано. Проблема в том, что URL-адрес принимает только методы POST, и он не принимает никаких действий с помощью метода GET...

Мне нужно прочитать все содержимое с помощью domdocument или file_get_contents(). Есть ли какой-либо метод, который позволит мне отправлять параметры с помощью метода POST, а затем читать содержимое через PHP?

Теги:
post
http
request

12 ответов

1158

Метод CURL-less с PHP5:

$url = 'http://server.com/path';
$data = array('key1' => 'value1', 'key2' => 'value2');

// use key 'http' even if you send the request to https://...
$options = array(
    'http' => array(
        'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
        'method'  => 'POST',
        'content' => http_build_query($data)
    )
);
$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */ }

var_dump($result);

См. руководство по PHP для получения дополнительной информации о методе и способах добавления заголовков, например:

  • 53
    Стоит отметить, что если вы решите использовать массив для заголовков, НЕ заканчивайте ключи или значения символом '\ r \ n'. stream_context_create () будет принимать только текст до первого '\ r \ n'
  • 8
    URL-адрес может использоваться в качестве имени файла с file_get_contents() только в том случае, если включены обертки fopen. Смотрите php.net/manual/en/…
Показать ещё 14 комментариев
84

Вы можете использовать cURL:

<?php
//The url you wish to send the POST request to
$url = $file_name;

//The data you want to send via POST
$fields = [
    '__VIEWSTATE '      => $state,
    '__EVENTVALIDATION' => $valid,
    'btnSubmit'         => 'Submit'
];

//url-ify the data for the POST
$fields_string = http_build_query($fields);

//open connection
$ch = curl_init();

//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);

//So that curl_exec returns the contents of the cURL; rather than echoing it
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true); 

//execute post
$result = curl_exec($ch);
echo $result;
?>
  • 3
    этот работал для меня, потому что страница, которую я отправляю на страницу, на которой нет содержимого, поэтому версия file_get_contents не работала.
  • 8
    Решение file_get_contents не работает в конфигурациях PHP с отключенным параметром allow_url_fopen (как в случае общего хостинга). В этой версии используется библиотека curl, и я считаю ее наиболее универсальной, поэтому я отдаю вам свой голос.
Показать ещё 4 комментария
49

Я использую следующую функцию для публикации данных с помощью curl. $ data - это массив полей для публикации (будет правильно закодирован с использованием http_build_query). Данные кодируются с использованием application/x-www-form-urlencoded.

function httpPost($url, $data)
{
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($curl);
    curl_close($curl);
    return $response;
}

@Edward упоминает, что http_build_query может быть опущен, так как curl будет правильно кодировать массив, переданный параметру CURLOPT_POSTFIELDS, но имейте в виду, что в этом случае данные будут кодироваться с использованием multipart/form-data.

Я использую эту функцию с API, которые ожидают, что данные будут закодированы с помощью application/x-www-form-urlencoded. Вот почему я использую http_build_query().

  • 0
    Передача массива в CURLOPT_POSTFIELDS приводит к тому, что данные кодируются с использованием multipart / form-data, что может быть нежелательно.
  • 0
    Пользователь запросил file_get_contents, поэтому ему нужно решение для изменения default_stream_context
37

Я рекомендую использовать пакет с открытым исходным кодом guzzle, который полностью протестирован и использует последние методы кодирования.

Установка Guzzle

Перейдите в командную строку в папке проекта и введите следующую команду (если у вас уже установлен диспетчер пакетов composer), Если вам нужна помощь по установке Composer, вы должны посмотреть здесь.

php composer.phar require guzzlehttp/guzzle

Использование Guzzle для отправки запроса POST

Использование Guzzle очень прямолинейно, поскольку использует легкий объектно-ориентированный API:

// Initialize Guzzle client
$client = new GuzzleHttp\Client();

// Create a POST request
$response = $client->request(
    'POST',
    'http://example.org/',
    [
        'form_params' => [
            'key1' => 'value1',
            'key2' => 'value2'
        ]
    ]
);

// Parse the response object, e.g. read the headers, body, etc.
$headers = $response->getHeaders();
$body = $response->getBody();

// Output headers and body for debugging purposes
var_dump($headers, $body);
  • 5
    Было бы полезно узнать, какие преимущества это имеет по сравнению с уже опубликованным нативным решением PHP, а также cURL.
  • 6
    @artfulrobot: нативное PHP-решение имеет множество проблем (например, соединение с https, проверка сертификата и т. п.), поэтому почти каждый разработчик PHP использует cURL. И почему бы не использовать cURL в этом случае? Все просто: Guzzle имеет простой, легкий и легкий интерфейс, который устраняет все эти «проблемы с низкоуровневой обработкой cURL». В любом случае, почти все, кто разрабатывает современный PHP, используют Composer, поэтому использовать Guzzle просто.
Показать ещё 1 комментарий
23

Там другой метод CURL, если вы идете этим путем.

Это довольно просто, как только вы узнаете, как работает PHP curl extension, сочетая различные флаги с вызовами setopt(). В этом примере у меня есть переменная $xml, которая содержит XML, который я подготовил для отправки, - я собираюсь опубликовать содержимое этого примера, например, методом тестирования.

$url = 'http://api.example.com/services/xmlrpc/';
$ch = curl_init($url);

curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
//process $response

Сначала мы инициализировали соединение, затем мы установили некоторые опции, используя setopt(). Они говорят PHP, что мы делаем почтовый запрос, и что мы отправляем с ним некоторые данные, поставляя данные. Флаг CURLOPT_RETURNTRANSFER сообщает curl, чтобы дать нам результат как возвращаемое значение curl_exec, а не выводить его. Затем мы делаем вызов и закрываем соединение - результат в $response.

  • 1
    в третьем вызове curl_setopt () первый аргумент должен быть $ch не $curl , правильно?
  • 0
    Можете ли вы использовать этот же код для размещения данных JSON? Но замените $ xml, скажем, $ json (где $ json - это, вероятно, строка JSON?)
18

Если вы случайно используете Wordpress для разработки своего приложения (это действительно удобный способ получить авторизацию, информационные страницы и т.д. даже для очень простых вещей), вы можете использовать следующий фрагмент:

$response = wp_remote_post( $url, array('body' => $parameters));

if ( is_wp_error( $response ) ) {
    // $response->get_error_message()
} else {
    // $response['body']
}

Он использует разные способы создания фактического HTTP-запроса, в зависимости от того, что доступно на веб-сервере. Для получения дополнительной информации см. Документацию HTTP API.

Если вы не хотите разрабатывать настраиваемую тему или плагин для запуска механизма Wordpress, вы можете просто сделать следующее в изолированном PHP файле в корневом каталоге wordpress:

require_once( dirname(__FILE__) . '/wp-load.php' );

// ... your code

Он не будет показывать какую-либо тему или выводить какой-либо HTML-код, просто взломайте API-интерфейсы Wordpress!

15

Я хотел бы добавить некоторые мысли об основанном на завитках ответе Фреда Танрикута. Я знаю, что большинство из них уже написаны в ответах выше, но я думаю, что это хорошая идея, чтобы показать ответ, который включает в себя все из них вместе.

Вот класс, который я написал для выполнения запросов HTTP-GET/POST/PUT/DELETE на основе curl, касающихся только тела ответа:

class HTTPRequester {
    /**
     * @description Make HTTP-GET call
     * @param       $url
     * @param       array $params
     * @return      HTTP-Response body or an empty string if the request fails or is empty
     */
    public static function HTTPGet($url, array $params) {
        $query = http_build_query($params); 
        $ch    = curl_init($url.'?'.$query);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
    /**
     * @description Make HTTP-POST call
     * @param       $url
     * @param       array $params
     * @return      HTTP-Response body or an empty string if the request fails or is empty
     */
    public static function HTTPPost($url, array $params) {
        $query = http_build_query($params);
        $ch    = curl_init();
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
    /**
     * @description Make HTTP-PUT call
     * @param       $url
     * @param       array $params
     * @return      HTTP-Response body or an empty string if the request fails or is empty
     */
    public static function HTTPPut($url, array $params) {
        $query = \http_build_query($params);
        $ch    = \curl_init();
        \curl_setopt($ch, \CURLOPT_RETURNTRANSFER, true);
        \curl_setopt($ch, \CURLOPT_HEADER, false);
        \curl_setopt($ch, \CURLOPT_URL, $url);
        \curl_setopt($ch, \CURLOPT_CUSTOMREQUEST, 'PUT');
        \curl_setopt($ch, \CURLOPT_POSTFIELDS, $query);
        $response = \curl_exec($ch);
        \curl_close($ch);
        return $response;
    }
    /**
     * @category Make HTTP-DELETE call
     * @param    $url
     * @param    array $params
     * @return   HTTP-Response body or an empty string if the request fails or is empty
     */
    public static function HTTPDelete($url, array $params) {
        $query = \http_build_query($params);
        $ch    = \curl_init();
        \curl_setopt($ch, \CURLOPT_RETURNTRANSFER, true);
        \curl_setopt($ch, \CURLOPT_HEADER, false);
        \curl_setopt($ch, \CURLOPT_URL, $url);
        \curl_setopt($ch, \CURLOPT_CUSTOMREQUEST, 'DELETE');
        \curl_setopt($ch, \CURLOPT_POSTFIELDS, $query);
        $response = \curl_exec($ch);
        \curl_close($ch);
        return $response;
    }
}

улучшения

  • Использование http_build_query для получения строки запроса из массива запроса (вы также можете использовать сам массив, поэтому смотрите: http://php.net/manual/en/function.curl-setopt.php)
  • Возвращать ответ, а не повторять его. Кстати, вы можете избежать возврата, удалив строку curl_setopt ($ ch, CURLOPT_RETURNTRANSFER, true); , После этого возвращаемое значение является логическим (истина = запрос был успешным, в противном случае произошла ошибка), и ответ отображается. Смотрите: http://php.net/en/manual/function.curl-exec.php
  • Очистите закрытие сессии и удаление обработчика curl с помощью curl_close. Смотрите: http://php.net/manual/en/function.curl-close.php
  • Использование логических значений для функции curl_setopt вместо использования любого числа (я знаю, что любое число, не равное нулю, также считается истинным, но использование true создает более читаемый код, но это только мое мнение)
  • Возможность совершать вызовы HTTP-PUT/DELETE (полезно для тестирования сервиса RESTful)

Пример использования

ПОЛУЧИТЬ

$response = HTTPRequester::HTTPGet("http://localhost/service/foobar.php", array("getParam" => "foobar"));

СООБЩЕНИЕ

$response = HTTPRequester::HTTPPost("http://localhost/service/foobar.php", array("postParam" => "foobar"));

ПОЛОЖИЛ

$response = HTTPRequester::HTTPPut("http://localhost/service/foobar.php", array("putParam" => "foobar"));

УДАЛЯТЬ

$response = HTTPRequester::HTTPDelete("http://localhost/service/foobar.php", array("deleteParam" => "foobar"));

тестирование

Вы также можете сделать несколько крутых тестов сервиса с помощью этого простого класса.

class HTTPRequesterCase extends TestCase {
    /**
     * @description test static method HTTPGet
     */
    public function testHTTPGet() {
        $requestArr = array("getLicenses" => 1);
        $url        = "http://localhost/project/req/licenseService.php";
        $this->assertEquals(HTTPRequester::HTTPGet($url, $requestArr), '[{"error":false,"val":["NONE","AGPL","GPLv3"]}]');
    }
    /**
     * @description test static method HTTPPost
     */
    public function testHTTPPost() {
        $requestArr = array("addPerson" => array("foo", "bar"));
        $url        = "http://localhost/project/req/personService.php";
        $this->assertEquals(HTTPRequester::HTTPPost($url, $requestArr), '[{"error":false}]');
    }
    /**
     * @description test static method HTTPPut
     */
    public function testHTTPPut() {
        $requestArr = array("updatePerson" => array("foo", "bar"));
        $url        = "http://localhost/project/req/personService.php";
        $this->assertEquals(HTTPRequester::HTTPPut($url, $requestArr), '[{"error":false}]');
    }
    /**
     * @description test static method HTTPDelete
     */
    public function testHTTPDelete() {
        $requestArr = array("deletePerson" => array("foo", "bar"));
        $url        = "http://localhost/project/req/personService.php";
        $this->assertEquals(HTTPRequester::HTTPDelete($url, $requestArr), '[{"error":false}]');
    }
}
  • 0
    Для меня это говорит "Uncaught Error: вызов неопределенного метода HTTPRequester :: HTTPost ()" . Я просто вставил ваш класс в мой файл .php. Что-нибудь еще мне нужно сделать?
  • 1
    Можете ли вы опубликовать свой код? Довольно сложно догадаться, что не так без какого-либо фрагмента кода.
Показать ещё 5 комментариев
10

Другая альтернатива из завитка менее метода выше, чтобы использовать встроенные функции потока:

  • stream_context_create():

    Создает и возвращает контекст потока с любыми параметрами, предоставленными в предустановке параметров.

  • stream_get_contents():

    Идентичен file_get_contents(), за исключением того, что stream_get_contents() работает с уже открытым потоковым ресурсом и возвращает оставшееся содержимое в строке, вплоть до байтов максимальной длины и начиная с указанного смещения.

Функция POST с этим может быть просто так:

<?php

function post_request($url, array $params) {
  $query_content = http_build_query($params);
  $fp = fopen($url, 'r', FALSE, // do not use_include_path
    stream_context_create([
    'http' => [
      'header'  => [ // header array does not need '\r\n'
        'Content-type: application/x-www-form-urlencoded',
        'Content-Length: ' . strlen($query_content)
      ],
      'method'  => 'POST',
      'content' => $query_content
    ]
  ]));
  if ($fp === FALSE) {
    fclose($fp);
    return json_encode(['error' => 'Failed to get contents...']);
  }
  $result = stream_get_contents($fp); // no maxlength/offset
  fclose($fp);
  return $result;
}
  • 1
    Этот метод без CURL работал хорошо для меня, чтобы проверить reCAPTCHA от Google. Этот ответ сходится с этим кодом Google: github.com/google/recaptcha/blob/master/src/ReCaptcha/…
5

Я искал аналогичную проблему и нашел лучший способ сделать это. Итак, вот оно.

Вы можете просто поместить следующую строку на страницу перенаправления (например, page1.php).

header("Location: URL", TRUE, 307); // Replace URL with to be redirected URL, e.g. final.php

Мне нужно это, чтобы перенаправить запросы POST для REST API-вызовов. Это решение может перенаправлять с пост-данными, а также с настраиваемыми значениями заголовков.

Здесь ссылка ссылки.

  • 0
    Это ответ, как перенаправить запрос страницы, а не Как отправить запрос POST с PHP? Конечно, это переадресует любые параметры POST, но это совсем не одно и то же
  • 0
    @ DelightedD0D, Извините, я не получил разницу между redirect a page request with POST param send POST request . Для меня цель обоих одинакова, поправьте меня, если я ошибаюсь.
Показать ещё 1 комментарий
4

Есть еще один, который вы можете использовать

<?php
$fields = array(
    'name' => 'mike',
    'pass' => 'se_ret'
);
$files = array(
    array(
        'name' => 'uimg',
        'type' => 'image/jpeg',
        'file' => './profile.jpg',
    )
);

$response = http_post_fields("http://www.example.com/", $fields, $files);
?>

Нажмите здесь для подробностей

  • 2
    Это зависит от расширения PECL, которое большинство не будет установлено. Даже не уверен, что он все еще доступен, так как страницы руководства были удалены.
1

Попробуйте PEAR HTTP_Request2 пакет, чтобы легко отправлять запросы POST. Кроме того, вы можете использовать функции curl PHP или использовать контекст потока PHP.

HTTP_Request2 также позволяет издеваться над сервером, поэтому вы можете легко тестировать свой код

  • 6
    Я хотел бы видеть вас, чтобы уточнить это, если это возможно.
0

Лучший способ отправки запросов GET или POST с помощью PHP:

<?php
    $r = new HttpRequest('http://example.com/form.php', HttpRequest::METH_POST);
    $r->setOptions(array('cookies' => array('lang' => 'de')));
    $r->addPostFields(array('user' => 'mike', 'pass' => 's3c|r3t'));

    try {
        echo $r->send()->getBody();
    } catch (HttpException $ex) {
        echo $ex;
    }
?>

Код взят из официальной документации здесь http://php.net/manual/it/httprequest.send.php

Ещё вопросы

Сообщество Overcoder
Наверх
Меню