PHPのデフォルト引数・可変長引数(…)の使い方

phpアイキャッチ PHP

こんにちは、かつコーチです。

前回は関数の基本として、引数と戻り値の使い方を解説しました。

今回はその発展編として、「引数を省略できるデフォルト引数」と「引数の数を自由にできる可変長引数」を扱います。

どちらも、前回触れた「引数の数が合わずエラーになる」問題をきれいに解決してくれる機能なので、セットで覚えておきましょう。

デフォルト引数とは?

引数を省略できる仕組み

デフォルト引数とは、関数を呼び出すときに値を渡さなかった場合に使われる「初期値」をあらかじめ設定しておける仕組みのことです。

前回の記事で、こんなエラーに遭遇する例を紹介しました。

<?php
function introduce($name, $age) {
    echo $name . "さん(" . $age . "歳)です。\n";
}

introduce("かつコーチ"); // Fatal error: Too few arguments
?>

デフォルト引数を使うと、$age を渡さなかった場合の初期値を設定できます。

<?php
function introduce($name, $age = 20) {
    echo $name . "さん(" . $age . "歳)です。\n";
}

introduce("かつコーチ");      // かつコーチさん(20歳)です。
introduce("佐藤さん", 25);    // 佐藤さん(25歳)です。
?>

$age = 20 のように、引数の後ろに = 初期値 を書くだけでデフォルト引数になります。

なぜデフォルト引数が必要なのか

実務では「たいていの場合は同じ値で問題ないが、たまに変更したいケースがある」という引数がよく登場します。

たとえば、検索結果を1ページに何件表示するかという「件数」の引数を考えてみましょう。

<?php
function getSearchResults($keyword, $limit = 20) {
    // $limitを指定しなければ20件、指定すればその件数を使う
    echo "「" . $keyword . "」で検索し、" . $limit . "件表示します。\n";
}

getSearchResults("PHP");        // 「PHP」で検索し、20件表示します。
getSearchResults("PHP", 50);    // 「PHP」で検索し、50件表示します。
?>

デフォルト引数があることで、呼び出す側は「特別な指定がなければこの値でいい」という前提でシンプルに関数を使えます。

毎回すべての引数を書く必要がなくなるので、コードもすっきりします。

デフォルト引数を使うときの注意点

デフォルト引数は、必ず引数リストの後ろの方に置く必要があります。

❌ Before:デフォルト引数を先頭に置いてしまう

<?php
function introduce($age = 20, $name) {
    echo $name . "さん(" . $age . "歳)です。\n";
}
?>

このコードを実行しようとすると、次のようなエラーになります。

Fatal error: Cannot use a default value for a required argument

私はこの並び順のルールを最初は意識しておらず、たまたま処理の都合で引数を並べ替えたときにこのエラーに遭遇しました。

「デフォルト値のない必須の引数は、デフォルト値を持つ引数より前に書く」というルールを知らなかったのが原因です。

✅ After:必須の引数を先、デフォルト引数を後ろに置く

<?php
function introduce($name, $age = 20) {
    echo $name . "さん(" . $age . "歳)です。\n";
}

introduce("かつコーチ"); // かつコーチさん(20歳)です。
?>

「省略できない引数が先、省略できる引数が後ろ」という並び順を意識しておけば、このエラーは避けられます。

可変長引数とは?

引数の数を自由にできる仕組み

可変長引数とは、... を使うことで「いくつでも」引数を受け取れるようにする仕組みのことです。

たとえば、複数の数値の合計を求める関数を考えてみます。

デフォルト引数だけでは対応しきれない、「引数の数そのものが毎回変わる」というケースに強いのが可変長引数です。

<?php
function sum(...$numbers) {
    $total = 0;
    foreach ($numbers as $number) {
        $total += $number;
    }
    return $total;
}

echo sum(1, 2, 3);          // 6
echo sum(10, 20, 30, 40);   // 100
echo sum(5);                // 5
?>

...$numbers の部分に、渡された引数がすべて配列としてまとめて入ってきます。

引数を1個渡しても、5個渡しても、同じ関数で対応できるのがポイントです。

可変長引数の中身を確認する

...$numbers に渡された値は、関数の中では普通の配列として扱えます。

