Navigation
 Startseite
 Fachbücher
 Anzeigenmarkt
 Forum
 Webmaster News
 Script Newsletter
 Push Meldungen
 Kontakt
 Script Installation
 Php
 Php Tutorials
 Lernpfade
 Webhoster Vergleich
 Impressum

Community-Bereich
 kostenlos Registrieren
 Anmelden
 Benutzerliste

Script Datenbank
 Script Archiv
 Script Top 20
 Screenshots
 Testberichte

Suche
 

Unsere Php Scripts
 Counter Script
 Umfrage Script
 Bilder Upload Script
 Terminverwaltung
 Simple PHP Forum
 RSS Grabber

Tools und Generatoren
 .htpasswd Generator
 md5 Generator
 base64 Generator
 Markdown to HTML
 Colorpicker
 Unix timestamp Tool
 Unit Test Generator
 TLD Liste
 Webkatalog‑Verzeichnis

Artfiles.de
Bietet Serviceorientierte...
https://www.Artfiles.de
Webspace-Mieten.d...
Webhosting mit Plesk aus Erfurt: Vier...
https://www.Webspace-Mieten.de
 
 
 

PHP call_user_func() Function: Callbacks mit Parametern

Sie befinden sich: Home > Php Tutorial > PHP call_user_func() Functi...

PHP call_user_func() Function: Callbacks mit Parametern
Veröffentlicht am:
27.10.2026
Hits / Besucher:
5
Sprache:
  Deutsch
Tutorial Art:
eigenes
Eingetragen von:
Merkliste:
 
Beschreibung

Ein kleiner Router liest aus einem Array, welche Funktion eine Seite erzeugt: 'kontakt' => 'zeige_kontakt'. Welche Funktion am Ende läuft, steht erst fest, wenn die Anfrage da ist. PHP call_user_func() nimmt diesen Funktionsnamen entgegen, ruft die Funktion mit den passenden Argumenten auf und gibt ihr Ergebnis zurück. Wie man Funktionen als Werte erzeugt und weiterreicht, zeigen die Tutorials zu Closures und zur First-Class Callable Syntax. Liegt der Callback erst einmal vor, bleibt der Aufruf, und an ihm entscheidet sich, ob die Parameter so ankommen, wie sie gemeint waren.

Illustration zum Tutorial: PHP call_user_func() Function: Callbacks mit Parametern

Den Callback zu übergeben ist der einfache Teil. Die Arbeit steckt in den Argumenten: einzeln, als Array, benannt oder als Referenz.

Was macht PHP call_user_func()?

Die Funktion bekommt als ersten Parameter etwas Aufrufbares, einen sogenannten Callback, und als weitere Parameter die Argumente dafür. Sie ruft den Callback auf und reicht seinen Rückgabewert unverändert durch. Gibt der Callback nichts zurück, liefert PHP call_user_func() NULL. Wirft er eine Exception, kommt sie unverändert beim Aufrufer an. Der Router aus der Einleitung sieht damit so aus:

<?php

function zeige_start(): string
{
return 'Startseite';
}

function zeige_kontakt(): string
{
return 'Kontaktformular';
}

$aktionen = [
'start' => 'zeige_start',
'kontakt' => 'zeige_kontakt',
];

$seite = $_GET['seite'] ?? 'start';
$callback = is_string($seite)
? ($aktionen[$seite] ?? null)
: null;

if (!is_callable($callback)) {
http_response_code(404);
exit('Seite nicht gefunden');
}

echo call_user_func($callback); /* Startseite */

Ohne die Prüfung mit is_callable() endet ein Tippfehler im Array, etwa 'zeige_kontak', in einem TypeError mit der Meldung must be a valid callback, function "zeige_kontak" not found or invalid function name. Das is_string() davor fängt Anfragen wie ?seite[]=x ab, die sonst schon beim Zugriff auf das Array mit Cannot access offset of type array on array abbrechen. Der Ablauf eines Aufrufs mit call_user_func() im Überblick:

flowchart TD
    A[Aufruf mit Callback] --> B{Callback gültig?}
    B -->|nein| C[TypeError]
    B -->|ja| D[Argumente als Kopie übergeben]
    D --> E{Referenzparameter?}
    E -->|ja| F[Warning, nur Kopie geändert]
    E -->|nein| G[Callback läuft]
    F --> H[Rückgabewert zurück]
    G --> H

Syntax und Parameter im Original

Beide Funktionen gibt es seit PHP 4. Die Signaturen, ausgelesen per Reflection unter PHP 8.4:

call_user_func(

callable $callback,
mixed ...$args
): mixed

call_user_func_array(
callable $callback,
array $args
): mixed

