Anda di halaman 1dari 15

Dealing with Forms

One of the most powerful features of PHP is the way it handles HTML forms. The basic concept that is
important to understand is that any form element will automatically be available to your PHP scripts. Please
read the manual section on Variables from outside of PHP for more information and examples on using
forms with PHP. Here is an example HTML form:

Example 2.6. A simple HTML form

<form action="action.php" method="post">


<p>Your name: <input type="text" name="name" /></p>
<p>Your age: <input type="text" name="age" /></p>
<p><input type="submit" /></p>
</form>

There is nothing special about this form. It is a straight HTML form with no special tags of any kind. When
the user fills in this form and hits the submit button, the action.php page is called. In this file you would
write something like this:

Example 2.7. Printing data from our form

Hi <?php echo htmlspecialchars($_POST['name']); ?>.


You are <?php echo (int)$_POST['age']; ?> years old.

A sample output of this script may be:

Hi Joe. You are 22 years old.

Apart from the htmlspecialchars() and (int) parts, it should be obvious what this does. htmlspecialchars()
makes sure any characters that are special in html are properly encoded so people can't inject HTML tags or
Javascript into your page. For the age field, since we know it is a number, we can just convert it to an
integer which will automatically get rid of any stray characters. You can also have PHP do this for you
automatically by using the filter extension. The $_POST['name'] and $_POST['age'] variables are
automatically set for you by PHP. Earlier we used the $_SERVER superglobal; above we just introduced the
$_POST superglobal which contains all POST data. Notice how the method of our form is POST. If we used
the method GET then our form information would live in the $_GET superglobal instead. You may also use
the $_REQUEST superglobal, if you do not care about the source of your request data. It contains the
merged information of GET, POST and COOKIE data. Also see the import_request_variables() function.
HTML Forms (GET and POST)

When a form is submitted to a PHP script, the information from that form is automatically made available to
the script. There are many ways to access this information, for example:

Example 12.9. A simple HTML form

<form action="foo.php" method="post">


Name: <input type="text" name="username" /><br />
Email: <input type="text" name="email" /><br />
<input type="submit" name="submit" value="Submit me!" />
</form>

Depending on your particular setup and personal preferences, there are many ways to access data from your
HTML forms. Some examples are:

Example 12.10. Accessing data from a simple POST HTML form

<?php
// Available since PHP 4.1.0

echo $_POST['username'];
echo $_REQUEST['username'];

import_request_variables('p', 'p_');
echo $p_username;

// Available since PHP 3. As of PHP 5.0.0, these long predefined


// variables can be disabled with the register_long_arrays directive.

echo $HTTP_POST_VARS['username'];

// Available if the PHP directive register_globals = on. As of


// PHP 4.2.0 the default value of register_globals = off.
// Using/relying on this method is not preferred.

echo $username;
?>

Using a GET form is similar except you'll use the appropriate GET predefined variable instead. GET also
applies to the QUERY_STRING (the information after the '?' in a URL). So, for example,
http://www.example.com/test.php?id=3 contains GET data which is accessible with $_GET['id']. See also
$_REQUEST and import_request_variables().
Note: Superglobal arrays, like $_POST and $_GET, became available in PHP 4.1.0

As shown, before PHP 4.2.0 the default value for register_globals was on. And, in PHP 3 it was always on.
The PHP community is encouraging all to not rely on this directive as it's preferred to assume it's off and
code accordingly.

