Zum Inhalt springen

Funktionen und Klassen in PHP

Eine Funktion gibt einem Stück Arbeit einen Namen. Eine Klasse bündelt Daten und die Arbeit damit. Dieser Text zeigt beides an lauffähigem Code und den Punkt, an dem man von der einen zur anderen wechselt.

  • Für wenEinsteiger, technisch Interessierte
  • NiveauGrundlagen bis Mittel
  • Lesezeitetwa 8 Minuten
  • Stand16. Oktober 2026

Das lernen Sie

  • Wie eine Funktion aufgebaut ist und was Typangaben bewirken
  • Was benannte Argumente und Vorgabewerte ersparen
  • Wie eine Klasse Daten und Verhalten zusammenhält
  • Woran man erkennt, dass eine Funktion eine Klasse werden sollte

Eine Funktion gibt der Arbeit einen Namen

Sobald derselbe Ablauf mit derselben fachlichen Bedeutung an zwei oder drei Stellen vorkommt, gehört er in eine Funktion. Der Gewinn ist nicht die gesparte Zeile, sondern dass eine Änderung nur noch an einer Stelle passiert. Der Gewinn ist nicht die gesparte Zeile, sondern dass eine Änderung nur noch an einer Stelle passiert.

PHPgeprüft mit PHP 8.3
declare(strict_types=1); function bruttoPreis(int $nettoCent, float $satz = 0.19): int { return (int) round($nettoCent * (1 + $satz)); } echo bruttoPreis(1000); // 1190 echo bruttoPreis(1000, 0.07); // 1070 echo bruttoPreis(nettoCent: 1000); // benanntes Argument
Die Typangaben links und hinter dem Doppelpunkt sind Zusagen. Ist in der aufrufenden Datei strict_types aktiv, weist PHP einen String für einen int-Parameter ab, statt ihn umzuwandeln. Ohne die Deklaration in der aufrufenden Datei wird "1000" stillschweigend zu 1000.

Beachten Sie den Betrag in ganzen Cent. Das ist kein Zufall: Kommazahlen sind für Geld ungeeignet, und eine Funktionssignatur ist der beste Ort, diese Entscheidung sichtbar zu machen.

Eine Klasse hält zusammen, was zusammengehört

Wenn mehrere Funktionen immer dieselben Werte herumreichen, gehören diese Werte und die Funktionen zusammen. Genau das ist eine Klasse.

PHPgeprüft mit PHP 8.3
declare(strict_types=1);

final class Auftragsposition
{
    public function __construct(
        private readonly string $artikel,
        private readonly int $menge,
        private readonly int $einzelpreisCent,
    ) {
        if ($menge < 1) {
            throw new InvalidArgumentException('Menge muss mindestens 1 sein.');
        }
    }

    public function gesamtCent(): int
    {
        return $this->menge * $this->einzelpreisCent;
    }

    public function beschreibung(): string
    {
        return sprintf('%dx %s', $this->menge, $this->artikel);
    }
}

$pos = new Auftragsposition('Dichtung', 3, 450);
echo $pos->beschreibung();   // 3x Dichtung
echo $pos->gesamtCent();     // 1350
Die kurze Schreibweise im Konstruktor legt Eigenschaften direkt an. readonly heißt: nach dem Erzeugen unveränderlich.

Drei Dinge passieren hier, die eine lose Funktion nicht leisten kann. Die Prüfung im Konstruktor sorgt dafür, dass es keine Position mit Menge 0 geben kann — kein späterer Aufrufer muss das noch prüfen. Die Daten sind nach außen nicht veränderbar. Und der Name sagt, worum es geht.

Wann aus einer Funktion eine Klasse wird

Drei Anzeichen, die für eine Klasse sprechen; meist genügt schon eines, um sie ernsthaft in Betracht zu ziehen:

  • Dieselben drei, vier Werte wandern durch mehrere Funktionen.
  • Eine Funktion braucht einen Zustand, der zwischen Aufrufen bestehen bleibt.
  • Es gibt ungültige Kombinationen der Werte, die niemand entstehen lassen darf.

Der umgekehrte Fall kommt ebenso vor: Eine Klasse mit einer einzigen Methode und ohne Eigenschaften ist in Wahrheit eine Funktion. Das ist kein Fehler, nur unnötiger Aufwand beim Lesen.

Ein Beispiel aus der Praxis

Was Typangaben im Betrieb wirklich bewirken

PHPgeprüft mit PHP 8.3
declare(strict_types=1);

function tageBis(DateTimeImmutable $ziel): int
{
    $heute = new DateTimeImmutable('today');
    return (int) $heute->diff($ziel)->format('%r%a');
}

// Richtig:
echo tageBis(new DateTimeImmutable('2027-01-01'));

// Falsch — faellt SOFORT auf, nicht erst im Ergebnis:
// echo tageBis('2027-01-01');
// TypeError: tageBis(): Argument #1 ($ziel) must be of type
// DateTimeImmutable, string given
Ohne Typangabe hätte die Funktion den String entgegengenommen und wäre erst beim Aufruf von diff() gescheitert — mit einer Meldung, die auf die falsche Stelle zeigt.

Das ist der eigentliche Nutzen: Der Fehler erscheint dort, wo er gemacht wurde, nicht drei Ebenen weiter unten. In einer gewachsenen Anwendung ist das der Unterschied zwischen fünf Minuten und einem halben Tag.

Häufige Missverständnisse

Eine Klasse lohnt sich ab dem Moment, in dem ungültige Zustände möglich wären. Das ist oft schon im zweiten Entwicklungsschritt der Fall.

Der Unterschied ist in der Praxis nicht messbar. Was sie kosten, ist Schreibarbeit; was sie sparen, ist Fehlersuche.

Es bedeutet, dass sich dieses Objekt nicht ändert. Für einen neuen Wert erzeugt man ein neues Objekt — das ist gewollt und macht Nebenwirkungen unmöglich.

Weiterführende Quellen

Über den Autor

Fabian Lücker ist geschäftsführender Gesellschafter der PHP-Schmiede KG in Rheine und seit 2007 in der Softwareentwicklung tätig. Er verantwortet Entwicklung und Konzeption und schreibt hier über Entscheidungen, die in echten Projekten anfallen.