Syntax
Read PHP tags, dollar-prefixed variables and statements.
CodeBhavyaTurn validated form strings into clear calculations and escaped HTML output.
Level 20 traced requests through a backend. PHP provides a concrete language for writing that side of an application. This lesson introduces its syntax, values, arrays, functions and form-processing boundaries, then follows a small study-plan quote from submitted strings to escaped HTML output.
Write clear PHP blocks, distinguish strings from accepted numbers, validate a form independently of browser controls and explain what PHP sends back to a browser. The interactive lab demonstrates a fixed algorithm in JavaScript; the matching PHP source can run separately in a PHP-enabled environment.
Read PHP tags, dollar-prefixed variables and statements.
Use strings, numbers, booleans and arrays deliberately.
Check external field shape and type before conversion.
Escape data for the intended HTML context.
A PHP interpreter evaluates PHP source. In a web application, the runtime handles a request and produces output such as HTML or JSON. The browser receives the response; it does not execute the server’s PHP source as browser JavaScript.
Saving a file with a .php extension is not enough. A host must be configured to execute PHP, or a separate backend must provide it. Uploading a PHP file into a static frontend folder does not add that runtime. Keep source and private configuration from being served as public text.
For learning, PHP also has a command-line interface. You can run a script directly, check its syntax and use the built-in development server. That development server is intended for local development, not as a public production hosting solution.
php -v
php -l study-plan.php
php tests.php
php -S 127.0.0.1:8000
# Run these in the folder containing the example files.With PHP installed, open http://127.0.0.1:8000/study-plan.php after starting the local server. The downloadable patch contains the example separately from the website upload files. It does not require changing your existing frontend hosting.
The standard opening tag is <?php. PHP statements commonly end with a semicolon, while braces delimit blocks such as functions and conditionals. Comments explain a decision without becoming output.
A PHP file can contain HTML outside PHP blocks, which the runtime sends as output. A file containing only PHP commonly omits the closing tag to avoid accidental trailing output. Headers must be sent before response body output.
Use full opening tags rather than relying on a short-tag configuration. In the examples, the opening tag, variable assignments and echo statements belong to PHP source; the values emitted by echo belong to the response.
<?php
// A complete CLI greeting script.
$course = "PHP";
echo "Learning " . $course . "
";
// No closing tag is needed in this PHP-only file.Do not confuse a syntax error with a failed form validation. The interpreter must first understand the program. A missing semicolon or unmatched brace can prevent the intended handler from running at all.
PHP variables begin with a dollar sign. Names are case-sensitive, so $course and $Course are different variables. An ordinary assignment stores a value; types include integers, floating-point values, strings, booleans, arrays and null.
The strict comparison operators === and !== consider type as well as value. Form values arrive as strings in the ordinary scalar form case, so the string "2" is not the same typed value as the integer 2. Validate the submitted representation before converting it.
Declare(strict_types=1) affects scalar type declarations at call boundaries; it does not automatically validate HTTP input or change every operator into a strict operator. A cast can produce a number from an unacceptable string, so casting alone is not the form contract.
<?php
$submitted = "2";
var_dump($submitted === 2); // false
$acceptedDays = (int) $submitted; // after validation
var_dump($acceptedDays === 2); // true
$enabled = true;
$missing = null;Use strict comparisons where type matters. Avoid depending on loose equality to decide whether an external field is valid, and do not use a successful cast as proof that the original input was acceptable.
PHP uses the dot operator for string concatenation. Echo emits output, while returning a value from a function makes it available to its caller. A function can calculate a value without immediately sending anything to the browser.
Double-quoted strings can interpolate variables; single-quoted strings have more limited interpretation. Choose whichever makes the intended text clear. The plus operator is for arithmetic, not PHP string concatenation.
A PHP string is a sequence of bytes. Strlen measures bytes, not a universal count of visible letters. Our form example uses a UTF-8 regular expression to bound Unicode code points and rejects ASCII control characters; it does not claim to count user-perceived grapheme clusters.
<?php
$topic = "Forms";
echo "Study " . $topic;
echo "
Topic: $topic
";
echo 'Literal variable name: $topic';In a web page, raw echo of untrusted text can create HTML markup. Calculating a correct string and inserting it into the correct output context are separate responsibilities. The escaping section shows how this lesson handles HTML text.
Arithmetic operators include +, -, *, / and %. Conditions use comparisons and logical operators. Keep a calculation’s units clear: duration in days, unit price in paise and total price in paise are different values.
Our fictional quote uses integer paise: HTML 12550, CSS 15000 and PHP 18000 per day. Days is an accepted integer from 1 to 5. Multiplication produces totalPaise; integer division and a two-digit remainder format the displayed rupees.
This bounded exercise avoids introducing a floating-point rounding decision into the price calculation. It is not a payment system or a general tax, currency-conversion or financial rounding engine.
<?php
$unitPaise = 12550;
$days = 2;
$totalPaise = $unitPaise * $days; // 25100
$totalINR = (string) intdiv($totalPaise, 100) . "." .
str_pad((string) ($totalPaise % 100), 2, "0", STR_PAD_LEFT);
echo $totalINR; // 251.00Check the accepted bounds before calculation. If your application later supports arbitrary prices or very large quantities, review integer range, input rules and formatting again instead of assuming this small contract covers every case.
If/elseif/else selects a branch. An early return can stop a handler after a rejected method or invalid input. That makes it easier to see why a failure never reaches the calculation.
For and foreach repeat work. Foreach is convenient for traversing an array of course records or a list of validation errors. Keep output escaping inside the rendering step rather than assuming array values are safe.
The PHP example gathers independent name, course and day errors after confirming that all three fields are scalar strings. A missing or array-valued field is rejected earlier because later string functions should not be called on it.
<?php
$errors = ["Choose a course", "Choose 1-5 days"];
foreach ($errors as $error) {
echo htmlspecialchars($error, ENT_QUOTES | ENT_SUBSTITUTE, "UTF-8");
echo "
";
}
for ($day = 1; $day <= 5; $day++) {
echo $day . " ";
}A loop in a request handler completes its work for that request. It does not keep a browser form connected to a changing server variable after the response is finished. A later interaction requires another request or an explicitly implemented connection.
PHP arrays map keys to values and preserve order. An indexed collection can hold error messages; an associative array can hold named fields such as title and unitPaise. Nested arrays represent small records or tables.
The example course table uses fixed keys html, css and php. The submitted course must match one of those keys before its price is read. Do not create a new trusted course record from arbitrary client-supplied price data.
Array access and null coalescing help handle absent values, but a default does not prove input validity. Confirm whether a field exists and whether its value has the expected type before using it.
<?php
$courses = [
"html" => ["title" => "HTML", "unitPaise" => 12550],
"css" => ["title" => "CSS", "unitPaise" => 15000]
];
$selected = "html";
if (array_key_exists($selected, $courses)) {
echo $courses[$selected]["title"];
}Our exact form contract rejects extra fields. A browser-supplied role or price therefore does not silently become part of the accepted record. For a real application, document which fields are accepted and which are derived from server data.
A function can validate a record, calculate a result or escape text. Clear parameters and return values make the pieces easier to inspect and test. Keep a pure calculation separate from the code that sends headers or renders a page.
ProcessPlan in the example receives already decoded form fields, a method and a media type. It returns a structured result containing status, headers and a body. PlanHtml turns that accepted result into an escaped HTML fragment.
The dispatch block reads $_POST and $_SERVER, invokes the processor, sends response metadata and outputs a small page. CLI tests can call the processor without pretending that an HTTP request or browser session exists.
<?php
function totalPaise(int $unitPaise, int $days): int
{
return $unitPaise * $days;
}
$amount = totalPaise(12550, 2);
echo $amount; // 25100Type declarations improve the function interface; they do not replace the processor’s validation of external values. In the form flow, a string is converted to an integer only after its allowed spelling has been accepted.
Superglobals are predefined arrays available in different scopes. $_GET represents URL query input. $_POST normally contains decoded form data for URL-encoded or multipart POST bodies. $_SERVER provides request and execution information, including the request method in a web environment.
A JSON request body does not automatically become the same $_POST form array. A JSON handler would read the raw body through php://input, decode it and validate its own contract. This example deliberately accepts only application/x-www-form-urlencoded.
Scalar form controls usually produce strings, but bracketed field names can produce arrays. A crafted days[] input is not the expected scalar duration. The processor checks is_string before applying a regular expression or cast.
<?php
$method = $_SERVER["REQUEST_METHOD"] ?? "GET";
if ($method === "POST") {
$days = $_POST["days"] ?? null;
if (!is_string($days)) {
// Reject missing or array-valued input before conversion.
}
}The browser lab shows a simulated already decoded field object. It is not a PHP request parser and does not model duplicate parameter normalization or every possible field-name transformation. The separate PHP runtime handles actual form decoding.
The exact decoded record is learner, course and days. All three must be strings. Learner is trimmed with PHP’s default trim character set, then must contain 2–40 Unicode code points with no ASCII control characters. Course must be html, css or php. Days must be exactly one digit from 1 to 5.
Only learner is trimmed. Days "02", "+2", "2.0", "2e0" and " 2 " are rejected even if a cast could produce an integer. Once the representation is accepted, convert days to an integer and derive the price from the fixed course table.
Validation and normalization are deliberate application rules. This short learner label is a demonstration field, not a universal policy for personal names. Unicode code points and visible characters can differ when combining marks or joined emoji are used.
Exactly three scalar string fields.
Trim and check the documented text bound.
Known course and a single digit 1–5.
Convert accepted days and calculate trusted price.
Failed validation returns 400 without calculating a quote. GET returns a ready form; unsupported methods return 405 with Allow: GET, POST; an unsupported POST media type returns 415. A successful quote uses 200 because nothing is booked, paid or stored.
Htmlspecialchars encodes special HTML characters. The example explicitly uses ENT_QUOTES | ENT_SUBSTITUTE and UTF-8 when placing a learner label into HTML text. An accepted label such as Ada <b> should be displayed literally rather than creating a bold element.
Escaping does not establish that a value meets the input contract. Conversely, validating a name’s length does not make it safe to insert as HTML. Validate at the input boundary and encode for the output context.
HTML text escaping is not SQL protection, JavaScript string encoding or URL validation. Use parameterized queries for database values and the relevant rules for other destinations. The study-plan example has no database and never evaluates submitted PHP code.
<?php
$learner = "Ada <b>";
echo "<p>" . htmlspecialchars(
$learner, ENT_QUOTES | ENT_SUBSTITUTE, "UTF-8"
) . "</p>";
// Source: <p>Ada <b></p>
// Visible text: Ada <b>The browser lab displays both an escaped-source representation and a safe preview built with DOM text nodes. It does not insert user-provided HTML or execute PHP. Seeing the source and visible text together makes the encoding boundary easier to inspect.
A normal form submission encodes its successful controls, sends the selected method to the action URL and receives a response. PHP interprets the script on the server, reads the appropriate input arrays and produces the response.
Our example checks method and media type before the form record. It verifies shape and scalar types, validates fields, calculates the quote and renders escaped output. A rejected request stops before calculation; the response makes the failed stage visible.
PHP variables in this handler belong to the current execution. They do not create durable records between independent requests. Sessions or a database need their own design and lifecycle, as introduced in Level 20.
Submit learner, course and days.
Check the method and decoded fields.
Calculate from accepted values and a trusted table.
Escape values and send a deliberate response.
The lab demonstrates this fixed flow locally. The real PHP example receives an actual form when run in a configured PHP environment. Neither version collects a payment, makes a reservation or saves the submitted label.
Keep syntax errors, invalid submissions and operational failures separate. A syntax check helps catch malformed source. Validation responses help a learner correct an input. A deployed server needs private diagnostic logging and deliberate handling of unexpected failures.
Header calls and http_response_code belong before body output. A stray byte before the PHP opening tag or unexpected output from an included file can cause a headers-already-sent problem. Separating processing from output helps keep this order clear.
Browser restrictions, request-size limits and runtime configuration still matter. A production handler should bound request bytes before parsing, use an appropriate session and permission design for protected operations, and keep secrets out of public frontend files.
Check the PHP file before exercising the form.
Return a useful failure without inventing a quote.
Set response metadata before writing the body.
Verify PHP behavior in its actual environment.
The demonstration quote does not change server data and is not an authentication system. It intentionally leaves persistence, payments and protected application actions for separately implemented features.
Save the following complete source as study-plan.php in a local PHP example folder. It includes reusable processing/rendering functions and a web dispatch block. The supplied tests.php calls those functions from the command line; PHP CLI execution skips the web output block.
Run php -l study-plan.php and php tests.php, then start php -S 127.0.0.1:8000 in that folder and open /study-plan.php. The example belongs in a PHP-enabled environment; keep it separate from the frontend upload patch.
The code is supplied for inspection and local execution. The browser exercise below is a JavaScript demonstration of its documented algorithm, not a general PHP interpreter.
<?php
declare(strict_types=1);
function planEscape(string $text): string
{
return htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
function processPlan(array $post, string $method, string $mediaType): array
{
$headers = ['Content-Type' => 'text/html; charset=UTF-8'];
if ($method === 'GET') {
return ['status' => 200, 'headers' => $headers,
'body' => ['message' => 'Form ready. Submit a fictional study plan.']];
}
if ($method !== 'POST') {
$headers['Allow'] = 'GET, POST';
return ['status' => 405, 'headers' => $headers,
'body' => ['message' => 'Only GET and POST are supported.']];
}
$media = strtolower(trim(explode(';', $mediaType)[0]));
if ($media !== 'application/x-www-form-urlencoded') {
return ['status' => 415, 'headers' => $headers,
'body' => ['message' => 'This example accepts URL-encoded form data.']];
}
$keys = array_keys($post);
sort($keys);
if ($keys !== ['course', 'days', 'learner']) {
return ['status' => 400, 'headers' => $headers,
'body' => ['message' => 'Expected exactly learner, course and days.']];
}
foreach (['learner', 'course', 'days'] as $key) {
if (!is_string($post[$key])) {
return ['status' => 400, 'headers' => $headers,
'body' => ['message' => 'Each submitted field must be a string.']];
}
}
$learner = trim($post['learner']);
$errors = [];
if (preg_match('/\A.{2,40}\z/u', $learner) !== 1 ||
preg_match('/[\x00-\x1F\x7F]/', $learner) === 1) {
$errors[] = 'Learner must contain 2-40 Unicode code points after trim, with no ASCII control characters.';
}
$courses = [
'html' => ['title' => 'HTML', 'unitPaise' => 12550],
'css' => ['title' => 'CSS', 'unitPaise' => 15000],
'php' => ['title' => 'PHP', 'unitPaise' => 18000]
];
if (!array_key_exists($post['course'], $courses)) {
$errors[] = 'Course must be html, css or php.';
}
if (preg_match('/\A[1-5]\z/', $post['days']) !== 1) {
$errors[] = 'Days must be exactly one digit from 1 to 5.';
}
if ($errors !== []) {
return ['status' => 400, 'headers' => $headers,
'body' => ['message' => 'Form validation failed.', 'errors' => $errors]];
}
$days = (int) $post['days'];
$course = $courses[$post['course']];
$totalPaise = $course['unitPaise'] * $days;
$totalINR = (string) intdiv($totalPaise, 100) . '.' .
str_pad((string) ($totalPaise % 100), 2, '0', STR_PAD_LEFT);
return ['status' => 200, 'headers' => $headers, 'body' => [
'message' => 'Study quote calculated; nothing was booked or saved.',
'accepted' => ['learner' => $learner, 'course' => $course['title'],
'days' => $days, 'unitPaise' => $course['unitPaise'],
'totalPaise' => $totalPaise, 'totalINR' => $totalINR]
]];
}
function planHtml(array $result): string
{
$body = $result['body'];
if (!isset($body['accepted'])) {
$html = '<p>' . planEscape($body['message']) . '</p>';
foreach ($body['errors'] ?? [] as $error) {
$html .= '<p>' . planEscape($error) . '</p>';
}
return $html;
}
$plan = $body['accepted'];
return '<h2>Study quote</h2><p>Learner: ' . planEscape($plan['learner']) .
'</p><p>Course: ' . planEscape($plan['course']) .
'</p><p>Days: ' . (string) $plan['days'] .
'</p><p>Total: INR ' . planEscape($plan['totalINR']) . '</p>';
}
// PHP's CLI web server reports "cli-server" here; CLI tests report "cli".
if (PHP_SAPI !== 'cli') {
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$media = $_SERVER['CONTENT_TYPE'] ?? '';
$result = processPlan($_POST, $method, $media);
http_response_code($result['status']);
foreach ($result['headers'] as $name => $value) {
header($name . ': ' . $value);
}
echo '<!doctype html><html lang="en"><meta charset="UTF-8">';
echo '<meta name="viewport" content="width=device-width, initial-scale=1">';
echo '<title>PHP study-plan example</title><body><h1>Study-plan form</h1>';
echo '<p>Learning example only. No payment, reservation or storage.</p>';
echo planHtml($result);
echo '<form action="study-plan.php" method="post">';
echo '<p><label>Learner <input name="learner" required></label></p>';
echo '<p><label>Course <select name="course"><option value="html">HTML</option>';
echo '<option value="css">CSS</option><option value="php">PHP</option></select></label></p>';
echo '<p><label>Days <select name="days">';
for ($day = 1; $day <= 5; $day++) {
echo '<option value="' . $day . '">' . $day . '</option>';
}
echo '</select></label></p><button type="submit">Calculate quote</button></form>';
echo '</body></html>';
}Follow a fixed successful study plan through receiving strings, validation, conversion, calculation and escaped output. The five-stage visualizer keeps the approved controls and styling. This is a teaching trace rather than live PHP execution.
An ordinary URL-encoded POST supplies scalar strings.
$_POST = ["learner" => "Ada", "course" => "html", "days" => "2"]PHP form input is external data. Check method, media type, exact fields and scalar types.
This browser lab is implemented in JavaScript and mirrors the documented form algorithm. It does not execute arbitrary PHP, send a request or save a learner label. The complete PHP source above can be run separately in a PHP environment.
The initial plan is Ada, HTML and the submitted string "2". A valid quote is INR 251.00. HTML costs 12550 paise per day, CSS 15000 and PHP 18000. Days must be exactly one digit 1–5; learner is trimmed and checked as described above.
Inspect the simulated decoded form input, stage trace, normalized result and escaped HTML source. The safe preview uses text nodes. Try a missing field, array-valued duration or an extra client price: each must reject before calculation. GET displays a ready message and ignores the form fields.
Use a fictional short label. Try "02", "2.0", "2e0" or a space around "2" to observe rejected representations.
Idle. JavaScript demonstration; PHP is not running in this page.
No input processed.No trace yet.No result yet.No generated source yet.No preview yet.
PHP source needs PHP execution; a static file upload is not enough.
Check a missing field or array value before calling string functions.
Validate the original days string before a cast.
Escape for HTML text and keep response headers before the body.
If JSON data appears absent from $_POST, inspect the request media type and the handler’s parsing contract. If days[] produces a type problem, reject non-string values before applying trim, regular expressions or integer conversion.
If a label appears as markup, inspect the rendering boundary. The HTML source should contain entities while the visible preview should contain the original literal text. If the quote changes after adding a price field, the handler is trusting a field outside its contract.
Use the local PHP syntax check and supplied test script before trying the real form. JavaScript tests of the browser demonstration cannot prove that a PHP runtime, its input decoding or headers behave correctly.
No. A supported PHP runtime executes the server source and sends a response to the browser.
It concatenates strings. The plus operator is arithmetic rather than PHP string concatenation.
No. It concerns scalar type declarations at call boundaries; external fields still need explicit shape, type and value checks.
It produces an array-shaped value rather than the required scalar string. String validation and conversion should not run on it.
The example accepts exactly one digit from 1 to 5. Conversion happens only after that representation passes validation.
No. The normal $_POST form parsing covers URL-encoded or multipart form input; a JSON handler needs a separate raw-body decoding contract.
Validation checks application meaning. Escaping prepares accepted data for a particular output context, such as HTML text.
It is a successful calculation and display. No booking, payment or persistent resource is created.
Process Ada/HTML/"2". Expected: 200, numeric days 2, totalPaise 25100 and totalINR "251.00".
Choose PHP/"5". Expected: 200 and INR 900.00 from the trusted price.
Try "02", "2.0", "+2", "2e0", " 2 " and "6". Expected: 400, no accepted quote.
Try missing days, array-valued days and extra price. Expected: 400 before calculation.
Try a one-code-point label or 41 code points. Expected: 400; a trimmed two-code-point label can pass.
Use Ada <b> as learner. Expected: accepted literal text; source contains <b> and preview has no injected bold node.
GET ignores submitted fields and returns ready 200. PUT gives 405; POST with JSON media type gives 415.
Run php -l study-plan.php, php tests.php, then the local PHP form. Expected: independently check syntax, algorithm and real request decoding.
The environment that interprets and executes PHP source.
A predefined PHP variable available across scopes, such as $_POST.
A single string value expected from an ordinary form control, rather than an array.
A PHP array using named keys to organize values.
Combining strings using the PHP dot operator.
A comparison that includes value and type, such as ===.
A deliberate conversion of already accepted input into an application representation.
Preparing data for a particular destination context, such as HTML text.
A Unicode value; it is not always the same as one visible character.
Reading request information, invoking processing and sending a response.
Run the supplied study-plan.php in a local PHP environment. Keep the exact scalar field contract and trusted course table. Validate method, media type, shape and values before converting days or calculating a quote. Escape the accepted learner label when generating HTML text.
Reproduce the valid quote, invalid days spellings, wrong-shaped fields and literal markup case. Compare the browser demonstration with PHP execution without assuming that one test proves the other runtime. Add real-request checks for GET, POST and an unsupported method.
Explain the differences between returned values and emitted output, scalar strings and integers, validation and escaping, and a calculated quote and a persistent booking. Keep the example separate from the static frontend deployment.
Success criterion: trace accepted external strings into a deliberate PHP response and explain each rejected boundary. Level 22 introduces Java Web Technologies.
Before marking complete, read the PHP example, explain one valid quote and reproduce type, shape, value and escaping outcomes in the demonstration. Run the separate PHP checks when a PHP environment is available. Completion remains a local study marker.