Note: The magic_quotes_gpc configuration directive affects Get, Post and Cookie values. If turned on,
value (It's "PHP!") will automagically become (It\'s \"PHP!\"). Escaping is needed for DB insertion. See
also addslashes(), stripslashes() and magic_quotes_sybase.

PHP also understands arrays in the context of form variables (see the related faq). You may, for example,
group related variables together, or use this feature to retrieve values from a multiple select input. For
example, let's post a form to itself and upon submission display the data:

Example 12.11. More complex form variables

<?php
if ($_POST) {
echo '<pre>';
echo htmlspecialchars(print_r($_POST, true));
echo '</pre>';
}
?>
<form action="" method="post">
Name: <input type="text" name="personal[name]" /><br />
Email: <input type="text" name="personal[email]" /><br />
Beer: <br />
<select multiple name="beer[]">
<option value="warthog">Warthog</option>
<option value="guinness">Guinness</option>
<option value="stuttgarter">Stuttgarter Schwabenbru</option>
</select><br />
<input type="submit" value="submit me!" />
</form>

In PHP 3, the array form variable usage is limited to single-dimensional arrays. As of PHP 4, no such
restriction applies.

IMAGE SUBMIT variable names

When submitting a form, it is possible to use an image instead of the standard submit button with a tag like:

<input type="image" src="image.gif" name="sub" />

When the user clicks somewhere on the image, the accompanying form will be transmitted to the server
with two additional variables, sub_x and sub_y. These contain the coordinates of the user click within the
image. The experienced may note that the actual variable names sent by the browser contains a period
rather than an underscore, but PHP converts the period to an underscore automatically.

HTTP Cookies

PHP transparently supports HTTP cookies as defined by Netscape's Spec. Cookies are a mechanism for
storing data in the remote browser and thus tracking or identifying return users. You can set cookies using
the setcookie() function. Cookies are part of the HTTP header, so the SetCookie function must be called
before any output is sent to the browser. This is the same restriction as for the header() function. Cookie data
is then available in the appropriate cookie data arrays, such as $_COOKIE, $HTTP_COOKIE_VARS as well
as in $_REQUEST. See the setcookie() manual page for more details and examples.

If you wish to assign multiple values to a single cookie variable, you may assign it as an array. For example:

<?php
setcookie("MyCookie[foo]", 'Testing 1', time()+3600);
setcookie("MyCookie[bar]", 'Testing 2', time()+3600);
?>

That will create two separate cookies although MyCookie will now be a single array in your script. If you
want to set just one cookie with multiple values, consider using serialize() or explode() on the value first.

Note that a cookie will replace a previous cookie by the same name in your browser unless the path or
domain is different. So, for a shopping cart application you may want to keep a counter and pass this along.
i.e.

Example 12.12. A setcookie() example

<?php
if (isset($_COOKIE['count'])) {
$count = $_COOKIE['count'] + 1;
} else {
$count = 1;
}
setcookie('count', $count, time()+3600);
setcookie("Cart[$count]", $item, time()+3600);
?>

Dots in incoming variable names

Typically, PHP does not alter the names of variables when they are passed into a script. However, it should
be noted that the dot (period, full stop) is not a valid character in a PHP variable name. For the reason, look
at it: <?php
$varname.ext; /* invalid variable name */
?> Now, what the parser sees is a variable named $varname, followed by the string concatenation operator,
followed by the barestring (i.e. unquoted string which doesn't match any known key or reserved words) 'ext'.
Obviously, this doesn't have the intended result.
For this reason, it is important to note that PHP will automatically replace any dots in incoming
variable names with underscores.

Determining variable types

Because PHP determines the types of variables and converts them (generally) as needed, it is not always
obvious what type a given variable is at any one time. PHP includes several functions which find out what
type a variable is, such as: gettype(), is_array(), is_float(), is_int(), is_object(), and is_string(). See also the
chapter on Types.

PHP and HTML interact a lot: PHP can generate HTML, and HTML can pass information to PHP. Before
reading these faqs, it's important you learn how to retrieve variables from outside of PHP. The manual page
on this topic includes many examples as well. Pay close attention to what register_globals means to you too.

66.1. What encoding/decoding do I need when I pass a value through a form/URL?


66.2. I'm trying to use an <input type="image"> tag, but the $foo.x and $foo.y variables aren't available.
$_GET['foo.x'] isn't existing either. Where are they?
66.3. How do I create arrays in a HTML <form>?
66.4. How do I get all the results from a select multiple HTML tag?
66.5. How can I pass a variable from Javascript to PHP?

66.1. What encoding/decoding do I need when I pass a value through a form/URL?

There are several stages for which encoding is important. Assuming that you have a string $data, which
contains the string you want to pass on in a non-encoded way, these are the relevant stages:

HTML interpretation. In order to specify a random string, you must include it in double quotes, and
htmlspecialchars() the whole value.
URL: A URL consists of several parts. If you want your data to be interpreted as one item, you must
encode it with urlencode().

Example 66.1. A hidden HTML form element

<?php
echo "<input type='hidden' value='" . htmlspecialchars($data) . "' />\n";
?>
Note: It is wrong to urlencode() $data, because it's the browsers responsibility to urlencode() the data.
All popular browsers do that correctly. Note that this will happen regardless of the method (i.e., GET
or POST). You'll only notice this in case of GET request though, because POST requests are usually
hidden.

Example 66.2. Data to be edited by the user

<?php
echo "<textarea name='mydata'>\n";
echo htmlspecialchars($data)."\n";
echo "</textarea>";
?>

Note: The data is shown in the browser as intended, because the browser will interpret the HTML escaped
symbols.

Upon submitting, either via GET or POST, the data will be urlencoded by the browser for
transferring, and directly urldecoded by PHP. So in the end, you don't need to do any
urlencoding/urldecoding yourself, everything is handled automagically.

Example 66.3. In a URL

<?php
echo "<a href='" . htmlspecialchars("/nextpage.php?stage=23&data=" .
urlencode($data)) . "'>\n";
?>

Note: In fact you are faking a HTML GET request, therefore it's necessary to manually urlencode() the data.

Note: You need to htmlspecialchars() the whole URL, because the URL occurs as value of an HTML-
attribute. In this case, the browser will first un-htmlspecialchars() the value, and then pass the URL on. PHP
will understand the URL correctly, because you urlencoded() the data.

You'll notice that the & in the URL is replaced by &amp;. Although most browsers will recover if you forget
this, this isn't always possible. So even if your URL is not dynamic, you need to htmlspecialchars() the
URL.

66.2. I'm trying to use an <input type="image"> tag, but the $foo.x and $foo.y variables aren't
available. $_GET['foo.x'] isn't existing either. Where are they?

When submitting a form, it is possible to use an image instead of the standard submit button with a tag like:

<input type="image" src="image.gif" name="foo" />


When the user clicks somewhere on the image, the accompanying form will be transmitted to the
server with two additional variables: foo.x and foo.y.

Because foo.x and foo.y would make invalid variable names in PHP, they are automagically converted
to foo_x and foo_y. That is, the periods are replaced with underscores. So, you'd access these variables
like any other described within the section on retrieving variables from outside of PHP. For example,
$_GET['foo_x'].

Note: Spaces in request variable names are converted to underscores.

66.3. How do I create arrays in a HTML <form>?

To get your <form> result sent as an array to your PHP script you name the <input>, <select> or <textarea>
elements like this:

<input name="MyArray[]" />


<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyArray[]" />

Notice the square brackets after the variable name, that's what makes it an array. You can group the elements
into different arrays by assigning the same name to different elements:
<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyOtherArray[]" />
<input name="MyOtherArray[]" />

This produces two arrays, MyArray and MyOtherArray, that gets sent to the PHP script. It's also possible to
assign specific keys to your arrays:
<input name="AnotherArray[]" />
<input name="AnotherArray[]" />
<input name="AnotherArray[email]" />
<input name="AnotherArray[phone]" />

The AnotherArray array will now contain the keys 0, 1, email and phone.

Note: Specifying an arrays key is optional in HTML. If you do not specify the keys, the array gets filled in
the order the elements appear in the form. Our first example will contain keys 0, 1, 2 and 3.

See also Array Functions and Variables from outside PHP.


66.4. How do I get all the results from a select multiple HTML tag?

The select multiple tag in an HTML construct allows users to select multiple items from a list. These items
are then passed to the action handler for the form. The problem is that they are all passed with the same
widget name. I.e.

<select name="var" multiple="yes">

Each selected option will arrive at the action handler as:


var=option1
var=option2
var=option3

Each option will overwrite the contents of the previous $var variable. The solution is to use PHP's
"array from form element" feature. The following should be used:
<select name="var[]" multiple="yes">

This tells PHP to treat $var as an array and each assignment of a value to var[] adds an item to the array. The
first item becomes $var[0], the next $var[1], etc. The count() function can be used to determine how many
options were selected, and the sort() function can be used to sort the option array if necessary.

Note that if you are using JavaScript the [] on the element name might cause you problems when you try to
refer to the element by name. Use it's numerical form element ID instead, or enclose the variable name in
single quotes and use that as the index to the elements array, for example:

variable = documents.forms[0].elements['var[]'];

HTTP GET variables: $_GET

Note: Introduced in 4.1.0. In earlier versions, use $HTTP_GET_VARS.

An associative array of variables passed to the current script via the HTTP GET method. Automatically
global in any scope.

This is a 'superglobal', or automatic global, variable. This simply means that it is available in all scopes
throughout a script. You don't need to do a global $_GET; to access it within functions or methods, as you
do with $HTTP_GET_VARS.
$HTTP_GET_VARS contains the same initial information, but is not a superglobal. (Note that
$HTTP_GET_VARS and $_GET are different variables and that PHP handles them as such)

If the register_globals directive is set, then these variables will also be made available in the global scope of
the script; i.e., separate from the $_GET and $HTTP_GET_VARS arrays. For related information, see the
security chapter titled Using Register Globals. These individual globals are not superglobals.

HTTP POST variables: $_POST

Note: Introduced in 4.1.0. In earlier versions, use $HTTP_POST_VARS.

An associative array of variables passed to the current script via the HTTP POST method. Automatically
global in any scope.

This is a 'superglobal', or automatic global, variable. This simply means that it is available in all scopes
throughout a script. You don't need to do a global $_POST; to access it within functions or methods, as you
do with $HTTP_POST_VARS.

$HTTP_POST_VARS contains the same initial information, but is not a superglobal. (Note that
$HTTP_POST_VARS and $_POST are different variables and that PHP handles them as such)

If the register_globals directive is set, then these variables will also be made available in the global scope of
the script; i.e., separate from the $_POST and $HTTP_POST_VARS arrays. For related information, see the
security chapter titled Using Register Globals. These individual globals are not superglobals.

HTTP File upload variables: $_FILES

Note: Introduced in 4.1.0. In earlier versions, use $HTTP_POST_FILES.

An associative array of items uploaded to the current script via the HTTP POST method. Automatically
global in any scope.

This is a 'superglobal', or automatic global, variable. This simply means that it is available in all scopes
throughout a script. You don't need to do a global $_FILES; to access it within functions or methods, as
you do with $HTTP_POST_FILES.

$HTTP_POST_FILES contains the same information, but is not a superglobal. (Note that
$HTTP_POST_FILES and $_FILES are different variables and that PHP handles them as such)

If the register_globals directive is set, then these variables will also be made available in the global scope of
the script; i.e., separate from the $_FILES and $HTTP_POST_FILES arrays. For related information, see the
security chapter titled Using Register Globals. These individual globals are not superglobals.

Request variables: $_REQUEST

Note: Introduced in 4.1.0. There is no equivalent array in earlier versions.


Note: Prior to PHP 4.3.0, $_FILES information was also included in $_REQUEST.

An associative array consisting of the contents of $_GET, $_POST, and $_COOKIE.

This is a 'superglobal', or automatic global, variable. This simply means that it is available in all scopes
throughout a script. You don't need to do a global $_REQUEST; to access it within functions or methods.

If the register_globals directive is set, then these variables will also be made available in the global scope of
the script; i.e., separate from the $_REQUEST array. For related information, see the security chapter titled
Using Register Globals. These individual globals are not superglobals.

Handling file uploads


Table of Contents
POST method uploads
Error Messages Explained
Common Pitfalls
Uploading multiple files
PUT method support

POST method uploads


This feature lets people upload both text and binary files. With PHP's authentication and file manipulation
functions, you have full control over who is allowed to upload and what is to be done with the file once it
has been uploaded.

PHP is capable of receiving file uploads from any RFC-1867 compliant browser (which includes Netscape
Navigator 3 or later, Microsoft Internet Explorer 3 with a patch from Microsoft, or later without a patch).

Related Configurations Note: See also the file_uploads, upload_max_filesize, upload_tmp_dir,


post_max_size and max_input_time directives in php.ini

PHP also supports PUT-method file uploads as used by Netscape Composer and W3C's Amaya clients. See
the PUT Method Support for more details.

Example 39.1. File Upload Form

A file upload screen can be built by creating a special form which looks something like this:

<!-- The data encoding type, enctype, MUST be specified as below -->
<form enctype="multipart/form-data" action="__URL__" method="POST">
<!-- MAX_FILE_SIZE must precede the file input field -->
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
<!-- Name of input element determines name in $_FILES array -->
Send this file: <input name="userfile" type="file" />
<input type="submit" value="Send File" />
</form>

The __URL__ in the above example should be replaced, and point to a PHP file.

The MAX_FILE_SIZE hidden field (measured in bytes) must precede the file input field, and its value
is the maximum filesize accepted by PHP. Fooling this setting on the browser side is quite easy, so never
rely on files with a greater size being blocked by this feature. The PHP settings for maximum-size, however,
cannot be fooled. This form element should always be used as it saves users the trouble of waiting for a big
file being transferred only to find that it was too big and the transfer failed.

Note: Be sure your file upload form has attribute enctype="multipart/form-data" otherwise the file
upload will not work.

The global $_FILES exists as of PHP 4.1.0 (Use $HTTP_POST_FILES instead if using an earlier version).
These arrays will contain all the uploaded file information.

The contents of $_FILES from the example form is as follows. Note that this assumes the use of the file
upload name userfile, as used in the example script above. This can be any name.

$_FILES['userfile']['name']

The original name of the file on the client machine.

$_FILES['userfile']['type']

The mime type of the file, if the browser provided this information. An example would be
"image/gif". This mime type is however not checked on the PHP side and therefore don't take its
value for granted.

$_FILES['userfile']['size']

The size, in bytes, of the uploaded file.

$_FILES['userfile']['tmp_name']

The temporary filename of the file in which the uploaded file was stored on the server.

$_FILES['userfile']['error']
The error code associated with this file upload. This element was added in PHP 4.2.0

Files will, by default be stored in the server's default temporary directory, unless another location has been
given with the upload_tmp_dir directive in php.ini. The server's default directory can be changed by setting
the environment variable TMPDIR in the environment in which PHP runs. Setting it using putenv() from
within a PHP script will not work. This environment variable can also be used to make sure that other
operations are working on uploaded files, as well.

Example 39.2. Validating file uploads

See also the function entries for is_uploaded_file() and move_uploaded_file() for further information. The
following example will process the file upload that came from a form.

<?php
// In PHP versions earlier than 4.1.0, $HTTP_POST_FILES should be used instead
// of $_FILES.

$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);

echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "Possible file upload attack!\n";
}