/* $callback the function to call: a function
name, 'Class::method', [object,
'method'], a Closure or an object
with __invoke()
$args parameters for the callback;
call_user_func() passes values,
call_user_func_array() keeps
references set with & in the
array; string keys are used as
parameter names
returns the return value of the callback

Calls the callback given by the first
parameter and passes the remaining
parameters as arguments. */

Der Typ callable sorgt dafür, dass ein ungültiger Callback schon beim Aufruf auffällt und nicht erst irgendwo im Callback. Wichtiger ist die zweite Zeile im Kommentar: call_user_func() übergibt die Argumente immer als Kopie, nur call_user_func_array() reicht Referenzen durch, die im Array mit & markiert sind.

Eine Funktion mit Parametern aufrufen

Die Argumente stehen einfach hinter dem Callback, in derselben Reihenfolge wie bei einem direkten Aufruf. Optionale Parameter darf man weglassen:

<?php

function rechnung(
string $kunde,
float $betrag,
string $waehrung = 'EUR'
): string {
return sprintf(
'%s: %.2f %s',
$kunde,
$betrag,
$waehrung
);
}

echo call_user_func('rechnung', 'Berg', 49.9);
/* Berg: 49.90 EUR */

echo call_user_func(
'rechnung',
'Berg',
49.9,
'CHF'
);
/* Berg: 49.90 CHF */

Fehlt ein Pflichtargument, meldet PHP ArgumentCountError: Too few arguments to function rechnung(), 1 passed ... and at least 2 expected. Bei zu vielen Argumenten unterscheiden sich eigene und eingebaute Funktionen. Ein viertes Argument an rechnung() ignoriert PHP stillschweigend. Eine interne Funktion wie strtoupper() lehnt es ab: strtoupper() expects exactly 1 argument, 2 given. Auch die Typen der Parameter gelten wie beim direkten Aufruf. Wer an einen int-Parameter den Text 'x' übergibt, bekommt must be of type int, string given, und als Aufrufstelle nennt die Meldung die Zeile mit dem call_user_func()-Aufruf.

PHP call_user_func_array(): Parameter als Array

Liegen die Argumente bereits in einem Array, etwa aus einer Zeile einer CSV-Datei, wäre es umständlich, sie einzeln herauszuziehen. PHP call_user_func_array() nimmt das Array als Ganzes und verteilt seine Einträge auf die Parameter:

<?php

$zeile = 'Berg;49.9;CHF';
$werte = explode(';', $zeile);

echo call_user_func_array('rechnung', $werte);
/* Berg: 49.90 CHF */

Dass aus dem Text '49.9' ein float wird, liegt an der gewöhnlichen Typumwandlung ohne strict_types, nicht an der Funktion. Stehen die Werte einzeln im Code, passt PHP call_user_func(), kommen sie als Array an, die Variante mit _array.

Callables: Funktion, Methode, Closure

Als Callback akzeptiert PHP sieben Formen. Alle Aufrufe der Tabelle nutzen diese Klasse:

<?php

class Rechner
{
public static function doppelt(int $x): int
{
return $x * 2;
}

public function plus(int $a, int $b): int
{
return $a + $b;
}

public function __invoke(int $x): int
{
return $x * 10;
}
}

$r = new Rechner();
Form Aufruf Ergebnis
Funktionsname call_user_func('strtoupper', 'abc') "ABC"
statische Methode als String call_user_func('Rechner::doppelt', 4) 8
statische Methode als Array call_user_func([Rechner::class, 'doppelt'], 5) 10
Instanzmethode call_user_func([$r, 'plus'], 2, 3) 5
Closure oder Arrow Function call_user_func(fn($x) => $x ** 2, 7) 49
Objekt mit __invoke() call_user_func($r, 3) 30
First-Class Callable call_user_func($r->plus(...), 10, 20) 30

Der häufigste Fehlgriff ist eine Instanzmethode in der statischen Schreibweise. call_user_func('Rechner::plus', 1, 2) scheitert mit non-static method Rechner::plus() cannot be called statically, und zwar auch dann, wenn man [Rechner::class, 'plus'] schreibt. Für Instanzmethoden gehört ein Objekt in das Array. Wer vor dem Aufruf wissen will, was PHP aus einem Callback macht, gibt is_callable() eine dritte Variable mit: Für [$r, 'plus'] steht darin danach Rechner::plus. Vorsicht beim zweiten Parameter: Mit true prüft is_callable() nur die Form, und is_callable('gibtsnicht', true) liefert true, obwohl es die Funktion nicht gibt. Wie __invoke() ein Objekt aufrufbar macht, zeigt das Tutorial zu Magic Methods.

Referenzparameter: die Warnung und der Ausweg

Erwartet die aufgerufene Funktion ihr Argument per Referenz, geht der Aufruf über PHP call_user_func() schief, und zwar nur halb sichtbar:

<?php

