Learning Objectives – after this chapter you will be able to:
- Explain why HTTP is stateless and why web applications need state management.
- Distinguish client-side from server-side state management options.
- Create, read, update and delete cookies with
setcookie()and$_COOKIE. - Pass values between pages with query strings and read them safely.
- List the advantages and limitations of cookies and query strings.
Why State Management?
Web pages and PHP use the HTTP protocol to communicate between a web browser and a web server. HTTP is a stateless protocol: every request is independent, and the server cannot automatically tell whether successive requests come from the same client or from different clients.
For example, if you develop a web application that shows a personalised page after a user logs on, you must keep track of the user's activities while he or she moves from page to page. HTTP does not do this for you. In addition, a page is fetched again every time it is posted to the server, so the information on the page – for example a checkbox the user ticked – is lost in each round trip unless you preserve it.
To overcome this limitation, PHP provides different state management options, divided into two categories:
| Category | Options |
|---|---|
| Client-side | Cookies, query strings (and hidden form fields) |
| Server-side | Session state (Chapter 31), database support (Part IV) |
Client-side state management
Client-side options store information in the web page or on the client computer. They give better performance because the load on the server is lower. Their disadvantage is that only a limited amount of data can be stored, and the user can see and change it.
Server-side state management
Server-side options store information on the web server. They can manage application- and session-related information securely, but they use server resources.
Cookies
A cookie is a small piece of information stored on the client machine. A web server sends a cookie to the browser together with the page output; on every later request to the same site the browser sends the cookie back. Because HTTP is stateless, cookies are used to recognise each individual user who accesses a web page.
Cookies can be temporary or persistent:
- Temporary (session) cookies live in the browser's memory. When the browser is closed, all session cookies are lost.
- Persistent cookies have an expiry date and are saved as files by the browser on the client computer until they expire.
Cookies can store information about a client, a session or an application. When the browser requests a page, it sends the cookie along with the request; the server reads the cookie and extracts its value.
Setting cookies – setcookie()
setcookie(name, value, expire, path, domain, secure, httponly) setcookie(name, value, options_array) // PHP 7.3+, e.g. with "samesite"
| Parameter | Meaning |
|---|---|
| name | The name of the cookie. |
| value | The value of the cookie (stored on the client – never store secrets). |
| expire | The time the cookie expires, as a Unix timestamp, e.g. time() + 3600. 0 or omitted = session cookie. |
| path | The path on the server where the cookie is available (/ = the whole site). |
| domain | The (sub)domain that can read the cookie. |
| secure | true = send the cookie only over HTTPS. Default false. |
| httponly | true = JavaScript cannot read the cookie (protects against XSS). Default false. |
All arguments except name are optional. setcookie() must be called before any HTML output is sent, because cookies are part of the HTTP headers.
<?php
setcookie("cookie1", "ICT"); // session cookie
setcookie("cookie2", "Bhopal", time() + 3600); // expires in 1 hour
setcookie("theme", "dark", [
"expires" => time() + 30 * 24 * 3600, // 30 days
"path" => "/",
"httponly" => true,
"samesite" => "Lax",
]);
?>
<html><body>
Cookies have been sent to the browser.<br>
They will be available in $_COOKIE from the <b>next</b> request.<br>
Cookies in this request: <?= count($_COOKIE) ?>
</body></html>Cookies have been sent to the browser. They will be available in $_COOKIE from the next request. Cookies in this request: 0
cookie1has the value ICT. Because no expiry time is given, it expires when the browser is closed.cookie2has the value Bhopal and expires in one hour (3600 seconds).themeis a persistent cookie for 30 days, readable on the whole site and hidden from JavaScript.
Retrieving cookies – $_COOKIE
Cookies are retrieved through the $_COOKIE array (very old code used $HTTP_COOKIE_VARS, removed in PHP 5.4). Assuming the name of the cookie is cookie1, its value is $_COOKIE['cookie1'].
<?php
echo "cookie1 = " . ($_COOKIE['cookie1'] ?? "not set") . "<br>";
echo "cookie2 = " . ($_COOKIE['cookie2'] ?? "not set") . "<br>";
echo "theme = " . htmlspecialchars($_COOKIE['theme'] ?? "light") . "<br>";
echo "All cookies:<br>";
foreach ($_COOKIE as $name => $value) {
if ($name != "PHPSESSID") echo " $name => " . htmlspecialchars($value) . "<br>";
}
?>cookie1 = ICT cookie2 = Bhopal theme = dark All cookies: cookie1 => ICT cookie2 => Bhopal theme => dark
Deleting cookies
To delete a cookie, call setcookie() with the same name (and path) and an expiry time in the past:
<?php
setcookie("cookie2", "", time() - 3600); // expiry in the past → browser deletes it
echo "cookie2 has been deleted.";
?>cookie2 has been deleted.
cookie1 = ICT cookie2 = not set theme = dark All cookies: cookie1 => ICT theme => dark
Example – remembering a visitor
A cookie can remember the visitor's name and count the visits:
<?php
if (isset($_GET['name'])) {
setcookie("visitor", $_GET['name'], time() + 86400 * 365);
$name = $_GET['name'];
} else {
$name = $_COOKIE['visitor'] ?? null;
}
$count = (int) ($_COOKIE['visits'] ?? 0) + 1;
setcookie("visits", $count, time() + 86400 * 365);
?>
<html><body>
<?php if ($name): ?>
Welcome back, <?= htmlspecialchars($name) ?>! This is visit number <?= $count ?>.
<?php else: ?>
Welcome, new visitor! (Add ?name=YourName to the URL.)
<?php endif; ?>
</body></html>Welcome back, Asha! This is visit number 3.
Advantages of cookies
- A cookie is stored on the client computer and is read by the server when a page is requested, so no server resources are needed to maintain it.
- A cookie is a simple text-based key–value pair, so it is easy to create and manipulate.
- A cookie can expire when the browser session ends, or exist for a long time on the client computer, subject to the expiry rules.
Limitations of cookies
- Cookies have a limited size – most browsers allow about 4096 bytes per cookie – so you cannot store much data.
- Users can disable cookies; a web application then cannot store cookies on that computer.
- Users can see and tamper with cookies, because they are stored on the client computer. Never store passwords or trust a cookie value without checking it.
- Browsers limit the number of cookies per site.
Query Strings
If you need to send information to another page (or back to the same page) through a URL, you can use a query string. The query string is the part of the URL after the question mark (?). It provides a simple way to pass information from one page to another – for example, the selected product id, or a page number in a list.
page2.php?d1=23&d2=45
d1is the name of an argument and23its value.- Several arguments are separated with &.
- The argument lasts only for that request – the next page receives it, and it is gone when the user navigates elsewhere.
Query-string arguments are read with $_GET (or $_REQUEST). Special characters in values must be encoded with urlencode() or built with http_build_query().
<?php $product = "PHP & MySQL Book"; $url = "page2.php?id=23&qty=2&name=" . urlencode($product); $url2 = "page2.php?" . http_build_query(["id" => 45, "qty" => 1, "name" => "XAMPP Guide"]); ?> <html><body style="font-family:Arial;font-size:13px"> <a href="<?= htmlspecialchars($url) ?>" id="l1">Buy the PHP book</a><br> <a href="<?= htmlspecialchars($url2) ?>" id="l2">Buy the XAMPP guide</a><br> Link 1 points to: <?= htmlspecialchars($url) ?> </body></html>