echo 'Here is some more debugging info:';


print_r($_FILES);

print "</pre>";

?>

The PHP script which receives the uploaded file should implement whatever logic is necessary for
determining what should be done with the uploaded file. You can, for example, use the $_FILES['userfile']
['size'] variable to throw away any files that are either too small or too big. You could use the
$_FILES['userfile']['type'] variable to throw away any files that didn't match a certain type criteria, but use
this only as first of a series of checks, because this value is completely under the control of the client and not
checked on the PHP side. As of PHP 4.2.0, you could use $_FILES['userfile']['error'] and plan your logic
according to the error codes. Whatever the logic, you should either delete the file from the temporary
directory or move it elsewhere.

If no file is selected for upload in your form, PHP will return $_FILES['userfile']['size'] as 0, and
$_FILES['userfile']['tmp_name'] as none.

The file will be deleted from the temporary directory at the end of the request if it has not been moved
away or renamed.
Example 39.3. Uploading array of files

PHP supports HTML array feature even with files.

<form action="" method="post" enctype="multipart/form-data">


<p>Pictures:
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="submit" value="Send" />
</p>
</form>

<?php
foreach ($_FILES["pictures"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
$name = $_FILES["pictures"]["name"][$key];
move_uploaded_file($tmp_name, "data/$name");
}
}
?>