function verdoppeln(int &$zahl): void
{
$zahl *= 2;
}

$n = 5;
call_user_func('verdoppeln', $n);
/* Warning: verdoppeln(): Argument #1 ($zahl)
must be passed by reference, value given */
echo $n; /* 5 */

call_user_func_array('verdoppeln', [&$n]);
echo $n; /* 10 */

Die Funktion läuft trotz der Warnung, verdoppelt aber nur eine Kopie, und $n bleibt bei 5. Erst das & im Array von call_user_func_array() reicht die Variable selbst durch. Ein Array ohne & löst dieselbe Warnung aus. Sauberer ist meist ein Callback, der seinen Wert zurückgibt, statt das Argument zu verändern. Den Gegenfall zeigt array_walk(): Dort übergibt PHP jedes Element per Referenz an den Callback, weil die Funktion genau dafür gebaut ist.

Benannte Argumente mit call_user_func_array()

Seit PHP 8.0 behandelt call_user_func_array() String-Schlüssel als Parameternamen. Vorher wurden sie laut Handbuch stillschweigend ignoriert. Damit lässt sich ein assoziatives Array direkt übergeben, in beliebiger Reihenfolge:

<?php

function adresse(
string $strasse,
string $ort,
string $land = 'DE'
): string {
return "$strasse, $ort ($land)";
}

$daten = [
'ort' => 'Bremen',
'strasse' => 'Hauptstr. 1',
];

echo call_user_func_array('adresse', $daten);
/* Hauptstr. 1, Bremen (DE) */

Positionale Werte dürfen vorne stehen, danach benannte. Auch PHP call_user_func() selbst nimmt benannte Argumente an und reicht sie weiter: call_user_func('adresse', ort: 'Berlin', strasse: 'Weg 2') ergibt Weg 2, Berlin (DE). Wie Named Arguments allgemein funktionieren, erklärt das Tutorial zu Named Arguments. Beim Übergeben über ein Array scheitert es meist an einer dieser Meldungen:

Array Meldung
['ort' => 'Bremen', 'Hauptstr. 1'] Cannot use positional argument after named argument
['strasse' => 'A', 'ort' => 'B', 'plz' => '28195'] Unknown named parameter $plz
['Hauptstr. 1', 'Bremen', 'strasse' => 'C'] Named parameter $strasse overwrites previous argument

Ganzzahlige Schlüssel zählen dagegen nur nach ihrer Position im Array, nicht nach ihrem Wert. [1 => 'Bremen', 0 => 'Hauptstr. 1'] ergibt Bremen, Hauptstr. 1 (DE), die Zahlen werden also übergangen.

Sichtbarkeit und Namespaces

Ob ein Callback gültig ist, prüft PHP an der Stelle, an der PHP call_user_func() aufgerufen wird. Eine private Methode lässt sich deshalb innerhalb der eigenen Klasse als Callback verwenden, von außen nicht:

<?php

class Tresor
{
private function oeffnen(): string
{
return 'offen';
}

public function test(): string
{
return call_user_func([$this, 'oeffnen']);
}
}

$t = new Tresor();
echo $t->test(); /* offen */

call_user_func([$t, 'oeffnen']);
/* TypeError: ... cannot access
private method Tresor::oeffnen() */

Bei Namespaces stolpert man über einen anderen Punkt. Ein Funktionsname als String wird nie relativ zum aktuellen Namespace aufgelöst, er gilt immer als vollständiger Name:

<?php

namespace App\Util;

function formatiere(string $s): string
{
return "[$s]";
}

call_user_func('formatiere', 'a');
/* TypeError: function "formatiere" not
found or invalid function name */

call_user_func('App\Util\formatiere', 'b');
call_user_func(__NAMESPACE__ . '\formatiere', 'c');
call_user_func(formatiere(...), 'd');

Die letzte Zeile ist die robusteste, weil PHP den Namen bereits beim Übersetzen auflöst und eine Umbenennung in der IDE mitwandert.

Praxis: ein Dispatcher für Ereignisse

Typischer Einsatzort für call_user_func_array() ist ein Ereignissystem. Module melden Callbacks für ein Ereignis an, und beim Auslösen bekommen alle dieselben Argumente:

<?php

final class Ereignisse
{
/** @var array<string, list<callable>> */
private array $hoerer = [];

public function an(
string $name,
callable $cb
): void {
$this->hoerer[$name][] = $cb;
}

public function ausloesen(
string $name,
mixed ...$args
): void {
foreach ($this->hoerer[$name] ?? [] as $cb) {
call_user_func_array($cb, $args);
}
}
}

$e = new Ereignisse();
$e->an('gespeichert', function (int $id): void {
echo "Log: Datensatz $id\n";
});
$e->ausloesen('gespeichert', 42);
/* Log: Datensatz 42 */

