Die Sprache hinter großen Teilen des Webs
Ausführen: Datei hallo.php speichern und mit php hallo.php starten oder mit php -S localhost:8000 einen Testserver öffnen.
<?php und ?>$; Anweisungen enden mit ;echo, print, print_r, var_dump, printf zur Ausgabehtmlspecialchars() absichernphp hallo.php # Skript ausführen
php -r 'echo 1 + 2;' # einzelne Zeile
php -S localhost:8000 # eingebauter Testserver
php -a # interaktive Shellint, float, string, bool, array, null, Objektegettype, var_dump, is_int ... zum Prüfen; (int), (string) ... zum Umwandeln=== statt == vergleichenfalse 0 0.0 "" "0" [] null?? und ??= für Standardwerte, isset prüft Existenzdeclare(strict_types=1); macht Typen strikt<?php
$name = "Mia";
$alter = 17;
$groesse = 1.68;
$aktiv = true;
$nichts = null;
echo gettype($name), " ", gettype($alter), " ", gettype($groesse), " ", gettype($aktiv), " ", gettype($nichts), "\n";
$a = $b = 5; // Mehrfachzuweisung
[$x, $y] = [1, 2]; // Destrukturieren
[$x, $y] = [$y, $x]; // Tauschen
echo "$a $b $x $y\n";
$varname = "dynamisch"; // variable Variablen (selten nötig)
$$varname = "Wert";
echo $dynamisch, "\n";
define("MAX", 10);
const MIN = 1; // Konstanten
echo MAX + MIN, "\n";. verkettet Strings, {$var} interpoliert, Heredoc für mehrzeiligen Text<=>, ??, ?: sind praktische Operatorenstrlen, substr, str_replace, strpos, explode, implode, trimstr_contains, str_starts_with, str_ends_with seit PHP 8mb_strlen, mb_substr, mb_strtoupperprintf/sprintf für Formatierung<?php
echo 7 + 2, " ", 7 - 2, " ", 7 * 2, " ", 7 / 2, " ", 7 % 3, " ", 2 ** 8, " ", intdiv(7, 2), "\n";
$x = 10; $x += 5; $x -= 3; $x *= 2; $x /= 4; $x .= "!";
echo $x, "\n";
$i = 5; echo $i++, " ", ++$i, " ", $i--, " ", --$i, "\n";
var_dump(5 <=> 3, "a" <=> "b", [1, 2] <=> [1, 3]); // Spaceship: -1, 0, 1
var_dump(true && false, true || false, !true, true xor true);
var_dump(5 & 3, 5 | 3, 5 ^ 3, ~5, 1 << 4, 256 >> 2);
echo true ? "ja" : "nein", "\n"; // ternär
echo null ?: "Elvis", "\n"; // kurze Form: erster truthy Wert
echo null ?? "Coalesce", "\n";if / elseif / else, ternär, ??match ist strikt, liefert einen Wert und wirft UnhandledMatchErrorfor, while, do-while, foreach (am häufigsten)break und continue (auch mit Ebenenangabe)foreach ($a as &$x) ändert Elemente, danach unset($x)<?php
$punkte = 78;
if ($punkte >= 90) {
echo "sehr gut\n";
} elseif ($punkte >= 75) {
echo "gut\n";
} else {
echo "weiter üben\n";
}
echo $punkte >= 50 ? "bestanden" : "durchgefallen", "\n";
// Alternative Syntax in Templates
if ($punkte > 70):
echo "über 70\n";
endif;[] anhängen, unset entfernt, isset/array_key_exists prüfensort, asort, ksort, usort sortieren; Zusatz r = absteigendarray_map, array_filter, array_reduce mit Pfeilfunktionen fn... entpackt Arrays, [$a, $b] = ... destrukturiert<?php
$liste = ["Apfel", "Birne", "Kirsche"];
$person = ["name" => "Mia", "alter" => 17, "hobbys" => ["Lesen", "Judo"]];
echo $liste[0], " ", $person["name"], " ", $person["hobbys"][1], " ", count($liste), "\n";
$liste[] = "Dattel"; // anhängen
$person["ort"] = "Berlin"; // hinzufügen
unset($liste[1]); // entfernen (Schlüssel bleiben!)
print_r($liste);
print_r(array_values($liste)); // neu durchnummerieren
var_dump(isset($person["ort"]), array_key_exists("alter", $person), in_array("Judo", $person["hobbys"]));function name(Typ $p = std): Rückgabetyp; ...$rest für variable Parameterf(name: "Mia")use (Closure), fn (automatisch), global/static (selten)&$x übergibt Referenzenyield macht eine Funktion zum Generatordeclare(strict_types=1); plus Typangaben<?php
declare(strict_types=1);
function gruss(string $name = "Welt", string $anrede = "Hallo"): string
{
return "$anrede, $name!";
}
function summe(int ...$zahlen): int // variable Parameteranzahl
{
return array_sum($zahlen);
}
function minmax(array $z): array
{
return [min($z), max($z)];
}
function nichts(): void { echo "kein Rückgabewert\n"; }
echo gruss(), " ", gruss("Mia"), " ", gruss(anrede: "Hi", name: "Tom"), "\n"; // benannte Argumente
echo summe(1, 2, 3), " ", summe(...[4, 5]), "\n";
[$klein, $gross] = minmax([4, 9, 1]);
echo "$klein $gross\n";
nichts();class mit Eigenschaften, Methoden, Konstanten und staticreadonly machen Klassen kurz und sicherpublic, protected, privateclone kopiert__toString, __get, __call, __invoke)<?php
declare(strict_types=1);
class Konto
{
private float $stand = 0.0;
public static int $anzahl = 0;
public const ZINS = 0.02;
public function __construct(
public readonly string $inhaber, // Constructor Promotion (8.0)
float $start = 0.0,
) {
$this->stand = $start;
self::$anzahl++;
}
public function einzahlen(float $betrag): static
{
if ($betrag <= 0) {
throw new InvalidArgumentException("Betrag muss positiv sein");
}
$this->stand += $betrag;
return $this; // für Verkettung
}
public function stand(): float { return $this->stand; }
public function __toString(): string
{
return sprintf("%s: %.2f", $this->inhaber, $this->stand);
}
}
$k = new Konto("Mia", 100);
$k->einzahlen(50)->einzahlen(25.5);
echo $k, "\n";
echo Konto::$anzahl, " ", Konto::ZINS, " ", $k->inhaber, "\n";
try {
$k->inhaber = "Tom"; // readonly
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
$k->einzahlen(-5);
} catch (InvalidArgumentException $e) {
echo "Fehler: ", $e->getMessage(), "\n";
}extends, parent::, abstract, finalCountable, ArrayAccess, IteratorAggregate, JsonSerializable) machen Objekte "native"<?php
abstract class Tier
{
public function __construct(protected string $name) {}
abstract public function laut(): string;
public function vorstellen(): string { return "{$this->name} sagt {$this->laut()}"; }
}
class Hund extends Tier
{
public function laut(): string { return "Wuff"; }
}
class Katze extends Tier
{
public function __construct(string $name, private int $leben = 9)
{
parent::__construct($name);
}
public function laut(): string { return "Miau"; }
public function vorstellen(): string
{
return parent::vorstellen() . " ({$this->leben} Leben)";
}
}
foreach ([new Hund("Rex"), new Katze("Mimi")] as $t) echo $t->vorstellen(), "\n";
var_dump(new Hund("x") instanceof Tier, get_parent_class(new Hund("x")));try / catch / finally, throw new ...Throwable -> Exception und ErrorgetPrevious() verkettet Ursachen; throw ist ein Ausdruck (?? throw)set_error_handler wandelt Warnungen in Exceptions um<?php
function teile(float $a, float $b): float
{
if ($b == 0) {
throw new DivisionByZeroError("Division durch null");
}
return $a / $b;
}
try {
echo teile(10, 4), "\n";
echo teile(1, 0), "\n";
echo "nicht erreicht\n";
} catch (DivisionByZeroError $e) {
echo "Fehler: ", $e->getMessage(), "\n";
} finally {
echo "finally läuft immer\n";
}file_get_contents, file_put_contents, fopen/fgets, filefgetcsv/fputcsv für CSV; json_encode/json_decode mit JSON_THROW_ON_ERRORDateTimeImmutable, DateInterval, DateTimeZone für Zeitrechnungpreg_match, preg_match_all, preg_replace, preg_split für reguläre Ausdrückefilter_var validiert E-Mails, Zahlen, URLs<?php
$pfad = sys_get_temp_dir() . "/php_demo.txt";
file_put_contents($pfad, "Zeile 1\nZeile 2\nZeile 3\n");
file_put_contents($pfad, "Zeile 4\n", FILE_APPEND);
echo file_get_contents($pfad);
print_r(file($pfad, FILE_IGNORE_NEW_LINES));
$h = fopen($pfad, "r"); // zeilenweise: speicherschonend für große Dateien
while (($zeile = fgets($h)) !== false) {
echo strlen(rtrim($zeile)), " ";
}
fclose($h);
echo "\n";
var_dump(file_exists($pfad), is_file($pfad), is_dir(dirname($pfad)), filesize($pfad));
echo basename("/a/b/datei.txt"), " ", pathinfo("/a/b/datei.tar.gz", PATHINFO_EXTENSION), " ", dirname("/a/b/datei.txt"), "\n";
unlink($pfad);
var_dump(file_exists($pfad));ERRMODE_EXCEPTION aktivierenprepare + execute) schützen vor SQL-Injectionfetch, fetchAll, fetchColumn, lastInsertId, rowCountbeginTransaction, commit, rollBacknew PDO("mysql:host=localhost;dbname=shop;charset=utf8mb4", $user, $pass, $optionen);
new PDO("pgsql:host=localhost;dbname=shop", $user, $pass);
new PDO("sqlite:/pfad/datei.db");
new PDO("sqlite::memory:");session_start, httponly/secure/samesite, session_regenerate_idpassword_hash und password_verifyhash_equals, Fehleranzeige in Produktion aus<?php
declare(strict_types=1);
$fehler = [];
$name = "";
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$name = trim($_POST["name"] ?? "");
$alter = filter_input(INPUT_POST, "alter", FILTER_VALIDATE_INT, ["options" => ["min_range" => 0, "max_range" => 120]]);
if ($name === "") $fehler[] = "Name fehlt.";
if ($alter === false || $alter === null) $fehler[] = "Alter ungültig.";
if (!$fehler) {
// speichern ... dann weiterleiten (Post/Redirect/Get)
header("Location: /danke.php");
exit;
}
}
?>
<form method="post">
<label>Name <input name="name" value="<?= htmlspecialchars($name) ?>"></label>
<label>Alter <input name="alter" type="number"></label>
<button>Senden</button>
</form>
<?php foreach ($fehler as $f): ?>
<p class="fehler"><?= htmlspecialchars($f) ?></p>
<?php endforeach; ?>use importiertvendor/autoload.php)<?php
namespace Shop\Modell {
class Produkt
{
public function __construct(public string $name) {}
}
function hilfe(): string { return __FUNCTION__; }
const VERSION = "1.0";
}
namespace {
use Shop\Modell\Produkt;
use Shop\Modell\Produkt as P;
use function Shop\Modell\hilfe;
use const Shop\Modell\VERSION;
$p = new Produkt("Stift");
echo $p::class, " ", (new P("Heft"))->name, " ", hilfe(), " ", VERSION, " ", \strlen("abc"), "\n";
}never, readonly, Enums, match?->, benannte Argumente, Constructor Promotion, First-class Callables<?php
declare(strict_types=1);
function f(int|string $id, ?array $optionen = null, mixed $beliebig = null): string|int|null { return $id; }
function wirf(): never { throw new Exception("nie zurück"); }
interface A {} interface B {}
class AB implements A, B {}
function schnitt(A&B $x): string { return $x::class; } // Intersection Types (8.1)
echo schnitt(new AB()), " ", f("x"), "\n";
class Mensch
{
public function __construct(
public readonly string $name,
public readonly int $alter = 0,
private array $tags = [],
) {}
public function mit(string $name): static
{
return new static($name, $this->alter, $this->tags); // "wither"-Muster für unveränderliche Objekte
}
}
$m = new Mensch("Mia", alter: 17);
echo $m->mit("Tom")->name, " ", $m->name, "\n";===, strikte Typen und htmlspecialchars sind deine wichtigsten Gewohnheitenpassword_hashif () {} elseif () {} else {} match ($x) { 1 => "a", default => "b" }
for ($i = 0; $i < 10; $i++) {} foreach ($arr as $k => $v) {}
while () {} do {} while (); break; continue; return;
try {} catch (A | B $e) {} finally {}
$a ?? $b $a ??= $b $a?->b $a ?: $b $x ? $y : $z