Error Messages Explained


Since PHP 4.2.0, PHP returns an appropriate error code along with the file array. The error code can be
found in the error segment of the file array that is created during the file upload by PHP. In other words, the
error might be found in $_FILES['userfile']['error'].

UPLOAD_ERR_OK

Value: 0; There is no error, the file uploaded with success.

UPLOAD_ERR_INI_SIZE

Value: 1; The uploaded file exceeds the upload_max_filesize directive in php.ini.

UPLOAD_ERR_FORM_SIZE

Value: 2; The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML
form.

UPLOAD_ERR_PARTIAL

Value: 3; The uploaded file was only partially uploaded.

UPLOAD_ERR_NO_FILE
Value: 4; No file was uploaded.

UPLOAD_ERR_NO_TMP_DIR

Value: 6; Missing a temporary folder. Introduced in PHP 4.3.10 and PHP 5.0.3.

UPLOAD_ERR_CANT_WRITE

Value: 7; Failed to write file to disk. Introduced in PHP 5.1.0.

UPLOAD_ERR_EXTENSION

Value: 8; File upload stopped by extension. Introduced in PHP 5.2.0.

Note: These became PHP constants in PHP 4.3.0.

Common Pitfalls
The MAX_FILE_SIZE item cannot specify a file size greater than the file size that has been set in the
upload_max_filesize ini-setting. The default is 2 Megabytes.

