関数

ここまで来るまでに、既に何度か登場している「関数」について解説します。

関数とは

ファ、ファ、ファンクション!

・・・。

「変数」のページで、「関数は野菜ジュースを生産する工場です。」なんて事を書きました。この阿呆な例えを踏まえた上で、次のサンプルと結果をご覧下さい。

<html>
<body>
<p>
<?php
    function juice(){
        static $num = 1;
        $vege1 = "Tomato ";
        $vege2 = "Carrot ";
        $vege3 = "Onion ";
        $juice = $vege1.$vege2.$vege3."Juice!!!(".$num.")<br />";
        echo $juice;
        $num = $num + 1;
    }
    
    for($i = 0; $i < 5; $i = $i + 1){
        juice();
    }
?>
</p>
</body>
</html>
Tomato Carrot Onion Juice!!!(1)
Tomato Carrot Onion Juice!!!(2)
Tomato Carrot Onion Juice!!!(3)
Tomato Carrot Onion Juice!!!(4)
Tomato Carrot Onion Juice!!!(5)

「何コレ?」 まず注目するのは「function juice(){ 処理 }」の部分。ここで行っているのは、「関数の定義」です。「関数の定義」は、「function」の後ろに「関数名()」、そしてその後ろに「{ 一連の処理 }」を記述して行います。

関数は、定義しただけでは何も起こりません。関数内の処理を実行するには、関数を呼び出す(コールする)必要があります。サンプルの中の「for($i = 0; $i < 5; $i = $i + 1){ juice(); }」の部分が、「関数juice()」を呼び出している所です。「for文」で5回呼び出しているので、5回処理が実行されています。

このように、関数は一連の決まった処理を何回も実行させたい時に便利なのですが、関数の本来の役割は、「与えられた値を加工して返す」というものです。

ちなみに、サンプルコードの中の「$vege1.$vege2.$vege3."Juice!!!(".$num.")<br />"」の部分ですが、この中の「.(ドット)」は、結合演算子(「演算子」のページで解説)というもので、「左右のオペランド(被演算子)の文字列(文字列で無い場合は文字列として)を連結し、連結したものを返す」という働きをします。よって、この部分は、「変数$vege1」と「変数$vege2」「変数$vege3」と「"Juice!!!("」と「変数$num」と「")<br />"」が結合され、「Tomato Carrot Onion Juice!!!(n)(「n」は関数が呼び出された回数)」となります。

関数にも名前を付けましょう

関数も変数同様、命名規則に沿って名前を付けなければなりません。基本的に変数の時と同じですが、「大文字と小文字を区別しない」という点で異なります。また、後で解説しますが、PHPには既に定義されている関数が幾つか(1000個以上)あり、これらと重複してはいけません。更に、PHPには「予約語」と呼ばれる、PHPにおいて意味のあるワードがあり、これらとも重複してはいけません。この予約語には、既に解説した制御構造(「if」等)やその他諸々があります(詳しくは本家のマニュアルの「付録」セクションの「予約語の一覧」のページをご参照下さい)。重複させるとエラーになります。しかし、これらの名前の付けられ方にはちょっとクセがあるので、そのクセを見付けて回避すれば、特に神経質になる必要はありません。

関数名の命名規則の、変数名の場合との相違点
  • 大文字と小文字を区別しない。つまり、「hode()」と定義した関数を「HODE()」で呼び出せる。
  • 関数名は、PHP側で定義済みの関数の名前及び予約語と重複してはならない。
  • また、既に定義した関数とも重複してはならない。これは、関数の再定義が出来ない事を意味します。

また、PHPは「__(アンダーバー2本)」で始まる全ての関数名を特殊な関数として予約(将来定義されるかもしれない)しているため、この「__(アンダーバー2本)」で始まる関数名は使用しない事が推奨されています。

関数の役目

引数

関数は一連の決まった処理を何回も実行させたい時に用いると便利ではありますが、関数が果たすべき最も重要な役目は、「与えられた値を加工して返す」というものです。これを踏まえて、以下のサンプルと結果をご覧下さい。

<html>
<body>
<p>
<?php
    function juice($vege1, $vege2, $vege3){
        static $num = 1;
        $juice = $vege1.$vege2.$vege3."Juice!!!(".$num.")<br />";
        echo $juice;
        $num = $num + 1;
    }
    
    for($i = 0; $i < 5; $i = $i + 1){
        juice("Tomato ", "Carrot ", "Onion ");
    }
?>
</p>
</body>
</html>
Tomato Carrot Onion Juice!!!(1)
Tomato Carrot Onion Juice!!!(2)
Tomato Carrot Onion Juice!!!(3)
Tomato Carrot Onion Juice!!!(4)
Tomato Carrot Onion Juice!!!(5)

