Web

Last updated Mar 24, 2024 Published Mar 20, 2018

The content here is under the Attribution 4.0 International (CC BY 4.0) license

PHP has always been very well recognized thanks to its web features, such as session, cookies, headers, among others, making its use very simple. In this chapter, we will cover how PHP interacts with these features and how we can use them.

Session

The HTTP protocol that we use for various operations on the web, such as browsing the internet or consuming APIs, is a stateless protocol (stateless), which means that it does not store any information between one request and another. However, in real-world applications, we can use this feature, where we store user information in session to be able to use it later.

This type of behavior is provided by programming languages and, in our case, PHP has some specific functions and configurations for this. For PHP to use a session, we need to use the session_start function in all our scripts. Only after declaring it will it be possible to define and retrieve values in the global variable $_SESSION.

session_start();

In our next example, we will share data across a session between two files: one called index.php and another called display.php.

//index.php

session_start();

$_SESSION['profile'] = 'User';

Now, in our other file exibir.php, we can retrieve this value:

// display.php

session_start();

print $_SESSION['profile']; //User

In addition to creating a session, we can also destroy it with the session_destroy function.

session_start();

session_destroy();

Always remember that working with sessions, even to destroy them, you need to use the session_start function before doing anything.

It is important to highlight that, to use session, we must be running a web application through a browser. Command line applications (CLI) do not have this feature, making their use unfeasible. This is one of the main differences between applications run by a web server and applications run on the command line.

php.ini

We have several configuration options for our PHP sessions. See below the beginning of the session settings in the php.ini file (starting with the characters [Session]). As there are many settings, we cannot see all the options in the image:

Session-oriented settings in php.ini {w=100%}

The first configuration we will look at is session.save_path, in which we can define the location where session data is stored.

session.save_path = "/foo/bar"

By default, this option is commented out, and PHP stores session files in the /tmp directory (on Linux distributions). But, if you want to change the path where the files are saved, just change this option. See below that we changed the location to /home/php/sessao.

session.save_path = "/home/php/sessao"

The second option we will highlight here is session.use_cookies, which makes PHP use cookies to store the id of the session. By default, this option comes with the value 1 (enabled), because when we disable this option, setting the value to 0 (zero), it is possible to view the id of the current session through the URL, as shown in our figure:

Accessing session data via URL {w=100%}

This becomes quite delicate, as anyone who has the id of your session will be able to access all of your content. Therefore, it is recommended that you always leave this option enabled (set to the value 1), so that you do not have any headaches with session theft or misuse.

Following the same language of reasoning, we have the option session.use_only_cookies, which actually forces PHP to only use cookies, ensuring that it is not possible to pass the id of the session through the URL. This makes our application much more reliable. This option comes with the value 1 (enabled) by default.

session.use_only_cookies = 1

The last option we highlight here is session.auto_start which, when enabled (that is, defined with the value 1, as in the following example), it is not necessary to use the session_start function. This is because, when we start our web server, the session will start automatically.

session.auto_start = 1

By default, this option is set to disabled (0).

The items shown here are fine adjustments to PHP to make the use of sessions safer and with greater control over what you are doing in your application. Remember that we do not provide all possible configuration options here. To go deeper, access the page dedicated just to session configurations in php.ini, at http://php.net/manual/session.configuration.php.

Forms

PHP is a language that was born focused on the web and has some interesting features for interacting with forms. In this topic, we will cover how to use forms and interact with different ways of retrieving data from them. For this, we will assume that you already have the necessary knowledge about HTML.

<!-- file: form.html -->

<form method="POST" action="data.php">
     Name
     <input type="text" name="name" value="Matheus Marabesi and Cia"/>

     Sex
     <input type="radio" value="female" name="sex"/>
     <input type="radio" value="male" name="sex"/>

     Activities
     <input type="checkbox" name="activities[]" value="swimming"/>Swimming
     <input type="checkbox" name="activities[]" value="basketball"/>Basketball
     <input type="checkbox" name="activities[]" value="football"/>Football

     Description
     <textarea name="description">Another item</textarea>
     <input type="submit" value="Submit"/>