If a memory limit is enabled, a larger memory_limit may be needed. Make sure you set memory_limit large
enough.

If max_execution_time is set too small, script execution may be exceeded by the value. Make sure you set
max_execution_time large enough.

Note: max_execution_time only affects the execution time of the script itself. Any time spent on activity
that happens outside the execution of the script such as system calls using system(), the sleep() function,
database queries, time taken by the file upload process, etc. is not included when determining the maximum
time that the script has been running.

Warning

max_input_time sets the maximum time, in seconds, the script is allowed to receive input; this includes file
uploads. For large or multiple files, or users on slower connections, the default of 60 seconds may be
exceeded.

If post_max_size is set too small, large files cannot be uploaded. Make sure you set post_max_size large
enough.

Not validating which file you operate on may mean that users can access sensitive information in other
directories.
Please note that the CERN httpd seems to strip off everything starting at the first whitespace in the content-
type mime header it gets from the client. As long as this is the case, CERN httpd will not support the file
upload feature.

Due to the large amount of directory listing styles we cannot guarantee that files with exotic names (like
containing spaces) are handled properly.

A developer may not mix normal input fields and file upload fields in the same form variable (by using an
input name like foo[]).

Uploading multiple files


Multiple files can be uploaded using different name for input.

It is also possible to upload multiple files simultaneously and have the information organized automatically
in arrays for you. To do so, you need to use the same array submission syntax in the HTML form as you do
with multiple selects and checkboxes:

Note: Support for multiple file uploads was added in PHP 3.0.10.

Example 39.4. Uploading multiple files

<form action="file-upload.php" method="post" enctype="multipart/form-data">


Send these files:<br />
<input name="userfile[]" type="file" /><br />
<input name="userfile[]" type="file" /><br />
<input type="submit" value="Send files" />
</form>

When the above form is submitted, the arrays $_FILES['userfile'], $_FILES['userfile']['name'], and
$_FILES['userfile']['size'] will be initialized (as well as in $HTTP_POST_FILES for PHP versions prior to
4.1.0). When register_globals is on, globals for uploaded files are also initialized. Each of these will be a
numerically indexed array of the appropriate values for the submitted files.

For instance, assume that the filenames /home/test/review.html and /home/test/xwp.out are submitted. In this
case, $_FILES['userfile']['name'][0] would contain the value review.html, and $_FILES['userfile']['name']
[1] would contain the value xwp.out. Similarly, $_FILES['userfile']['size'][0] would contain review.html's
file size, and so forth.

$_FILES['userfile']['name'][0], $_FILES['userfile']['tmp_name'][0], $_FILES['userfile']['size'][0], and


$_FILES['userfile']['type'][0] are also set.

Anda mungkin juga menyukai