結果は前回とたまたま同じですが、関数定義の部分と関数を呼び出している部分に追加されたものがあります。いずれも関数名の後の「()」の中に、関数定義の部分には「$vege1, $vege2, $vege3」が、関数を呼び出している部分には「"Tomato", "Carrot", "Onion"」が追加されています。

関数名の後ろにある「()」ですが、これは飾りではなく、「引数(ひきすう)」と呼ばれるもので、ここに値を指定する事で、関数は与えられた値を使って処理します。

今回のサンプルの場合は、関数を呼び出している部分の「"Tomato", "Carrot", "Onion"」の「,(カンマ)」で区切られた3つの値が、定義された関数の「$vege1, $vege2, $vege3」の同じく「,(カンマ)」で区切られた3つの変数に代入されて、この変数は関数のローカル変数として処理に使われています。

仮引数と実引数

前回のサンプルの、関数呼び出し部の「"Tomato", "Carrot", "Onion"」と、定義された関数の「$vege1, $vege2, $vege3」をそれぞれ、「実引数」、「仮引数」と言います。定義時に指定する方が「仮引数」、呼び出し時に指定する方が「実引数」です。当然の事ながら、仮引数と実引数の数は一致していなければいけません。

実引数の省略と仮引数のデフォルト値

「仮引数と実引数の数は一致していなければいけません」と書きましたが、実際はそうでなくてもいい場合もあります。要するに、実引数を省略する事が可能な場合もあるのです。これを踏まえて、以下のサンプルと結果をご覧下さい。

<html>
<body>
<p>
<?php
    function juice( $vege1 = "Tomato ",
                    $vege2 = "Carrot ", $vege3 = "Onion " ){
        static $num = 1;
        $juice = $vege1.$vege2.$vege3."Juice!!!(".$num.")<br />";
        echo $juice;
        $num = $num + 1;
    }
    
    for($i = 0; $i < 5; $i = $i + 1){
        juice("Apple ");
    }
?>
</p>
</body>
</html>
Apple Carrot Onion Juice!!!(1)
Apple Carrot Onion Juice!!!(2)
Apple Carrot Onion Juice!!!(3)
Apple Carrot Onion Juice!!!(4)
Apple Carrot Onion Juice!!!(5)

今回のサンプルでは、仮引数が3つなのに、実引数は1つしかありません。が、ちゃんと機能しています。

そしてサンプルコードを見ると、仮引数に、「$vege1 = "Tomato ", $vege2 = "Carrot ", $vege3 = "Onion "」と、値を代入しています。この、仮引数に代入された値を、「デフォルト値」と言います。実引数が省略された場合、このデフォルト値が実引数として扱われます。

サンプルの結果を見ると、前回の結果と比較して「Tomato」が「Apple」になっているのが判ります。これは、唯一、第一引数(1つ目の引数)が指定されたためです。

しかし、デフォルト値の設定にはルールがあります。次のサンプルをご覧下さい。

<html>
<body>
<p>
<?php
    function juice($vege1 = "Tomato ", $vege2, $vege3){
        … 省略 …
    }
    
    … 省略 …
?>
</p>
</body>
</html>

このサンプルでは、仮引数の第一引数のみにデフォルト値を設定しています。はてさて、この関数を呼び出す時、どのように呼び出すのでしょうか?第二引数と第三引数は省略できないので指定しなければいけませんが、第二引数、第三引数は、それぞれ2番目、3番目になければいけないので、当然第一引数も指定しなければいけなくなります。という事は、サンプルのデフォルト値は全くの無意味になってしまいます。この書き方でエラーになるわけではありませんが、無意味という点で、間違った書き方です。

そんな訳で、仮引数の一部にデフォルト値を設定したい場合は、デフォルト値を設定した変数を右側に寄せる必要があります。以下にサンプル。

<html>
<body>
<p>
<?php
    function juice($vege2, $vege3, $vege1 = "Tomato "){
        … 省略 …
    }
    
    … 省略 …
?>
</p>
</body>
</html>

返り値

「・・・。アレェ!?「関数が果たすべき最も重要な役目は与えられた値を加工して返すだ」なんて言ってたけどよ、「返す」って何なんだ?オイ!コノ野郎!「返す」って何を返してんだか解かんねーよ!」
「・・・お客様がおかけになった電話番号は、現在使われておりません・・・。」
「余り似ていない事で有名な西郷隆盛の肖像画ですが、アレを描いたのはイタリア人です。。。」
「へぇ。」
「・・・。」

「関数が果たすべき最も重要な役目は与えられた値を加工して返すです」と書いていましたが、残念ながら、前回までのサンプルでは、関数は何も返していません。では、以下の、何かを「返す」サンプルと結果をご覧下さい。

<html>
<body>
<p>
<?php
    function juice($vege1, $vege2, $vege3){
        static $num = 1;
        $juice = $vege1.$vege2.$vege3."Juice!!!(".$num.")<br />";
        $num = $num + 1;
        return $juice;
    }
    
    for($i = 0; $i < 5; $i = $i + 1){
        $juice = juice("Tomato", "Carrot", "Onion");
        echo $juice;
    }
