Need clarification type=hidden with submit button from Novice to Ninja

I am following and doing the exercises in the PHP & MySQL Novice to Ninja fifth edition.

On page 214 we create a search form and I understand everything except this line of code:

[input type=“hidden” name=“action” value=“search”] ← this line
[input type=“submit” value=“Search”]

Why do I need this line?

Some browsers (older IE?) do not send the submit button with the POST variables.

So if the code does something like

if ($_POST['search']) {

it will sometimes be wrongly FALSE
Having that in a hidden input avoids that problem

How old are these browsers? I’ve never come across this, ever, and I’ve been doing this for a VERY long time.

The reason that the search won’t be seen in the $_POST data is because the submit input hasn’t got a name

<input type="submit" name="action" value="Search">

That would do the job.

HOWEVER, I would suggest that the reason is so that your action isn’t dependant on what text you display on your submit button. Imagine you wanted to change it to say Click to Search. You would then need to go into the action and where you’ve probably got something like this:

if ($_POST['action'] == 'search') {
    // Do something
} 

You’d need to seek them all out and change them to:

if ($_POST['action'] == 'Click to Search') {
    // Do something
}

Trust me when I say that you don’t want to put yourself into that position :smile:

I agree with you on that 100% (first-hand experience)

It has been so long I forgot a detail. The problem also involves “click” vs. “enter”

1 Like

Yes, it’s not a problem unless you have multiple submits, which is acceptable. At that point you will only see the submit that was clicked. It won’t matter if you clicked it with your mouse or pressed enter on your keyboard though; you’ll only see the one. So in the event that you have multiple submit buttons you would need to check to see which was clicked:

if ($_POST['submit1']) {

} elseif ($_POST['submit2']){

}

I’ve got to say that I really dislike this kind of code though. I don’t like to see forms with multiple submit buttons. They’re a massive headache!

IE9 was notorious for this.

<input type='submit' name='search' value='1'>

If you hit “enter” to submit the form instead of clicking the button in IE9, $_POST[‘search’] does not exist.

Do not trust a button to have been pushed.

So if I understand correctly, IE9 or under will not recognize the code (when pressing enter) if I put the code in one line:

[input type=“submit” name=“action” value=“Search”]

versus using two line correct?:

[input type=“hidden” name=“action” value=“search”]
[input type=“submit” value=“Search”]

What do you guys usually do?

Also if you look at both line I am guessing it is not case sensitive. one is “search” and the other is “Search”

ignore the submit button and test that the data to process are there.

2 Likes

+1

Not as “generic” as testing for “search”, and still might lead to a “change everywhere” chore, but I can’t recall ever needing to since I stopped testing for “search”.

Using a hidden input of “search” in all forms does seem like a more future proof way to do things

make that a CSRF token and then it actually does something useful.

1 Like

OK, in case a newbie like me is doing the exercise in the book. On page 291, Kevin explains the reason for the hidden field. It is indeed like everyone here stated when someone presses the enter key instead of clicking the submit button.

1 Like

I don’t want to butt in where I don’t belong and I’m not sure if the book is teaching you proper coding, but checking if something like that is clicked is a bad idea. Generically, it is easier to do it that way however it actually is flawed. I know I have said this to so many people and it might get annoying at times, but checking to see if something was submitted by checking a $_POST[‘submit’] is flawed.

Let’s say someone has FireFox installed. I’m not sure if it’s the same with Google Chrome, but in FireFox, you are given the “Inspect Element (Q)” tool. If an average Joe comes along and knows how to use the “Inspect Element (Q)” option properly. They can actually change the value of said fields to what ever they want and poof. That whole if($_POST[‘submit’]) failed.

If you had a field like

<input type="hidden" name="submit" value="1">

And the average Joe was using the Inspect Element tool, they can do something like this

<input type="hidden" name="a_fools_fool_is_a_fools_fool" value="1">

Then when they go to hit the submit button or hit the enter button on a text filed, their submission wasn’t successful because all they did was modified a field.

You should actually be checking this with the $_ SERVER[‘REQUEST_METHOD’]. This way you avoid these kind of problems. All you really to do after that is check if the fields are up to standard and what you want them to be. You should then wrap your error checking inside the $_ SERVER[‘REQUEST_METHOD’].

Something like this is fool-proof

<?php
// Check if the form was submitted via POST
if($_SERVER['REQUEST_METHOD'] == 'POST') {
    // Check if the text field was empty
    if($_POST['next_field'] == '') {
        $_SESSION['your_error_session'] = 1; // Only put an integer here
        // You don't want to stuff an actual error into your session variables
        // You can always check if the session variable exists on your HTML page.
        if(isset($_SERVER['HTTP_REFERER'])) {
            // Redirect the user back to the same page without giving them a back button. IMO it is a bad idea to give the user a back button when it comes to form submission. You should only give them the back button if it is really necessary. This is because if a user submits something. When they hit the back button on a browser, their data is lost.
            header('Location: ' . $_SERVER['HTTP_REFERER']);
        } else {
            // Give them a direct URL. This is only needed if the user accessed the page directly.
            // The $_SERVER['HTTP_REFERER'] will be empty if they didn't come from a link. If they accessed the file directly, this variable will be empty.
        }
    } else {
        // What ever you want to put in once all fields are correctly typed in
    }
} else {
    // Form wasn't submitted. Most likely it was a direct access
}

Something along those lines would work. If I sound rude or anything. I apologize. If I am wrong, correct me.

So here’s why you’re wrong.

if your “i’m gonna be smart and fiddle with your form” guy goes and changes the name of “next_field” to “imsilly”, then your first line here throws a WARNING because $_POST[‘next_field’] doesnt exist.

How would you prevent that? isset($_POST['next_field']) … the thing you’ve just said is a bad idea. Oh… right.

Also, if the page has multiple forms, REQUEST_METHOD does not differentiate between them. So… you’d have to do isset checks anyway… making the request_method check… redundant.

I can send blind POST requests to your form action. So “direct access” is a bit of a misnomer - yup, someone who pointed their browser directly at your form action would indeed send GET, but… an isset… catches that too.

Also, never rely on $_SERVER['HTTP_REFERER'] for anything, including sending the user back to where they came from. Send them to index.php instead. Or if you feel fancy and this form handler is only for a specific page, specify that page instead.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.