はじめに
PHPでは、コールバック関数(関数名やメソッドを変数のように扱う仕組み)を実行するために、call_user_func() と call_user_func_array() がよく使われます。両者は似ていますが、**「引数の渡し方」**に違いがあります。この記事では、PHP8上級試験でも頻出のこの2つの関数の違いを、コード例と出力結果をもとにわかりやすく解説します。
目次
🧩 call_user_funcとcall_user_func_arrayの基本構文
| 関数名 | 説明 | 主な違い |
|---|---|---|
call_user_func(callable $callback, mixed ...$args): mixed | コールバック関数を、引数を1つずつ指定して呼び出す | 引数を直接列挙して渡す |
call_user_func_array(callable $callback, array $args): mixed | コールバック関数を、引数を配列としてまとめて呼び出す | 引数を配列で渡す |
両方とも「動的に関数・メソッドを実行する」ための関数ですが、引数の渡し方だけが違う点を押さえておきましょう。
💻 実際のコード例
<?php
declare(strict_types=1);
error_reporting(-1);
class Hoge {
public function func(int $num, string $str): bool {
var_dump(__METHOD__, $num, $str);
return true;
}
public static function sfunc(int $num, string $str): bool {
var_dump(__METHOD__, $num, $str);
return false;
}
}
$obj = new Hoge();
// 配列で引数を渡す(call_user_func_array)
$r = call_user_func_array([$obj, 'func'], [123, '2nd']);
var_dump($r);
// 可変長引数で渡す(call_user_func)
$r = call_user_func([Hoge::class, 'sfunc'], 456, '3rd');
var_dump($r);🧾 実行結果
string(10) "Hoge::func"
int(123)
string(3) "2nd"
bool(true)
string(11) "Hoge::sfunc"
int(456)
string(3) "3rd"
bool(false)✅ 結果の意味
| 行 | 内容 | 説明 |
|---|---|---|
Hoge::func | インスタンスメソッドが呼ばれた | $obj->func(123, '2nd') と等価 |
Hoge::sfunc | 静的メソッドが呼ばれた | Hoge::sfunc(456, '3rd') と等価 |
bool(true) / bool(false) | それぞれのメソッドの戻り値 | 関数の結果が変数$rに入る |
🧠 図解で理解する:引数の渡し方の違い
┌────────────────────────────────────────────────────────┐
│ call_user_func_array([$obj, 'func'], [123, '2nd']) │
│ └──────────────┬──────────────┘ │
│ 配列でまとめて渡す │
└────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────┐
│ call_user_func([Hoge::class, 'sfunc'], 456, '3rd') │
│ └─────┬─────┘ └───┬───┘ │
│ 呼び出し先指定 引数を列挙して渡す │
└────────────────────────────────────────────────────────┘💡 まとめ
| 比較項目 | call_user_func | call_user_func_array |
|---|---|---|
| 引数の渡し方 | 1つずつ直接書く | 配列でまとめて渡す |
| 呼び出し対象 | 関数・メソッドどちらも可 | 関数・メソッドどちらも可 |
| 代表的用途 | 可変長引数で直接呼びたいとき | 配列で渡したいとき(ループなど) |
✅ 試験ポイント:
- 両者の違いは「引数の形式」だけ。
[オブジェクト, 'メソッド名']または[クラス名, '静的メソッド名']の指定形式はどちらでも共通。