</form>

The first thing to notice in our form is the form tag, where we indicate the type used to send the data to our PHP page, and the action attribute which indicates the page on which the data will be sent. form.

If no attribute is indicated in the form tag when submitting the form, the current file will be used to submit the data. And if no method attribute is provided or the value is invalid, the GET method will be assumed.

// data.php file

print_r($_POST);

When we submit our form to our PHP script without filling in any values, we have the following result:

Array
(
     [name] => Matheus Marabesi and Cia
     [description] => Another item
)

You might be wondering where the other values are? Because there are other fields besides the name and description, right? We have some special behaviors when it comes to elements like radio and checkbox. For data from these elements to be sent to the server-side PHP script, at least 1 (one) value must be selected.

So let’s change our form so that it sends this data to our script. We will only edit the radio and checkbox element part, and the rest of the HTML will remain the same.

Sex
<input type="radio" value="female" name="sex" checked/>
<input type="radio" value="male" name="sex"/>

Activities
<input type="checkbox" name="activities[]" value="swimming" checked/>Swimming
<input type="checkbox" name="activities[]" value="basketball"/>Basketball
<input type="checkbox" name="activities[]" value="football"/>Football

After this change, when we submit the form again, we obtain the following result:

Array
(
     [name] =>
     [sex] => female
     [activities] => Array
         (
             [0] => swimming
         )

     [description] =>
)

Now we have all the items that exist in the form on the server side, but we should note one thing: the activities field has become an array. This occurs because we use a different notation in the element name. Look:

<input type="checkbox" name="activities[]" value="swimming" checked/>Swimming
<input type="checkbox" name="activities[]" value="basketball"/>Basketball
<input type="checkbox" name="activities[]" value="football"/>Football

In the name attribute, at the end of its name, we put square brackets, indicating that more than one value can be sent for the same field. We can use this notation for other fields as well, such as text fields:

<form method="POST" action="data.php">
     Name
     <input type="text" name="nome[]" value="Matheus Marabesi"/>
     <input type="text" name="name[]" value="Cia"/>
</form>

And if we submit the form with just these elements, we have the following result:

Array
(
     [name] => Array
         (
             [0] => Matheus Marabesi
             [1] => Cia
         )
)

We can have this behavior for all existing fields in the form text, textare, radio, checkbox etc. Always remember that, when using the bracket notation at the end of the name attribute, it is possible to have multiple values and, on the server side, an array with these elements will be sent.

Naming fields

An important detail that we must pay attention to is the naming of the fields on our form. In PHP, when we use the names of elements in a form with a period (.) or spaces, they are converted to underscores (_).

In our example below, we created a form that will send your data via the POST method to the dados.php page. This form has two text fields, named username and email.do.usuario. Note that the first has white spaces, and the second has periods, which will make PHP replace these characters with underscores. See the code:

<form method="POST" action="data.php">
     Name
     <input type="text" name="username`" value="Matheus Marabesi and Michael Douglas"/>
    
     Email
     <input type="email" value="meu_email@meu_email.com.br" name="email.do.usuario"/>
    
     <input type="submit" value="Submit"/>
</form>

When we check the data sent to the PHP script on the server side, see the names of the fields that are sent:

Array
(
     [user_name] => Matheus Marabesi and Michael Douglas
     [user_email] => [email protected]
)

Fields with spaces or periods have been replaced by underscores. This will occur regardless of the method specified in the method attribute.

Valid values for the method attribute are POST and GET. For more information, see the official documentation made available by the W3C, at http://www.w3.org/TR/html5/forms.html#attr-fs-method.

Sending files

In certain applications, it will be necessary to send files to the server. For this to happen, we must make some changes to our form and enter some specific attributes.

