PHP 関数のデフォルト引数
PHP の関数を設計する際、引数(Arguments)にあらかじめ「デフォルト値(Default Values)」を設定することができます。関数を呼び出す際、呼び出し側がその引数に対して明示的な値を渡さなかった場合、PHP は自動的にこのデフォルト値を使用します。
この機能は関数の柔軟性を大幅に向上させます。同じ関数でありながら、受け取る引数の数に応じて異なる挙動をさせることが可能になり、異なるシナリオのために複数の似たような関数を作成する手間を省けます(これは PHP において、他言語の「関数オーバーロード」特性を代替する主要な手段でもあります)。
1. デフォルト引数の定義
関数の引数にデフォルト値を指定するには、関数定義の括弧内で引数変数に直接値を代入するだけです。
関数呼び出し時にその引数を省略すると、PHP はデフォルト値を使用します。呼び出し時に値が提供された場合は、その値がデフォルト値をオーバーライド(上書き)します。
<?php
// デフォルトの名前を持つ挨拶関数を定義
function greet($name = "ゲスト") {
echo "こんにちは、" . $name . "さん!\n";
}
// 引数を渡さずに関数を呼び出し
greet(); // 出力:こんにちは、ゲストさん!
// 特定の引数を渡して関数を呼び出し
greet("アリス"); // 出力:こんにちは、アリスさん!
// 長方形の面積を計算する関数、デフォルトの幅を 10 に設定
function calculateRectangleArea($length, $width = 10) {
return $length * $width;
}
// 長さのみを指定して呼び出し。幅はデフォルト値の 10 が使用される
echo "面積 1:" . calculateRectangleArea(5) . "\n"; // 出力:面積 1:50 (5 * 10)
// 長さと幅の両方を指定して呼び出し
echo "面積 2:" . calculateRectangleArea(5, 20) . "\n"; // 出力:面積 2:100 (5 * 20)
?>2. 【厳格なルール】デフォルト引数の並び順
デフォルト値を持つ引数は、関数シグネチャにおいて、デフォルト値を持たないすべての引数の後に配置しなければなりません。
PHP は引数を左から右へと処理します。もしデフォルト値を持つ引数の後にデフォルト値を持たない引数が続くと、呼び出し側が値を省略した際に、PHP はどの引数が省略されたのかを判断できなくなります。
<?php
// 誤った例:デフォルト値を持つ引数が、持たない引数の前に配置されている
// これは Parse error (パースエラー) を引き起こします:Default parameter must be declared after non-default parameters
/*
function displayUserInfo($name = "不明", $age) {
echo "名前:" . $name . "、年齢:" . $age . "\n";
}
*/
// 正しい例:デフォルト値を持たない引数を前に、持つ引数を後ろに配置
function displayUserInfo($age, $name = "不明") {
echo "名前:" . $name . "、年齢:" . $age . "\n";
}
displayUserInfo(30); // 出力:名前:不明、年齢:30
displayUserInfo(25, "ボブ"); // 出力:名前:ボブ、年齢:25
// 複数のデフォルト引数を持つことも可能ですが、それらはすべて最後に並べる必要があります
function sendMessage($message, $recipient = "ユーザー", $subject = "システム通知") {
echo "宛先:" . $recipient . "\n";
echo "件名:" . $subject . "\n";
echo "本文:" . $message . "\n\n";
}
sendMessage("ご注文の商品を発送いたしました。");
// 出力:
// 宛先:ユーザー
// 件名:システム通知
// 本文:ご注文の商品を発送いたしました。
sendMessage("ようこそ!", "管理者");
// 出力:
// 宛先:管理者
// 件名:システム通知
// 本文:ようこそ!
sendMessage("会議のリマインド", "開発チーム", "緊急");
// 出力:
// 宛先:開発チーム
// 件名:緊急
// 本文:会議のリマインド
?>3. 総合実践ケース
デフォルト引数は、「大半の汎用的なシナリオをカバーしつつ、特殊なケースではカスタマイズを許可する」という柔軟な関数を作成するのに最適です。
3.1 データベース接続関数
データベースへの接続を行う関数を考えてみましょう。通常は標準的な認証情報(localhost や root など)を使用しますが、時には異なるホストへの接続や異なるデータベース名が必要になることがあります。
<?php
/**
* データベースに接続する。
*
* @param string $host ホスト名。デフォルトは 'localhost'。
* @param string $username ユーザー名。デフォルトは 'root'。
* @param string $password パスワード。デフォルトは空文字列 ''。
* @param string $dbname データベース名。デフォルトは 'app_db'。
* @return string シミュレートされた接続ステータスメッセージ。
*/
function connectToDatabase($host = 'localhost', $username = 'root', $password = '', $dbname = 'app_db') {
// 実際のアプリケーションでは、ここで PDO や mysqli を使用して接続を確立します。
// デモのために文字列をリターンします。
return "DB:$dbname に接続を試行中 (ホスト:$host、ユーザー:$username)...\n" .
"接続シミュレーションに成功しました。\n";
}
// すべての引数でデフォルト値を使用(最も一般的なローカル開発環境)
echo connectToDatabase();
// 出力:
// DB:app_db に接続を試行中 (ホスト:localhost、ユーザー:root)...
// 接続シミュレーションに成功しました。
// 【アドバンスド・テクニック】PHP 8 で導入された「名前付き引数」を使い、前のデフォルト値をスキップして特定の値を変更
echo connectToDatabase(dbname: 'test_db');
// 出力:
// DB:test_db に接続を試行中 (ホスト:localhost、ユーザー:root)...
// 接続シミュレーションに成功しました。
// 特定の認証情報を持つリモートホストへの接続(すべて上書き)
echo connectToDatabase('remote_server.com', 'admin_user', 'secure_pass', 'prod_db');
// 出力:
// DB:prod_db に接続を試行中 (ホスト:remote_server.com、ユーザー:admin_user)...
// 接続シミュレーションに成功しました。
?>3.2 HTML 要素のダイナミック生成
HTML 要素ジェネレーターを作成する際、通常はデフォルトの属性(特定の CSS クラスなど)を持たせたいものですが、それらをオーバーライドできる柔軟性も確保しておく必要があります。
<?php
/**
* HTML ボタン要素を生成する。
*
* @param string $text ボタンのテキスト内容。
* @param string $class ボタンの CSS クラス。デフォルトは 'btn btn-primary'。
* @param string $type ボタンの type 属性。デフォルトは 'button'。
* @param string $id ボタンの ID 属性。デフォルトは空文字列。
* @return string 生成された HTML ボタン文字列。
*/
function createButton($text, $class = 'btn btn-primary', $type = 'button', $id = '') {
$idAttribute = $id ? " id=\"$id\"" : ""; // ID が提供された場合のみ id 属性を追加
return "<button type=\"$type\" class=\"$class\"$idAttribute>$text</button>\n";
}
// 標準的な primary ボタンを作成
echo createButton("フォーム送信");
// 出力: <button type="button" class="btn btn-primary">フォーム送信</button>
// 特定の ID を持つ警告ボタンを作成(PHP 8 名前付き引数を使用)
echo createButton("キャンセル", "btn btn-warning", id: "cancelButton");
// 出力: <button type="button" class="btn btn-warning" id="cancelButton">キャンセル</button>
// カスタムクラスを持つ submit (送信) ボタンを作成
echo createButton("ログイン", "btn btn-success", "submit");
// 出力: <button type="submit" class="btn btn-success">ログイン</button>
?>