Context engineering
Obiettivo del modulo. Fornire una conoscenza esaustiva della sintassi di base di PHP, del modello di variabili e tipi, delle costanti e degli operatori, con esempi pronti all’uso e un esercizio guidato (calcolo area e perimetro di un rettangolo) implementato in più varianti (script semplice, form web, CLI, versione “robusta” con validazione e test).
Struttura base di un file PHP
Tag PHP e integrazione HTML
Modalità di esecuzione (CLI / server integrato / server web)
Direttive utili per sviluppo (error reporting, display_errors)
Variabili: binding, naming, scope
Tipi di dato in PHP (primitivi e compound)
Type juggling, casting esplicito e declare(strict_types=1)
Costanti: const vs define()
Operatori (aritmetici, confronto, logici, stringa, bitwise, null coalescing, spaceship, ecc.)
Stringhe: concatenazione, interpolazione, heredoc/nowdoc
Superglobals e input (sicurezza e validazione)
Buone pratiche e anti-pattern
Esercizio completo: Area e perimetro del rettangolo — 4 versioni (snippet + spiegazioni)
Test, logging e error handling (sintesi)
Riferimenti e letture consigliate
Un file PHP è un file di testo con estensione .php che contiene codice PHP racchiuso tra tag di apertura e tag di chiusura. La struttura minima:
<?php// file: index.phpecho "Hello, World!";
Si possono mescolare HTML e PHP:
<!doctype html><html lang="it"><head><meta charset="utf-8"><title>PHP Demo</title></head><body> <h1><?php echo "Benvenuto"; ?></h1> <p>Ora sono in HTML</p></body></html>
Nota: preferire sempre <?php ... ?> per compatibilità. Il short-tag <? è deprecato/oscillante in alcune configurazioni; il short-echo <?= ... ?> è disponibile di default nelle versioni recenti di PHP ed è comodo per l’output rapido.
<?php ... ?> blocco PHP standard.
<?= expr ?> equivalente a <?php echo expr; ?>. Utile in template.
<? short tag (sconsigliato).
/* ... */ commento multi-linea, // e # commento single-line.
Esempio di template semplice (separazione logica/presentazione):
<?php$title = "Prodotti";$items = ["Pane", "Latte", "Uova"];?><!doctype html><html><head><meta charset="utf-8"><title><?= htmlspecialchars($title) ?></title></head><body> <h1><?= htmlspecialchars($title) ?></h1> <ul> <?php foreach ($items as $it): ?> <li><?= htmlspecialchars($it) ?></li> <?php endforeach; ?> </ul></body></html>
Usare htmlspecialchars() per prevenire XSS quando si visualizza input utente.
Server web (Apache / Nginx + PHP-FPM / mod_php): file serviti via http://localhost.
Server integrato (dev): php -S localhost:8000 -t public/ per test rapido (non per produzione).
CLI: php script.php per strumenti a riga di comando. In CLI sono disponibili $argc, $argv.
Esempio CLI:
php rect_cli.php 3.5 2.1
Dove rect_cli.php legge $argv[1] e $argv[2].
Nel file o in php.ini per sviluppo impostare:
ini_set('display_errors', '1');ini_set('display_startup_errors', '1');error_reporting(E_ALL);
In produzione disabilitare display_errors e loggare invece gli errori (error_log).
In PHP le variabili iniziano con $ e fanno binding dinamico all’oggetto:
$a = 5; // $a è un int$a = "ciao"; // ora è una stringa
Iniziano con $ seguito da lettera o underscore.
Sensibili a maiuscole/minuscole: $Var ≠ $var.
Evitare nomi di funzione o parole riservate.
Local (variabili dentro funzione), global (variabili file-scope), superglobals ($_GET, $_POST, $_SERVER, $_SESSION, $_COOKIE, $_FILES, $_ENV, $GLOBALS).
Per accedere a una variabile globale dentro una funzione usare $GLOBALS['name'] o global $name;.
static all’interno di una funzione mantiene valore tra invocazioni.
Esempi:
$x = 10;function foo() { global $x; echo $x; // stampa 10}function bar() { static $counter = 0; $counter++; echo $counter;}
Variabili variabili (es. $a = 'b'; $$a = 5; → crea $b = 5) — utile ma spesso fonte di confusione e rischi; evitarle o usarle con cautela.
int (integer), float (double), string, bool (boolean).
null rappresenta assenza di valore.
array (vettori e mappe associative), object (istanze di classi), resource (risorse esterne: handle DB, stream).
callable, iterable (PHP 7+), mixed (PHP 8.0+), e union types (PHP 8+) come int|float.
gettype($x), var_dump($x), print_r($x), is_int(), is_float(), is_numeric(), is_string(), is_array(), is_null().
Esempio:
$a = "123";var_dump($a); // string(3) "123"var_dump((int)$a); // int(123)is_numeric("12.3"); // true
declare(strict_types=1)PHP coerce automaticamente tipi quando necessario (type juggling), es.: '5' + 2 → 7. Questo può essere comodo ma anche fonte di bug.
Casting esplicito
$int = (int) '3.7'; // 3$float = (float) '3.7'; // 3.7$str = (string) 123; // "123"
<?phpdeclare(strict_types=1);function add(int $a, int $b): int { return $a + $b;}
Con strict_types attivo, la chiamata add('2','3') genera un TypeError; senza strict_types PHP tenterà coerzione.
Union types (PHP 8)
function foo(int|float $x): float { return (float)$x; }
const vs define()const NAME = value; — definizione a compile-time (dentro classi o global scope).
define('NAME', value); — definizione a runtime (case-sensitive per default).
Esempio:
const PI = 3.14159;define('APP_NAME', 'MiaApp');
Dal PHP 7 si possono usare const anche per array.
+ - * / % ** (potenza **).
=, +=, -=, *=, /=, .= (concatenazione assegnata).
== (valore), === (valore + tipo), !=, !==, <, >, <=, >=.
Operator <=> (spaceship) restituisce -1, 0, 1 — utile per sort comparators (PHP 7+).
and, or, xor, &&, ||, !. Nota: and/or hanno precedenza inferiore rispetto ad = — preferire && e || in espressioni complesse.
Concatenazione: . operator. Interpolazione nelle stringhe doppie ("valore $v").
$x = $_GET['p'] ?? 'default'; — ideale per recuperare valori con fallback.
$a ??= 'default';
Attenzione alla precedenza: es. false && true vs false and true e =. Usa parentesi per chiarezza.
Esempi:
$a = 5;$a += 3; // 8$s = "a" . "b"; // "ab"$val = $_GET['x'] ?? 10;
Doppie virgolette: interpreti variabili e sequenze (\n, \t).
Single quotes: letterale, migliore performance se non serve interpolation.
Heredoc: <<<EOT ... EOT; interpreta variabili.
Nowdoc: <<<'EOT' ... EOT; come single quote (no interpolation).
Esempi:
$name = "Luca";echo "Ciao $name\n"; // interpolationecho 'Ciao $name\n'; // literal$text = <<<HTML<p>Ciao $name</p>HTML;
$_GET, $_POST, $_REQUEST, $_COOKIE, $_FILES, $_SESSION, $_SERVER, $_ENV, $GLOBALS.
Non fidarsi mai di input utente. Usare filter_input() e filter_var().
Esempio:
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT);if ($age === false) { echo "Età non valida.";}
Per stringhe e output HTML usare htmlspecialchars($str, ENT_QUOTES, 'UTF-8').
Escape sempre output destinato all’HTML.
Per SQL usare prepared statements (PDO with prepared statements) per evitare SQL injection.
Per form sensibili, utilizzare token CSRF memorizzati in $_SESSION.
Consigli
Abilitare declare(strict_types=1) nei file di produzione per maggior robustezza (valutare trade-off con interoperabilità).
Separare logica e view (template engine: Twig, Blade, ecc.).
Usare PDO + prepared statements per DB.
Validare e sanificare sempre input.
Usare Composer per gestione dipendenze e PSR-12 per coding standard.
Anti-pattern
Non usare eval() su input utente.
Evitare extract() su $_REQUEST.
Evitare @ operator per silenziare errori: nasconde problemi.
Non scrivere HTML con echo concatenati estensivamente — preferire template.
Presenteremo 4 versioni: (A) script semplice, (B) form web minimo, (C) form robusto con validazione e output sicuro, (D) CLI + test.
rect_simple.php
<?php// rect_simple.php$width = isset($_GET['w']) ? (float) $_GET['w'] : 0;$height = isset($_GET['h']) ? (float) $_GET['h'] : 0;$area = $width * $height;$perimeter = 2 * ($width + $height);header('Content-Type: text/plain; charset=utf-8');echo "Width: $width\n";echo "Height: $height\n";echo "Area: $area\n";echo "Perimeter: $perimeter\n";
Chiamare: http://localhost/rect_simple.php?w=3.5&h=2.25
Limiti: nessuna validazione, output non escapato (ma numerico).
rect_form.php
<?php// rect_form.php$w = isset($_GET['w']) ? $_GET['w'] : '';$h = isset($_GET['h']) ? $_GET['h'] : '';$area = $perimeter = null;if ($w !== '' && $h !== '') { $width = (float) str_replace(',', '.', $w); $height = (float) str_replace(',', '.', $h); $area = $width * $height; $perimeter = 2 * ($width + $height);}?><!doctype html><html><head><meta charset="utf-8"><title>Rettangolo</title></head><body> <form method="get"> Larghezza: <input name="w" value="<?= htmlspecialchars($w) ?>"><br> Altezza: <input name="h" value="<?= htmlspecialchars($h) ?>"><br> <button type="submit">Calcola</button> </form> <?php if ($area !== null): ?> <p>Area: <?= htmlspecialchars((string)$area) ?></p> <p>Perimetro: <?= htmlspecialchars((string)$perimeter) ?></p> <?php endif; ?></body></html>
rect_robust.php
<?php// rect_robust.phpdeclare(strict_types=1);ini_set('display_errors','1'); error_reporting(E_ALL);function parseDecimal(string $s): ?float { $s = trim($s); if ($s === '') return null; // replace comma with dot for locales like it_IT $s = str_replace(',', '.', $s); // use filter to validate numeric string if (!is_numeric($s)) return null; return (float)$s;}$errors = [];$width = $height = null;if ($_SERVER['REQUEST_METHOD'] === 'POST') { $wIn = $_POST['width'] ?? ''; $hIn = $_POST['height'] ?? ''; $width = parseDecimal($wIn); $height = parseDecimal($hIn); if ($width === null || $width <= 0) $errors[] = "Larghezza non valida (deve essere > 0)."; if ($height === null || $height <= 0) $errors[] = "Altezza non valida (deve essere > 0)."; if (empty($errors)) { $area = $width * $height; $perimeter = 2 * ($width + $height); // format output with 2 decimal places $areaStr = number_format($area, 2, ',', '.'); $perimeterStr = number_format($perimeter, 2, ',', '.'); }}?><!doctype html><html><head><meta charset="utf-8"><title>Rettangolo - Robusto</title></head><body> <h1>Calcola Area e Perimetro</h1> <?php if (!empty($errors)): ?> <ul style="color:red"> <?php foreach ($errors as $e): ?> <li><?= htmlspecialchars($e) ?></li> <?php endforeach; ?> </ul> <?php endif; ?> <form method="post" action=""> <label>Larghezza: <input name="width" value="<?= htmlspecialchars($_POST['width'] ?? '') ?>"></label><br> <label>Altezza: <input name="height" value="<?= htmlspecialchars($_POST['height'] ?? '') ?>"></label><br> <button type="submit">Calcola</button> </form><?php if (isset($areaStr)): ?> <h2>Risultati</h2> <p>Area: <?= $areaStr ?> (unità²)</p> <p>Perimetro: <?= $perimeterStr ?> (unità)</p><?php endif; ?></body></html>
Punti chiave della versione C
declare(strict_types=1) impone controlli più rigorosi sulle tipologie quando usate type hints.
parseDecimal() gestisce la virgola come separatore decimale e blocca input non numerici.
htmlspecialchars() per evitare XSS.
number_format() per output leggibile con formattazione locale.
rect_cli.php
<?php// rect_cli.phpif (php_sapi_name() !== 'cli') { echo "Questo script è per CLI\n"; exit(1);}if ($argc < 3) { echo "Uso: php rect_cli.php width height\n"; exit(1);}$width = (float)$argv[1];$height = (float)$argv[2];if ($width <= 0 || $height <= 0) { echo "Valori devono essere > 0\n"; exit(1);}$area = $width * $height;$perimeter = 2 * ($width + $height);printf("Area: %.2f\nPerimeter: %.2f\n", $area, $perimeter);
Test semplice (shell):
php rect_cli.php 3.5 2.5
Output:
Area: 8.75Perimeter: 12.00
Usare error_log() per registrare errori lato server o un logger PSR-3 (Monolog):
error_log("Input non valido: width=$width height=$height");
Per test automatici usare PHPUnit. Esempio di test (scheletro):
tests/RectTest.php
<?phpuse PHPUnit\Framework\TestCase;require_once __DIR__ . '/../rect_functions.php';class RectTest extends TestCase { public function testArea() { $this->assertEquals(6.0, area(2.0, 3.0)); } public function testPerimeter() { $this->assertEquals(10.0, perimeter(2.0, 3.0)); }}
rect_functions.php con funzioni pure da testare:
<?phpfunction area(float $w, float $h): float { return $w * $h; }function perimeter(float $w, float $h): float { return 2*($w+$h); }
Usare eccezioni per casi critici.
Validare input e restituire messaggi utente chiari.
Non esporre informazioni di debug in produzione.
Validazione: ogni input va validato e sanitizzato (filter_input, filter_var).
Escaping: htmlspecialchars sempre per output HTML.
Typed code: preferire type hints e declare(strict_types=1) nei moduli critici.
Separa logica e presentazione: non mischiare troppo echo HTML/procedurale; usare template engine se il progetto cresce.
No eval, no extract($_REQUEST), no @ operator.
Usa PDO per accesso DB e prepared statements.
Gestione errori: log, testing e configurazione ambiente (dev vs prod).
'5' + '3' → 8 (coercizione numerica)
'05' == 5 → true, '05' === 5 → false
0 == 'abc' → true (attenzione!) — meglio is_numeric() prima di convertire.
?? and ?: differenza: $x = $a ?? 'd' vs $x = $a ?: 'd' (?: considera falsy).
Manuale PHP (php.net) — pagine essenziali: Variables, Types, Type Declarations, filter_input, htmlspecialchars, PDO.
PSR-12 Coding Style Guide — standard di codice PHP.
OWASP PHP Security Cheat Sheet — buone pratiche di sicurezza web.
PHPUnit documentation — testing in PHP.
Per la lezione di 3 ore:
30' teoria (sintassi, tags, error reporting),
45' variabili, tipi e operatori con esercizi rapidi (quiz su cui è vero/falso),
30' stringhe e formattazione,
45' laboratorio (implementare Versione B o C dell’esercizio rettangolo),
30' testing e riflessioni su sicurezza e best-practice.
Materiale da consegnare: zip con gli script (rect_simple.php, rect_form.php, rect_robust.php, rect_cli.php), rect_functions.php per unit tests, e README.md con istruzioni per eseguire in dev server (php -S localhost:8000).
Commenti
Posta un commento