<form method="POST" action="process_file.php" enctype="multipart/form-data">
     File
     <input type="file" name="file"/>
    
     <input type="submit" value="Submit"/>
</form>

Using the entype attribute is extremely important when using files in forms, because, without it in the form element, the file is not sent to the server and the global variable $_FILES that we use to retrieve the file’s data will be left empty. empty.

// file process_file.php

print_r($_FILES);

In our example, we are sending a PDF file and, through the global $_FILES, we can access the data sent to the server.

Array
(
     [file] => Array
         (
             [name] => php_e_tdd.pdf
             [type] => application/pdf
             [tmp_name] => /tmp/phppEyfB8
             [error] => 0
             [size] => 1823994
         )
)

And of course, if you need to send several files in a single form, it’s very simple, as we only need to use the array notation in the file element.

<form method="POST" action="process_file.php" enctype="multipart/form-data">
     File 1
     <input type="file" name="file[]"/>

     File 2
     <input type="file" name="file[]"/>

     <input type="submit" value="Submit"/>
</form>

We save our sent files in the same way, using the global variable $_FILES:

print_r($_FILES);

But notice that now for the items name, type, tmp_name, error and size, they are arrays with all the files sent to the server, each one with the data referring to the selected file.

Array
(
     [file] => Array
         (
             [name] => Array
                 (
                     [0] => php.pdf
                     [1] => cover.png
                 )

             [type] => Array
                 (
                     [0] => application/pdf
                     [1] => image/png
                 )

             [tmp_name] => Array
                 (
                     [0] => /tmp/phppEyfB8
                     [1] => /tmp/php5ByDMS
                 )

             [error] => Array
                 (
                     [0] => 0
                     [1] => 0
                 )

             [size] => Array
                 (
                     [0] => 2023604
                     [1] => 4974
                 )
         )
)

Sending files in detail

So far we have shown how we can use the combination of HTML through forms created server-side with PHP, where we use global variables to interact with what the user sends us. However, we did not go through the settings that we can manipulate through php.ini to make some fine adjustments to file sending, such as limiting the number of files sent per request, the size of the file sent, etc.

php.ini options to configure file upload {w=100%}

The first option we see is file_uploads, used to allow uploading files. This directive must have the value On to be able to send files. We must be careful when changing the value to Off, as this disables the sending of files and, when trying to send any file to PHP, the global variable $_FILES will always return an empty array.

Array ( )

The second option we have is upload_tmp_dir, which we use to define where PHP will keep the uploaded files until they are moved. We can see this path through the tmp_name key in the global variable $_FILES. In our example, all uploaded files are temporarily saved in the tmp folder.

Array
(
     [file] => Array
         (
             [name] => php_e_tdd.pdf
             [type] => application/pdf
             [tmp_name] => /tmp/phppEyfB8
             [error] => 0
             [size] => 1823994
         )
)

The third option we will look at is upload_max_filesize, which allows us to control the maximum size allowed to upload the file. See in the previous figure that this option has the value 2M (2 megabytes). If a file larger than 2MB is sent, PHP will set the error key of the global variable $_FILES to 1, which indicates that the size of the sent file is larger than allowed.

Array
(
     [file] => Array
         (
             [name] => file_greater_than_2mb.pdf
             [type] =>
             [tmp_name] =>
             [error] => 1
             [size] => 0
         )

)

All possible numbers that the error key can have can be found at http://php.net/manual/features.file-upload.errors.php.

Finally, we have the max_files_upload option, which limits the maximum number of possible files sent to PHP in a single request. In our case, we limit this number to 20. If we try to upload 21 files, a WARNING will be displayed:

Warning: Maximum number of allowable file uploads has been exceeded in Unknown on line 0

And the last file in the list will be removed, that is, only the first 20 files will actually be sent.

Cookies

