Magyar zászlóMagyar

Practice 8 - PHP: Array Functions, Forms, and Validation

2025-04-10 4 min read GitHub

Introduction

This session continues from the PHP basics and covers two key topics:

  • Functional array operationsarray_filter, array_map, and the three ways to pass a callback
  • HTML forms with PHP — reading query parameters ($_GET), validating user input, and returning errors to the page

1. array_filter

array_filter keeps only the elements for which the callback returns true. The original array is not modified.

$numbers = [2, 3, -5, 6, 8];

$evens = array_filter($numbers, function ($x) {
    return $x % 2 == 0;
});
// $evens: [2, 6, 8]

JavaScript equivalent:

const evens = numbers.filter(x => x % 2 === 0);

Three ways to pass a callback

PHP gives you three syntaxes for callbacks, all equivalent in result:

1. Named function — define a function separately and pass its name as a string:

function isEven($x) {
    return $x % 2 == 0;
}

$evens = array_filter($numbers, "isEven");

2. Anonymous function — define it inline (same as JavaScript’s function expression):

$evens = array_filter($numbers, function ($x) {
    return $x % 2 == 0;
});

3. Arrow function (fn) — PHP 7.4+, like JavaScript’s arrow function, but the => body is a single expression:

$evens = array_filter($numbers, fn($x) => $x % 2 == 0);
💡

Arrow functions in PHP (fn($x) => expr) automatically capture variables from the surrounding scope — you do not need use. In a multi-line anonymous function you do need use (&$var) to access outer variables.

Task — filter negatives

$negatives = array_filter($numbers, function ($x) {
    return $x < 0;
});
// $negatives: [-5]

2. array_map

array_map transforms every element in the array and returns a new array of the same length.

$squared = array_map(fn($x) => $x * $x, $numbers);
// $squared: [4, 9, 25, 36, 64]

Note the argument order: the callback comes first, the array second (opposite to array_filter).

JavaScript equivalent:

const squared = numbers.map(x => x * x);
PHPJavaScript
array_filter($arr, $fn)arr.filter(fn)
array_map($fn, $arr)arr.map(fn)
ℹ️

array_filter with a non-consecutive result preserves the original numeric keys. If you need a re-indexed array starting at 0, wrap the result: array_values(array_filter(...)).


3. Built-in array functions

echo max($numbers);        // largest value: 8
echo array_sum($numbers);  // sum of all elements: 14
PHPJavaScript
max($arr)Math.max(...arr)
min($arr)Math.min(...arr)
array_sum($arr)arr.reduce((s, x) => s + x, 0)

4. == vs ===

PHP has the same two equality operators as JavaScript, and they behave the same way:

"1" == 1    // true  — loose equality, type coercion applied
"1" === 1   // false — strict equality, types must also match

=== checks that both the value and the type are identical. Always prefer === to avoid unexpected coercions.

OperatorNameType check
==Loose equalityNo
===Strict equalityYes
!=Loose not-equalNo
!==Strict not-equalYes

5. Variable interpolation inside HTML attributes

When you need a PHP variable inside an HTML attribute string, wrapping the variable in {...} makes the intent clear and is required when the variable is immediately followed by other characters:

for ($i = 8; $i < 20; $i++) {
    echo "<p style='font-size: {$i}px'>Hello world</p>";
}

Without braces $ipx would be parsed as a variable named $ipx (which does not exist). The braces delimit the variable name: {$i} means the value of $i, then the literal px.


6. HTML forms with PHP — task2.php

PHP and HTML can live in the same file. PHP blocks (<?php ... ?>) execute on the server; everything outside them is sent as-is to the browser.

A form that submits to itself:

<?php
// This block runs BEFORE the HTML is sent
$errors = [];

if ($_GET) {
    $a = $_GET["a"];
    $b = $_GET["b"];
    // ... validation ...
}
?>
<!DOCTYPE html>
<html lang="en">
<body>
    <form method="GET" action="task2.php">
        a = <input type="text" name="a" />
        <br>
        b = <input type="text" name="b" />
        <br>
        <button type="submit">Divide</button>
    </form>
</body>
</html>

method="GET" and the query string

When the form’s method is GET, the browser appends the field values to the URL:

http://127.0.0.1:8080/task2.php?a=8&b=2

The PHP superglobal $_GET is an associative array populated from those parameters:

$a = $_GET["a"];   // "8"
$b = $_GET["b"];   // "2"
ℹ️

$_GET is a superglobal — a built-in array that PHP populates automatically. $_POST works the same way for forms with method="POST". Use POST for forms that modify data; GET for read-only queries.


7. Constants — define

define('APPLE', 1);
echo APPLE;   // 1

Constants have no $ prefix and are conventionally written in ALL_CAPS. Unlike variables, they cannot be reassigned.


8. Input validation with filter_var