Buy the PHP book Buy the XAMPP guide Link 1 points to: page2.php?id=23&qty=2&name=PHP+%26+MySQL+Book
<?php $id = filter_input(INPUT_GET, "id", FILTER_VALIDATE_INT); $qty = filter_input(INPUT_GET, "qty", FILTER_VALIDATE_INT); $name = $_GET["name"] ?? ""; echo "Query string received: " . htmlspecialchars($_SERVER["QUERY_STRING"]) . "<br>"; echo "Product id: $id<br>"; echo "Quantity: $qty<br>"; echo "Name: " . htmlspecialchars($name); ?>
Query string received: id=23&qty=2&name=PHP+%26+MySQL+Book Product id: 23 Quantity: 2 Name: PHP & MySQL Book
Notice that & in the product name was encoded as %26 – otherwise it would have started a new argument.
Advantages of query strings
- A query string is part of the HTTP request for a URL, so no server resources are needed to keep it.
- All browsers support passing values in a query string, so an application using query strings works everywhere.
- Pages with query strings can be bookmarked and shared.
Limitations of query strings
- The information is directly visible to the user in the address bar (and stored in browser history and server logs). Confidential information must never be sent this way.
- The user can change the values easily, so they must always be validated on the server.
- There is a limit to the length of a URL. Very old browsers allowed only 255 characters; modern browsers accept far more, but URLs longer than about 2000 characters should be avoided.
Hidden Form Fields
A third client-side technique is a hidden field in a form: <input type="hidden" name="step" value="2">. The value travels with the form's GET or POST request but is not displayed. Like a query string it can be seen in the page source and changed by the user, so it must be validated too.
Key Takeaways
- HTTP is stateless; state management keeps information across requests.
- Client-side: cookies, query strings, hidden fields. Server-side: sessions and databases.
setcookie(name, value, expire, path, domain, secure, httponly)must be called before output; values appear in$_COOKIEfrom the next request.- Delete a cookie by setting an expiry time in the past.
- Cookies: small (about 4 KB), can be disabled, visible and changeable by the user.
- Query strings (
page.php?a=1&b=2) are read with$_GET; encode values withurlencode()/http_build_query()and always validate them.
Program File
Extract the ZIP into C:\xampp\htdocs. It creates the folder phpbook/ch30 used in the file labels above; open the programs at http://localhost/phpbook/… with Apache (and MySQL, where needed) started in the XAMPP Control Panel.
Question / Answer (15 questions)
MCQ Test : Check Your Understanding (5 questions)
Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.
Bibliography/References
The notes on this page are the author’s own compilation from the e-book PHP: Basics to Advance. Every program was run on Apache with PHP 8 and MariaDB, and the output shown is the real result of that run. The works listed below were consulted and are cited for attribution and further reading. Product names and trademarks belong to their respective owners.
- The PHP Group. (n.d.). PHP Manual – setcookie. https://www.php.net/manual/en/function.setcookie.php
- The PHP Group. (n.d.). PHP Manual – $_COOKIE. https://www.php.net/manual/en/reserved.variables.cookies.php
- The PHP Group. (n.d.). PHP Manual – http_build_query. https://www.php.net/manual/en/function.http-build-query.php
- MDN contributors. (n.d.). Using HTTP cookies. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
- Barth, A. (2011). RFC 6265: HTTP State Management Mechanism. IETF. https://www.rfc-editor.org/rfc/rfc6265