We use cookies across the web to store data on the user’s machine instead of the server, so that we later have access to the saved information. Several websites nowadays use cookies in different ways: to store user preferences, access data, as well as storing the session identifier used in PHP. The cookie is what makes PHP able to create the session between the client and the server.

If you want to understand in depth what it is, how it works and what happens behind the HTTP protocol, see the official RFC about cookies at http://www.faqs.org/rfcs/rfc6265.html.

With a PHP application, we can also set our own cookies using the setcookie function. The most basic way to define a cookie is through its name and value:

setcookie('book', 'Another item');

But it is possible to set a cookie without any value, as the only mandatory value in the function used by PHP is its name:

setcookie('book');

This way, we have already defined a cookie that will be stored on the user’s machine. However, you need to pay attention to two very important details. The first is that the cookie will be set on the user’s machine in the first request, and it will only be possible to read the defined value in the next request to the server. The second is that if no expiration time is passed, the cookie will exist as long as the browser is open; if the user closes, the cookie is deleted.

Setting a cookie {w=100%}

See this figure. We run the PHP script to set the book cookie, but nothing is displayed in the list of active cookies in the browser.

Cookie set after page reload {w=100%}

After reloading the page, we can see our cookie with the value Another item. Note that the cookie value is escaped before being stored. Also note that the value in the Expires/Max-Age column is Session, which tells us that the cookie will be deleted as soon as the browser closes.

To access the value defined in the cookie, PHP provides us with a very easy way through the global variable $_COOKIE.

print_r($_COOKIE);

As the global variable $_COOKIE is an associative array, we obtain the following result:

Array
(
     [book] => Another item
)

This way, we will access all cookies defined for the domain, but it is also possible to access a specific cookie.

print_r($_COOKIE['book']); //Another item

Generally, cookies are used to last longer than just the current browser session. For this to happen, we must inform the third parameter to the setcookie function with the time we want the cookie to last. This time must be defined by seconds.

setcookie('book', 'Another item', time() + 86400);

Our cookie will now last for 2 days from the current day. This allows us to access it anywhere on our website. But, at some point, you may want to restrict the use of a cookie according to the domain you are on.

Imagine that we want to set a cookie to be used only when we access http://localhost/livro. To do this, we must use the fourth parameter of the sercookie function:

setcookie('book', 'Another item', time() + 172800, '/book');

HTTP headers

Nowadays, modern development abstracts a lot of things from us developers to become productive. One of these items are HTTP headers. Many frameworks abstract away all header manipulation, leaving us to worry about what matters. But we can manipulate the headers in our HTTP requests and responses natively.

Although it is a very laborious task (because every space counts, remember that we are working with HTTP and, in the end, everything will become text), PHP makes manipulating headers very simple through the header function .

For our first example, we will return JSON content to our client. To do this, we will use the Content-Type header, which informs the type of content being sent/received.

header('Content-Type: application/json');

For a complete list of headers used, visit https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers.

We can also chain together several headers to be sent by calling the header function several times. Note that, in addition to using Content-Type, we will use HTTP/1.0 200 OK to indicate that the request was accepted and the response was received successfully and without any errors.

header('HTTP/1.0 200 OK');
header('Content-Type: application/json');

When we access our script through a web server (we are using the server built into PHP), we can inspect the responses that the server sends us.

The built-in PHP server can be run and accessed in your terminal, with the command php -S localhost:8282. You can find a dedicated part especially for the built-in server that PHP has in http://php.net/manual/features.commandline.webserver.php.

Response from the web server according to the header we use {w=90%}

Now that we know how we can manipulate it, we can start sending different codes to see how the browser behaves. Let’s change it to status 500, which indicates that an internal error occurred on the server when processing the sent request.

header('HTTP/1.0 500 Record not found');
header('Content-Type: application/json');

We now change the status to 500, and also change the description to Record not found. Now, when we inspect the response, we see a red signal, indicating that an error has occurred internally on the server.

