# PHP Form submitting If we have the following structure in our application: * 📁 application_folder_name - 📄 index.php - 📄 handle_form.php - 📄 main.js And we fill our `index.php` with the following content just to get a basic website with a form working. You should be able to run this through a php-server of your choice. ```html PHP
``` ### Submitting a form with PHP Lets focus on the form. To successfully submit a form you need to have your inputs inside of the `form`-element, this indicates that the inputs shall be sent along with the form if we submit the form "like normal". To send the form without JavaScript all inputs need to have a `name`, in fact they should have a `name` regardless if you are sending the data via JavaScript or PHP. The actual form needs **3** things: * `action` - telling the form to **which** file should this information be sent, in this case `handle_form.php` which is located in the same folder as `index.php` * `method` - **how** should this information be sent: `POST` or `GET`. Default is `GET` * `` - To be able to send the form via click, even if you handle this via JavaScript, you should always ha a "Send"-button. This button can also be `` to allow HTML inside of the button (for example to add an icon inside a button) ```html
``` All this information needs to exists in HTML to successfully send a request. If this markup is correct we should be able to submit the form to the file `handle_form.php`: ```php ` will result in the value of the input field being stored in `$_POST["username"]`. So the `name` of the input field will decide what the variable is called in PHP. * If we use `method="POST"` on the form the values will be stored in `$_POST` * If we use `method="GET"` or do not supply a `method` to the form the values will be stored in `$_GET` * PHP also has a `$_REQUEST`-variable that can contain these values. `$_POST` and `$_GET` will always be an _Associative Array_, this is how we would write the variable if it wouldn't get created for us: ```php "zero_cool", "favorite_number" => "10" ]; ``` The JavaScript equivalent would be: ```js var $_POST = { username: "zero_cool", favorite_number: "10" }; ``` #### Using `GET` instead of `$_POST` We can send the same information with `GET` instead: ```html
``` The only difference in this case is that we store the data inside of `$_GET` instead of `$_POST`. ```php "zero_cool", "favorite_number" => "10" ]; ``` The JavaScript equivalent would be: ```js var $_GET = { username: "zero_cool", favorite_number: "10" }; ``` The other difference is that the information will be available inside of the URL: ```http http://localhost:8888/handle_form.php?username=zero_cool&favorite_number=10 ``` This also means that we can basically call PHP-files like the one handling our form with a link instead. So if we were to write the code below, we would get the same result. This is only possible with `GET`-requests because the information is always sent via the URL and **not** inside of body like with `POST`. ```html Click me to submit ``` ### Submitting a form with JavaScript We can submit the same form with the use of JavaScript without reloading the page. The same logic will be applied inside of the PHP-file and most of the work must be done in JavaScript. If we have the same form as above we must first make sure the form **isn't** being submitted. A forms default behavior is to redirect you to a new site, which is fine if we don't have JavaScript. But in this case we can use JavaScript to our advantage. ```js // Get the whole form, not the individual input-fields const form = document.getElementById('example_form'); /** * Add an onclick-listener to the whole form, the callback-function * will always know what you have clicked and supply your function with * an event-object as first parameter, `addEventListener` creates this for us */ form.addEventListener('click', function(event){ //Prevent the event from submitting the form, no redirect or page reload event.preventDefault(); }); ``` No we have stopped the form from behaving like it normally would. That also means that we need to specify what it should do instead. So we know that we need to communicate with the backend. Even though the client side and the server side are on the same domain, JavaScript can't communicate back to PHP without going through AJAX. AJAX must always be used. Let's use the native built in way of using AJAX: `fetch`. Notice that the first code below will not work, it is just a first step ```js // Get the whole form, not the individual input-fields const form = document.getElementById('example_form'); /** * Add an onclick-listener to the whole form, the callback-function * will always know what you have clicked and supply your function with * an event-object as first parameter, `addEventListener` creates this for us */ form.addEventListener('click', function(event){ //Prevent the event from submitting the form, no redirect or page reload event.preventDefault(); postData(); }); async function postData(){ /* * We are still using the same file as before and we are still not touching * either the backend code or the actual form. We could grab * the action-attribute from the form but it's easier to just put * in the 'URL' here. We don't need to supply PORT or 'localhost' */ const response = await fetch('handle_form.php'); /* * Because we are using `echo` inside of `handle_form.php` the response * will be a string and not JSON-data. Because of this we need to use * `response.text()` instead of `response.json()` to convert it to someting * that JavaScript understands */ const data = await response.text(); //This should later print out the values submitted through the form console.log(data); } ``` But we are still missing the information to be sent. In raw PHP/HTML the form handles converting the data and sending it to `handle_form.php`. If we write our own logic for sending the data we must also make sure that the data is properly formatted. The data needs to be formatted to [`x-www-form-urlencoded`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) or [`multipart/form-data`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) which is what PHP is expecting to recieve. The easiest way to handle this is via the [`FormData`-object](https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects). We can also make it accept JSON but it's easier to use the `FormData`-object. ```js // Get the whole form, not the individual input-fields const form = document.getElementById('example_form'); /** * Add an onclick-listener to the whole form, the callback-function * will always know what you have clicked and supply your function with * an event-object as first parameter, `addEventListener` creates this for us */ form.addEventListener('click', function(event){ //Prevent the event from submitting the form, no redirect or page reload event.preventDefault(); /** * If we want to use every input-value inside of the form we can call * `new FormData()` with the form we are submitting as an argument * This will create a body-object that PHP can read properly */ const formattedFormData = new FormData(form); postData(formattedFormData); }); async function postData(formattedFormData){ /** * If we want to 'POST' something we need to change the `method` to 'POST' * 'POST' also expectes the request to send along values inside of `body` * so we must specify that property too. We use the earlier created * FormData()-object and just pass it along. */ const response = await fetch('handle_form.php',{ method: 'POST', body: formattedFormData }); /* * Because we are using `echo` inside of `handle_form.php` the response * will be a string and not JSON-data. Because of this we need to use * `response.text()` instead of `response.json()` to convert it to someting * that JavaScript understands */ const data = await response.text(); //This should now print out the values that we sent to the backend-side console.log(data); } ``` #### Adding more values to `FormData` in JavaScript If we want to add stuff that isn't inside of the form to this object we can use the `.append()`-method on the `FormData`-object: ```js form.addEventListener('click', function(event){ event.preventDefault(); const formattedFormData = new FormData(form); formattedFormData.append('property', 'value'); postData(formattedFormData); }); ``` #### Sending both `GET` AND `POST` The form and the `fetch`-call will only either use `GET` or `POST`. A request can only be one of these requests. We can however send along values in the URL and these will be stored inside of the `$_GET`-variable even though our request is a `POST`. ```js const form = document.getElementById('example_form'); form.addEventListener('click', function(event){ event.preventDefault(); const formattedFormData = new FormData(form); postData(formattedFormData); }); async function postData(formattedFormData){ /** * The request is still 'POST' but the $_GET variable * will get values too: 'name' and 'favorite_color' */ const response = await fetch( 'handle_form.php?name=Jesper&favorite_color=pink', { method: 'POST', body: formattedFormData } ); const data = await response.text(); console.log(data); } ``` This would result in the following variables being set inside of `handle_form.php`: ```php