第7章 関数

関数の定義と呼び出し

関数は特定のタスクを実行するためのコードのまとまりで、functionキーワードを使用して定義します。以下に簡単な関数の例を示します。

// 関数の定義
function greet() {
    echo "こんにちは、世界!";
}

// 関数の呼び出し
greet(); // こんにちは、世界!

この例では、greetという名前の関数を定義し、それを呼び出しています。関数は定義した後で何度でも呼び出すことができます。


引数と戻り値

関数は引数を取り、戻り値を返すことができます。引数は関数に情報を渡すためのもので、戻り値は関数の結果を返すためのものです。

// 引数と戻り値を持つ関数の定義
function add($x, $y) {
    $sum = $x + $y;
    return $sum;
}

// 関数の呼び出しと結果の表示
$result = add(5, 3);
echo $result; // 8

また、関数の定義時に指定する引数を「仮引数」、関数を呼び出す際に指定する引数を「実引数」と呼びます。

function sayHello($name) { // $nameは仮引数
    echo "Hello, " . $name;
}

$name = "John"; // これが実引数
sayHello($name);


スコープ

スコープとは、変数が参照可能な範囲のことを指します。PHPでは、関数の内部で定義された変数はその関数内部からしかアクセスできません。これを「ローカルスコープ」と呼びます。

function test() {
    $localVar = "ローカル";
    echo $localVar; // ローカル
}

test();
echo $localVar; // Undefined variable: localVar


ビルトイン関数

PHPには多くのビルトイン(組み込み)関数があります。例えば、count()関数は配列の要素数を数えます。

$array = array(1, 2, 3, 4, 5);
echo count($array); // 5


再帰関数

関数が自分自身を呼び出すことを「再帰」と呼びます。この技術は適切に使われると、複雑な問題を解決するのに役立ちます。例えば、階乗を計算する関数を再帰を用いて作成することができます。

// 再帰関数の定義
function factorial($n) {
    if ($n === 0) {
        return 1;
    } else {
        return $n * factorial($n - 1);
    }
}

// 関数の呼び出しと結果の表示
echo factorial(5); // 120


参照渡し

PHPでは、関数に引数を渡す際に値渡し(コピー)と参照渡しの2つの方法があります。デフォルトは値渡しですが、参照渡しを行いたい場合は、仮引数の前にアンパサンド(&)を付けます。

参照渡しを用いると、関数内で行われた変更が元の変数にも反映されます。

function addOne(&$num) {
    $num++;
}

$num = 10;
addOne($num);
echo $num; // 11を出力します。関数内での変更が$numに反映されています。


複数の値を返す

PHPの関数は一つの値を返すことが基本ですが、複数の値を返したい場合は、配列を用いて返すことが一般的です。

function calculate($num1, $num2) {
    $sum = $num1 + $num2;
    $product = $num1 * $num2;
    return array($sum, $product);
}

$result = calculate(3, 5);
echo "Sum: " . $result[0] . ", Product: " . $result[1];


関数の名前の付け方

関数名を選ぶときには、以下のような規則や規範を参考にすると良いでしょう

  1. 明確さ: 関数が何をするのかを一目で理解できるように、明確な名前をつけましょう。例えば、「calculateAverage」や「validateInput」のように。
  2. 一貫性: 同じ種類の操作を行う関数は、似たような命名規則を持つべきです。これにより、他の関数の名前を推測しやすくなります。
  3. 短さと簡潔さ: 短くて簡潔な名前が望ましいですが、それだけでは関数の目的が明確に伝わらない場合は、より長い名前を使用します。一方で、非常に長い名前は読みにくくなるので避けるべきです。
  4. 動詞の使用: 関数は一般的にアクションまたは操作を表すため、関数名は通常動詞または動詞のフレーズで始まります。例:getTotal, calculateSum。
  5. キャメルケースまたはスネークケースの使用: PHPでは関数名は大文字と小文字を区別します。一般的にはキャメルケース(例:calculateAverage)またはスネークケース(例:calculate_average)を使用します。
  6. 予約語の避ける: PHPの予約語(例えばechoやprintなど)は関数名として使わないでください。


単一責任原則

「単一責任原則」は、一つの関数やクラスが一つの仕事だけを行うべきであるというプログラミングの原則です。これは、コードの可読性やメンテナンス性を高め、エラーの可能性を低減するための重要な原則です。

以下に、単一責任原則を守っていない関数の例を示します。

function processStudent($student){
    // 生徒の成績を計算
    $average = ($student['math'] + $student['science'] + $student['english']) / 3;

    // 生徒の成績に基づく評価を出力
    if ($average > 80){
        echo $student['name'] . "の成績は優秀です。";
    } else {
        echo $student['name'] . "の成績は良くないです。";
    }

    // 生徒のデータをデータベースに保存
    $db = new mysqli('localhost', 'user', 'password', 'database');
    $stmt = $db->prepare("INSERT INTO students (name, math, science, english) VALUES (?, ?, ?, ?)");
    $stmt->bind_param("siii", $student['name'], $student['math'], $student['science'], $student['english']);
    $stmt->execute();
}

この関数は「成績を計算する」「成績に基づいて評価を出力する」「データベースにデータを保存する」という三つの異なる責任を担っています。それぞれの責任は独立した関数として定義するべきです。これにより、各関数は単一の責任を果たすことができ、他の部分のコードから独立してテストや再利用が可能になります。

※データベースについては別章で解説いたします。


練習問題1.

以下の仕様を満たす関数を作成してください。

関数名はgreetとする

引数として文字列$nameを1つ受け取る

"Hello, 引数の名前!"という文字列を出力する


練習問題2.

関数名はcalculateAreaとする

引数として数値$lengthと$widthを2つ受け取る

引数で受け取った$lengthと$widthの積を返す(これが面積になる)


練習問題3.

関数名はincrementとする

引数として数値$numを1つ受け取る。引数は参照渡しとする

引数で受け取った$numの値を1増やす(つまり、元の変数の値も1増える)