Der Typ callable an an() fängt Tippfehler schon beim Anmelden ab: Ereignisse::an(): Argument #2 ($cb) must be of type callable, string given. Ohne ihn fiele der Fehler erst beim Auslösen auf, vielleicht Stunden später in einem Cronjob. Wirft ein Callback eine Exception, bricht die Schleife ab; soll der nächste Hörer trotzdem laufen, gehört ein try in die Schleife. WordPress arbeitet nach demselben Muster: Die Klasse WP_Hook ruft in apply_filters() und do_all_hook() ihre Callbacks mit call_user_func_array() auf.

Veraltete Callables mit parent::, self:: und static::

Ältere Basisklassen übergeben gern Callbacks wie 'parent::name'. Seit PHP 8.2 meldet PHP dafür eine Deprecation, getestet bis PHP 8.5. Der Aufruf funktioniert noch, füllt aber das Log:

Alter Callback Meldung Ersatz
'parent::name' Use of "parent" in callables is deprecated [parent::class, 'name'] oder parent::name(...)
'self::name' Use of "self" in callables is deprecated [self::class, 'name'] oder self::name(...)
'static::name' Use of "static" in callables is deprecated [static::class, 'name'] oder static::name(...)
[$this, 'parent::hallo'] Callables of the form ["Kind", "parent::hallo"] are deprecated [get_parent_class($this), 'hallo']

Die drei String-Formen liefern gemessen dasselbe Ergebnis wie ihr Ersatz, auch aus Unterklassen heraus. Bei [$this, 'parent::hallo'] hängt das Ziel dagegen an der Klasse des Objekts: Aus einem Enkel-Objekt aufgerufen, landete der alte Callback in der Kindklasse, parent::hallo(...) dagegen in der Basisklasse. Gleich verhält sich nur [get_parent_class($this), 'hallo']. Bei static bleibt auch die späte Bindung erhalten: Aus einer Enkelklasse aufgerufen, landet static::name(...) in der Enkelklasse, self::name(...) in der Klasse, in der die Zeile steht.

Variable Funktionen statt PHP call_user_func()?

Jeder Callback lässt sich auch ohne PHP call_user_func() aufrufen. Variable Funktionen wie $fn(3) funktionieren mit allen sieben Formen, auch mit 'Rechner::doppelt' als String, und der Spread-Operator übergibt String-Schlüssel genauso als benannte Argumente:

<?php

$fn = 'Rechner::doppelt';
echo $fn(3); /* 6 */

$fn = [new Rechner(), 'plus'];
$args = ['b' => 5, 'a' => 1];
echo $fn(...$args); /* 6 */

Auch an der Laufzeit hängt die Entscheidung nicht. Drei Millionen Aufrufe einer Funktion mit zwei Argumenten:

Aufruf Windows 8.4.8 Linux 8.4.17
direkt 93 ms 43 ms
$fn(1, 2) mit String 138 ms 90 ms
$fn(...$args) 160 ms 115 ms
First-Class Callable 129 ms 51 ms
call_user_func() 137 ms 79 ms
call_user_func_array() 146 ms 96 ms

Die Unterschiede liegen im Bereich von Nanosekunden je Aufruf. Entscheidend ist, was IDE und statische Analyse sehen: strtoupper(...) erkennen beide als Funktion, 'strtoupper' ist für sie nur Text. In neuem Code ist deshalb $callback(...$args) mit einem callable-Typ oder gleich eine First-Class Callable die bessere Wahl. PHP call_user_func() bleibt in Bestandscode, in Plugin-Systemen und überall dort sinnvoll, wo ein Funktionsname als Text aus einer Konfiguration kommt.

Fazit

PHP call_user_func() ruft einen Callback mit einzeln aufgezählten Argumenten auf, die Variante mit _array nimmt sie als Array und versteht seit PHP 8.0 auch benannte Argumente. Welche der sieben Callable-Formen man übergibt, entscheidet darüber, ob statisch oder über ein Objekt aufgerufen wird; die Sichtbarkeit prüft PHP am Ort des Aufrufs.

Referenzparameter kommen nur mit einem & im Array an, sonst arbeitet die Funktion an einer Kopie. Und Strings wie 'parent::name' sind seit PHP 8.2 veraltet, mit parent::name(...) gibt es einen Ersatz, der auch der IDE hilft. Für neuen Code reicht oft $callback(...$args).

 


 

Kommentare (0)

Noch keine Kommentare. Sei der Erste!

Melde dich an, um einen Kommentar zu schreiben.
Bücherregal mit drei Büchern: 'PHP 4 - Grundlagen und Profiwissen' von Hanser Verlag, 'Webdesign in a Nutshell' von O'Reilly Verlag, und 'Webgestaltung' von Galileo Computing.