<?php
function sum(...$numbers) {
    var_dump($numbers);
    // array(3) {
    //   [0]=> int(1)
    //   [1]=> int(2)
    //   [2]=> int(3)
    // }
    return array_sum($numbers);
}

echo sum(1, 2, 3); // 6
?>

var_dump() で中身を確認すると、渡した値がそのまま配列に格納されていることが分かります。

前回・前々回で学んだ配列の知識が、ここでもそのまま活きてきます。

通常の引数と組み合わせる

可変長引数は、通常の引数と組み合わせて使うこともできます。

その場合、可変長引数は必ず最後の引数として書く必要があります。

<?php
function announce($title, ...$names) {
    echo $title . ":" . implode("、", $names) . "\n";
}

announce("出席者", "かつコーチ", "佐藤さん", "鈴木さん");
// 出席者:かつコーチ、佐藤さん、鈴木さん
?>

$title は必須の1つの値、...$names はそれ以降のすべての値をまとめて受け取る、という組み合わせです。

よくあるつまずきポイント・エラー対処

可変長引数を先頭に書いてエラーになる

私が実際にやってしまった失敗が、可変長引数を引数リストの途中や先頭に書いてしまうミスです。

❌ Before:可変長引数を先頭に置いてしまう

<?php
function announce(...$names, $title) {
    echo $title . ":" . implode("、", $names) . "\n";
}
?>

これを実行しようとすると、次のような構文エラーになります。

Fatal error: Only the last parameter can be variadic

「可変長になれるのは最後の引数だけ」という意味のエラーです。

私は「タイトルを先に受け取ってから、名前を後で並べたい」という順番にこだわりすぎて、このルールを見落としていました。

✅ After:可変長引数は必ず最後に置く

<?php
function announce($title, ...$names) {
    echo $title . ":" . implode("、", $names) . "\n";
}

announce("出席者", "かつコーチ", "佐藤さん", "鈴木さん");
// 出席者:かつコーチ、佐藤さん、鈴木さん
?>

「引数の数が不定になるものは、必ず最後にひとつだけ」というルールを覚えておけば、このエラーは防げます。

応用・一歩先の使い方

配列を可変長引数として展開して渡す

すでに配列としてデータがある場合、... を使ってその配列を可変長引数として展開して渡すこともできます。

<?php
function sum(...$numbers) {
    return array_sum($numbers);
}

$prices = [1200, 3000, 500];

// 配列をそのまま展開して渡す(スプレッド構文)
echo sum(...$prices); // 4700
?>

sum($prices) と書いてしまうと配列がまるごと1つの引数として渡ってしまいますが、sum(...$prices) と書くことで、配列の中身が1つずつの引数として展開されます。

この書き方は「スプレッド構文」とも呼ばれ、既存の配列データを関数にそのまま渡したいときに便利です。

デフォルト引数と可変長引数を組み合わせる

デフォルト引数と可変長引数は、それぞれ役割が異なるため組み合わせて使うこともできます。

<?php
function formatMessage($prefix = "お知らせ", ...$items) {
    return $prefix . ":" . implode("、", $items);
}

echo formatMessage("お知らせ", "会議は10時から", "資料は事前配布");
// お知らせ:会議は10時から、資料は事前配布

echo formatMessage(...["重要", "本日締切です"]);
// 重要:本日締切です
?>

「基本的な設定はデフォルト値で済ませつつ、可変長引数で自由度を持たせる」という組み合わせは、汎用的な関数を作るときに役立ちます。

まとめ

この記事のポイント

  • デフォルト引数は $引数 = 初期値 で設定し、呼び出し時に値を省略できる
  • デフォルト引数を持つ引数は、必須の引数より後ろに書く必要がある
  • 可変長引数は ...$引数名 で、いくつでも値を受け取れる
  • 可変長引数は関数の引数リストの最後にひとつだけ書ける
  • ... を使うと配列を展開して関数の引数として渡せる(スプレッド構文)

次に読むべき記事

引数の柔軟な扱い方が分かったら、次は名前を持たない関数「無名関数(クロージャ)」を学んでいきましょう。

→ 次の記事:PHPの無名関数・クロージャ(use)をわかりやすく解説

タイトルとURLをコピーしました