How do I send a POST request with PHP?
Actually I want to read the contents that come after the search query, when it is done. The problem is that the URL only accepts POST methods, and it does not take any action with GET method. I have to read all contents with the help of domdocument or file_get_contents() . Is there any method that will let me send parameters with POST method and then read the contents via PHP ?
18 Answers 18
Answer recommended by PHP Collective
$url = 'http://server.com/path'; $data = ['key1' => 'value1', 'key2' => 'value2']; // use key 'http' even if you send the request to https://. $options = [ 'http' => [ '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);
See the PHP manual for more information on the method and how to add headers, for example:
It’s worth noting that if you decide to use an array for the headers, do NOT end the keys or values with ‘\r\n’. stream_context_create() will only take the text up to the first ‘\r\n’
A URL can be used as a filename with file_get_contents() only if the fopen wrappers have been enabled. See php.net/manual/en/…
@jvannistelrooy CURL for PHP is an extension which may not exist in all environments whereas file_get_contents() is part of PHP’s core. Also, using an extension unnecessarily can widen the attack surface of your app. E.g. Google php curl cve
$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, true); 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; ?>
this one worked for me because the page I am sending to a page that has no content so the file_get_contents version didn’t work.
file_get_contents solution doesn’t work on PHP configurations with allow_url_fopen Off (like in shared hosting). This version uses curl library and I think is most «universal» so I give you my vote
Although it is not very important, the CURLOPT_POSTFIELDS parameter data actually doesn’t need to be converted to a string («urlified»). Quote: «This parameter can either be passed as a urlencoded string like ‘para1=val1¶2=val2&. ‘ or as an array with the field name as key and field data as value. If value is an array, the Content-Type header will be set to multipart/form-data.» Link: php.net/manual/en/function.curl-setopt.php.
Also, no offence for writing it differently, but I don’t know why the CURLOPT_POST parameter is specified as a number here as it says to set it to a boolean on the manual page. Quote: «CURLOPT_POST: TRUE to do a regular HTTP POST.» Link: php.net/manual/en/function.curl-setopt.php.
I use the following function to post data using curl. $data is an array of fields to post (will be correctly encoded using http_build_query() ).
function httpPost($url, $data)
@Edward mentions that http_build_query() may be omitted since curl will correctly encode array passed to CURLOPT_POSTFIELDS parameter, which is correct, but be advised that in this case the data will be encoded using multipart/form-data and it may not be desirable as some endpoints expect data to be encoded using application/x-www-form-urlencoded . When using http_build_query() as in the function above, data will be encoded with application/x-www-form-urlencoded .
Passing array to CURLOPT_POSTFIELDS causes data to be encoded using multipart/form-data which may not be desirable.
The user did ask for file_get_contents, so he needs a solution for changing the default_stream_context
To clarify: I think @DimaL. is responding to a comment that has been deleted; http_build_query converts $data array to a string, avoiding output as multipart/form-data.
@ToolmakerSteve as I said, the question was for file_get_contents and your solution needs CURL what many people dont have. so your solution is maybe working, but it is not answering the question how to do this with the native builtin file/stream functions.
I recommend you to use the open-source package guzzle that is fully unit tested and uses the latest coding practices.
Installing Guzzle
Go to the command line in your project folder and type in the following command (assuming you already have the package manager composer installed). If you need help how to install Composer, you should have a look here.
php composer.phar require guzzlehttp/guzzle
Using Guzzle to send a POST request
The usage of Guzzle is very straight forward as it uses a light-weight object-oriented 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);
It would be useful to know what advantages this has over the native PHP solution already posted, and the cURL one too.
@artfulrobot: The native PHP-solution has lots of problems (e.g. connecting with https, certificate verification, etc.pp.), which is why almost every PHP developer uses cURL. And why not use cURL in this case? It’s simple: Guzzle has a straight-forward, easy, light-weight interface which abstracts all those «low-level cURL handling problems» away. Almost everyone developing modern PHP uses Composer anyway, so using Guzzle is just really simple.
Thanks, I know guzzle is popular, however there are use cases when composer causes grief (e.g. developing plugins for bigger software projects that might already use a (different version) of guzzle or other dependencies), so it’s good to know this info to make a decision about which solution will be most robust
@Andreas while you are right, this is a good example of more and more abstraction leading to less and less understanding of low-level technology thus leading to more and more devs not knowing what they are doing there anyway and not beeing able to debug even a simple request.
@clockw0rk Unfortunately, you’re right about that. But still abstraction (to some extent) is useful and saves a lot of time and mistakes / potential bugs. Obviously, everyone using Guzzle should still be able to debug requests and also have a basic understanding of networking and how HTTP works.
I’d like to add some thoughts about the curl-based answer of Fred Tanrikut. I know most of them are already written in the answers above, but I think it is a good idea to show an answer that includes all of them together.
Here is the class I wrote to make HTTP-GET/POST/PUT/DELETE requests based on curl, concerning just about the response body:
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; >>
Improvements
- Using http_build_query to get the query-string out of an request-array.(you could also use the array itself, therefore see: http://php.net/manual/en/function.curl-setopt.php)
- Returning the response instead of echoing it. Btw you can avoid the returning by removing the line curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);. After that the return value is a boolean(true = request was successful otherwise an error occured) and the response is echoed. See: http://php.net/en/manual/function.curl-exec.php
- Clean session closing and deletion of the curl-handler by using curl_close. See: http://php.net/manual/en/function.curl-close.php
- Using boolean values for the curl_setopt function instead of using any number.(I know that any number not equal zero is also considered as true, but the usage of true generates a more readable code, but that’s just my opinion)
- Ability to make HTTP-PUT/DELETE calls(useful for RESTful service testing)
Example of usage
GET
$response = HTTPRequester::HTTPGet("http://localhost/service/foobar.php", array("getParam" => "foobar"));
POST
$response = HTTPRequester::HTTPPost("http://localhost/service/foobar.php", array("postParam" => "foobar"));
PUT
$response = HTTPRequester::HTTPPut("http://localhost/service/foobar.php", array("putParam" => "foobar"));
DELETE
$response = HTTPRequester::HTTPDelete("http://localhost/service/foobar.php", array("deleteParam" => "foobar"));
Testing
You can also make some cool service tests by using this simple class.
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), '[]'); > /** * @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), '[]'); > /** * @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), '[]'); > /** * @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), '[]'); > >
How to pass POST parameters in a url
Is it possible to upload images/files by sending the POST or REQUEST, parameters in the URL without HTML content? I created a PHP file that gets a image from my someone, stores that file into the database, and a in a folder on my computer. It works fine but what I want to do now is remove the html content and only allow someone to send the images/files via the URL. I tried using $_GET but I received a lot of errors. I also researched this and read that only $_POST will work. Here is my PHP source code with HTML but keep in mind, «I want the page blank and the only way for someone to send the images/files is through URL». PHP:
if(isset($_POST['submit'])) < if(@getimagesize($_FILES['image']['tmp_name']) ==FALSE)< // Select an image echo "Please select an image."; >else < // THE PATH TO STORE THE UPLOAD IMAGE $target = "images/".basename($_FILES['image']['name']); //CONNECT TO DATABASE $db = mysqli_connect("localhost", "root", ""); mysqli_select_db($db, "magicsever"); if(mysqli_connect_error())< die ("Database connection error"); >//GET ALL THE SUBMITTED DATA $image = $_FILES['image']['tmp_name']; $name = $_FILES['image']['name']; //Store te submitted data to database $sql = "INSERT INTO image_test (name, image)VALUES ('$name','$image')"; $query = mysqli_query($db, $sql); //Now lets move the uploaded image into the folder $nullResult = array(); $nullResult['Image'] = (move_uploaded_file($_FILES['image']['tmp_name'], $target))? "Successful": "Unsuccessful"; echo json_encode($nullResult); > >
Your code is vulnerable to SQL injection attacks. You should use mysqli or PDO prepared statements with bound parameters as described in this post.
When your visitor POST an image, it does only include that image. What is HTML content? I can’t see any reason, you should use GET, instead POST, to upload a file to server.
Thanks @AlexHowansky and i am trying to send it in the URL without the html content which is the upload button etc