Never trust data that comes from the user. filter_var validates a value against a built-in filter:

if (filter_var($a, FILTER_VALIDATE_FLOAT) === false) {
    $errors["a"] = "a must be a number!";
}

FILTER_VALIDATE_FLOAT returns the validated value on success, or false on failure. Using === false (strict) is important — a value of 0 would be falsy with ==.

Common filters:

Filter constantValidates
FILTER_VALIDATE_FLOATDecimal number
FILTER_VALIDATE_INTInteger
FILTER_VALIDATE_EMAILEmail address
FILTER_VALIDATE_URLURL

9. Collecting errors into an array

A clean pattern for multi-field form validation:

$errors = [];

if (filter_var($a, FILTER_VALIDATE_FLOAT) === false) {
    $errors["a"] = "a must be a number!";
}
if (filter_var($b, FILTER_VALIDATE_FLOAT) === false) {
    $errors["b"] = "b must be a number!";
}
if ($b == 0) {
    $errors["b"] = "b cannot be 0!";
}

Output the result only when there are no errors:

if ($a && $b && count($errors) === 0) {
    echo "<p>" . ($a / $b) . "</p>";
}

10. The null coalescing operator ??

?? returns the left operand if it is set and not null, otherwise the right operand. It is the safe equivalent of an isset check:

<?= $errors["a"] ?? "" ?>

If $errors["a"] is not set (no validation error for field a), an empty string is output instead of a PHP notice.

JavaScript equivalent:

errors.a ?? ""
// or: errors.a !== undefined ? errors.a : ""

11. Short echo tag <?= ?>

<?= $value ?> is shorthand for <?php echo $value; ?>. Use it when you need to inject a single value into HTML:

<?= $errors["a"] ?? "" ?>

is exactly the same as:

<?php echo $errors["a"] ?? ""; ?>

Complete task files

task1.php

<?php

$numbers = [2, 3, -5, 6, 8];

// Filter even numbers — three callback styles
$evens = array_filter($numbers, function ($x) {
    return $x % 2 == 0;
});

function isEven($x) {
    return $x % 2 == 0;
}
$evens2 = array_filter($numbers, "isEven");
$evens3 = array_filter($numbers, fn($x) => $x % 2 == 0);

echo "<pre>"; print_r($evens); echo "</pre>";

// == vs ===
if ("1" == 1) {
    echo "Two equal is true<br />";
}
if ("1" === 1) {
    echo "True";
} else {
    echo "False, because I've used 3 =<br />";
}

// Filter negatives
$negatives = array_filter($numbers, function ($x) {
    return $x < 0;
});
echo "<pre>"; print_r($negatives); echo "</pre>";

// Square all numbers
$squared = array_map(fn($x) => $x * $x, $numbers);
echo "<pre>"; print_r($squared); echo "</pre>";

// Max and sum
echo "Max: " . max($numbers) . "<br>";
echo "Sum: " . array_sum($numbers) . "<br>";

// Hello world with increasing font size
for ($i = 8; $i < 20; $i++) {
    echo "<p style='font-size: {$i}px'>Hello world</p>";
}

?>

task2.php

<?php
define('APPLE', 1);

$errors = [];
if ($_GET) {
    $a = $_GET["a"];
    $b = $_GET["b"];

    if (filter_var($a, FILTER_VALIDATE_FLOAT) === false) {
        $errors["a"] = "a must be a number!";
    }
    if (filter_var($b, FILTER_VALIDATE_FLOAT) === false) {
        $errors["b"] = "b must be a number!";
    }
    if ($b == 0) {
        $errors["b"] = "b cannot be 0!";
    }
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form method="GET" action="task2.php">
        a = <input type="text" name="a" />
        <?= $errors["a"] ?? "" ?>
        <br>
        b = <input type="text" name="b" />
        <?php echo $errors["b"] ?? "" ?>
        <br>
        <button type="submit">Divide</button>
    </form>

    <?php
    if ($a && $b && count($errors) === 0) {
        echo "<p>" . $a / $b . "</p>";
    }
    ?>
</body>
</html>

Summary

ConceptPHP
Filter arrayarray_filter($arr, $fn)
Map arrayarray_map($fn, $arr)
Named callbackarray_filter($arr, "functionName")
Anonymous callbackarray_filter($arr, function($x) { ... })
Arrow functionfn($x) => expression
Largest valuemax($arr)
Sum of valuesarray_sum($arr)
Loose equality== — value only
Strict equality=== — value and type
Variable in HTML attribute"{$var}px"
Define a constantdefine('NAME', value)
Read GET param$_GET["name"]
Validate inputfilter_var($v, FILTER_VALIDATE_FLOAT)
Short echo tag<?= $value ?>
Null coalescing$x ?? "default"
Form method GETAppends values to URL as ?a=1&b=2