?>
</p>
</body>
</html>
Tomato Carrot Onion Juice!!!(1)
Tomato Carrot Onion Juice!!!(2)
Tomato Carrot Onion Juice!!!(3)
Tomato Carrot Onion Juice!!!(4)
Tomato Carrot Onion Juice!!!(5)

今回のサンプルには、新たに「return $juice;」と言うものが追加されました。また、関数を呼び出す部分は、「$juice = juice("Tomato", "Carrot", "Onion");」となっています。

まず、関数定義内の「return」ですが、これは、「その時点で関数の処理を終了して(その後に処理が残っていても実行せず)、パラメータ(引数)(「$juice」)の値を返す」という働きをもちます。

この、「返す」という言葉の意味ですが、これは、「関数を呼び出した部分に値を返す」という意味です。「それではスタジオにお返ししまーす」みたいなイメージです。よって、関数呼び出し部分の「$juice = juice("Tomato", "Carrot", "Onion");」は、「$juice = Tomato Carrot Onion Juice!!!(n);(「n」は関数が呼び出された回数)」と同じ意味になります。

そして、この、返って来る値の事を「返り値(「戻り値」、「リターン値」とも言う)」と言います。また、関数が返す値は「関数値」と言います。

なお、この「関数値」には、処理した結果だけではなく、処理に成功したか、何らかの理由で処理に失敗したかを表す真偽値を指定し、例えば「if文」の条件式に使えば、コールした関数の処理が成功したか否かによって、処理を分岐させるという事も出来ます。

ローカル変数がローカルスコープな わけ

「変数」のページで、「変数には定義された場所によって参照範囲が制限される」と書きましたが、参照出来ないという事は、関数内と関数外で同じ名前の変数を定義しても、それらは別の変数として扱われる事を意味します。これにより、グローバル変数に名前を付ける時に、関数内で使われている変数の名前を気にする必要がなくなるわけです。

可変関数

変数に可変変数があるように、関数にも「可変関数」なるものがあります。これの書き方のサンプルを以下に。

<html>
<body>
<p>
<?php
    function hode(){
        echo "HODENASU!!";
    }
    
    $kahen = "hode";
    
    $kahen();
?>
</p>
</body>
</html>

結果やいかに。

HODENASU!!

結果から、「関数hode()」が実行されているのが判ります。

で、呼び出し部分を見てみると・・・、何か変です。変数の後ろに「()」が引っ付いています。

解説すると、「変数$kahen」には文字列の「"hode"」が格納されていて、この「"hode"」の後ろに「()」を付けると、「関数hode()」になります。すると、この「関数hode()」がコールされます。当然、存在しない関数名だと、エラーになります。

ユーザー定義関数と内部(ビルトイン)関数

ユーザー定義関数」とは、今まで書いてきた「juice()」や「hode()」などの関数の事です。要するに、スクリプト作成者が自分で定義した関数の事です。これに対して、既に何度か書きましたが、PHP側で既に定義されている1000以上の関数の事を、「内部(ビルトイン)関数」と言います。以下に、内部(ビルトイン)関数のサンプルと結果を。

<html>
<body>
<p>
<?php
    $time = time();
    $date = date("Y/m/d", $time);
    
    echo $date;
?>
</p>
</body>
</html>
2004/05/16

今回のサンプルでは、2つの内部(ビルトイン)関数を使用しています。「time()」と「date()」です。

time()」は、「現在のUNIXタイムスタンプ(1970年01月01日 00時00分00秒 GMT からの経過秒数)を返す」という処理をし、「date()」の方は、「第二引数に指定されたタイムスタンプを元に、第一引数に指定したフォーマットの日付文字列を返す」という処理をします。詳しくは本家のマニュアルをご参照下さい。

おさらいと予告

以上で関数の解説は終わりです。

関数とは

  • 関数は、定義するだけでは何もせず、呼び出されて初めて処理を実行する。
  • 関数名には、変数名同様、命名規則があるが、相違点が幾つかある。また、「__(アンダーバー2本)」で始まる関数名は使用しない事が推奨されている。
  • 関数は再定義出来ない。
  • 関数を呼び出す時に指定する引数は「実引数」で、定義部分の引数は「仮引数」と言う。
  • 関数は「return文」によって、その時点で処理を終了し、値を返す。返された値を「返り値」と言う。
  • 文字列(関数名)を格納した変数の後ろに「()」を置くと、その関数名の関数がコールされる(可変関数)。
  • スクリプト作成者が自分で定義した関数を「ユーザー定義関数」、PHP側で既に定義されている関数を「内部(ビルトイン)関数」と言う。

男に二言は、無ぇ。

次回は、関数同様、一度定義したら再定義は出来ない「定数」について解説します。

作成日:2004年05月14日 最終更新日:2004年05月20日
【通常モード で表示】