In reality, no error occurred, we just simulated this error to better understand how to manipulate HTTP headers.

Error 500 displayed when inspecting the response sent by the server {w=90%}

For applications run via the command line (CLI), functions that manipulate headers have no effect and are ignored during script execution. Like sessions, headers are one of the items available only to applications running through a web server, and not on a command line.

We saw in this section the extensive use of the header function. However, this function has two more types of arguments that we can use that we have not explored so far. The first in this list that we will look at is the argument that allows us to replace the sent header. It, by default, is set to true. Therefore, the header we send will always replace the previous one, and it does not allow us to define multiple values for the same header.

In our example, we will send a header with the name Token, simulating the authentication of a user using this token, and we will pass the value false so that PHP allows us to define multiple values for the same header.

header('Token: my_token');
header('Token: other_value', false);

The first thing we see is that the first call to the header function does not have the value false. In other words, in this first call we are guaranteeing that, if this header exists, it will be overwritten. Soon after, we make a new call to the header function, but this time, passing the false value as an argument. With this, we can send multiple values to a single header.

See the result we get when inspecting the response data from the request we made to our server:

Token Header with multiple values {w=100%}

Finally, we have the last argument passed to the header function. It allows us to force an HTTP response code. Let’s continue using our previous example with the Token header.

See that, in the previous figure, we received the code 200, which reports success in the request made to the server. However, let’s assume that the token entered is not valid and we need to report the status 401 (Unauthorized), which informs us that access is not permitted.

header('Invalid-Token: meu_token', true, 401);

This time, we will send a new header called Invalid-Token to inform the response that the token sent is not valid. Look:

Server response from unauthorized user {w=90%}

We advise you to access the official PHP manual to delve deeper into the subject, at http://php.net/manual/function.header.php.

Listing headers

So far, we have used the browser to see what headers were sent. However, we have another way to check if a header was sent: through the header_list function. This list is an array with all the headers that were sent to the web server. If we run this script, we would only have the X-Powered-By header information, which gives us some information about the operating system the web server is running on and what programming language it is using.

Array
(
     [0] => X-Powered-By: PHP/5.5.9-1ubuntu4.14
)

Let’s then add another header so that content can be rendered in XML using the header function:

header('Content-Type: text/xml');

print_r(headers_sent());

Now, we have two elements in our array: one with information about the environment where we are running PHP, and another about what type of content we are displaying.

Array
(
     [0] => X-Powered-By: PHP/5.5.9-1ubuntu4.14
     [1] => Content-Type: text/xml
)

Checking sent headers

PHP provides us with a way to check if some type of header has already been sent through the headers_sent function.

if (!headers_sent()) {
     header('Location: www.casadocodigo.com');
}

In this code, we just check if some type of header has already been sent to our web server. If not, what we do is redirect to the website www.casadocodigo.com.br through the Location header.

We can also check if the headers have already been sent to remove them using the header_remove function:

if (headers_sent()) {
     header_remove();
}

The header_remove function may or may not take a single argument, specifying which header we want to remove. In the previous code, since we didn’t specify any headers to be removed, PHP will simply remove them all.

But what if we don’t want them all removed? We simply specify which header we want to remove. First, we check if any headers were sent and then we remove only the Content-Type header.

if (headers_sent()) {
     header_remove('Content-Type');
}

you can get more information at http://php.net/manual/features.http-auth.php.

Summary

PHP is a language made for the web. So, you need to know the characteristics that this world has and also what functions it has to help you manipulate these functionalities. We also went further, presenting concepts about the web such as how to collect user data through forms, sending files and the difference between web applications and CLI applications (Command Line Interface). These are the minimum characteristics that web applications have and that you must master to take the test comfortably.

But PHP is a sea full of features that we can use. In addition to what was covered here, there is a section of the documentation with numerous functions that are used in the web environment: gethostname, http_response_code and header_register_callback are some that we can highlight. For a complete list of functions, access the official documentation..