PHPにおける関数:同じような処理をまとめて扱うしくみ

2015年3月11日(水)
野田 貴子

はじめに

これから始めるPHP入門コラムでは、PHPを学ぶ人が、PHPで簡単なプログラムを書けるようになるまでに必要な知識とポイントをTips的に書いていきます。今後PHPのスキルを身につけて仕事に役立てたい、という方のために「PHP技術者認定初級試験」の出題範囲を意識しながら進めていきますので、ぜひ最後までお付き合いください。

今回のあらすじ

  1. 関数の使い道(1)
  2. 関数から結果(返り値)を受け取る方法
  3. 引数のデフォルト値を設定する
  4. 関数の使い道(2)
  5. 関数内での変数のスコープ

関数の使い道(1)

プログラムを書いていて、同じような処理が2回以上現れることってありますよね。下のコードの「消費税込みの金額と改行を出力する」という部分に着目しましょう。

1// リンゴ:値段を決める
2$apple_price = 100;
3// リンゴ:消費税込みの金額と改行を出力する。
4echo floor($apple_price * 1.08) . "\n";
5 
6// みかん:値段を決める
7$orange_price = 70;
8// みかん:消費税込みの金額と改行を出力する。
9echo floor($orange_price * 1.08) . "\n";

こういうときは、同じような処理を「関数」として一ヶ所にまとめておくと便利です。PHPにはsubstrのように最初から用意されている関数もありますが、自分で関数を作ることもできます(ユーザー定義関数)。まずは関数の作り方(宣言方法)を見てみましょう。

1// 消費税込みの金額と改行を出力する関数の宣言
2function echo_price_inc_tax($price) {
3    echo floor($price * 1.08) . "\n";
4}

この関数では、第一引数(pricepriceは、この関数の内部で使うためのもので、別の名前でも構いません。

「echo_price_inc_tax」という関数名は、すでにある関数と被らない限り、自由に付けることができます。関数名は大文字と小文字を区別しないので、上記の関数は「echo_PRICE_inc_TAX」という名前でも参照できます。

なお、関数名は自由に付けられると書きましたが、「echo_zeikomi」のように日本語で付けるのは避けた方がよいでしょう。せっかくプログラミングは世界共通言語なのですから、いつ海外のプログラマーが開発に参加しても困らないように、そして私たちも英語で書く癖を付けられるように、変数名や関数名は英語で付けましょう。
また、プログラマー自身や開発チームによって、命名ルールが設けられていることもあります。

ユーザー定義関数の使い方は、これまでに使ったことのあるsubstrなどのPHP関数と同様です。このように書けば、

1echo_price_inc_tax(200);

以下のように実行されます。

1echo floor(200 * 1.08) . "\n";

関数を使うことで、冒頭のコードは次のように書き換えられます。なおPHPの場合、プログラム内での関数の宣言をする位置は、関数を使う場所より前でも後でも構いません。

01// リンゴ:値段を決める
02$apple_price = 100;
03// リンゴ:消費税込みの金額と改行を出力する。
04echo_price_inc_tax($apple_price);
05 
06// みかん:値段を決める
07$orange_price = 70;
08// みかん:消費税込みの金額と改行を出力する。
09echo_price_inc_tax($orange_price);
10 
11// 消費税込みの金額と改行を出力する関数の宣言
12function echo_price_inc_tax($price) {
13    echo floor($price * 1.08) . "\n";
14}

この例の場合、関数にまとめることで、良いことが2つあります。

(1)同じ処理を書いたはずが間違ってしまうという可能性を防ぐことができる

下のコードを見てください。リンゴと同じように書いたはずが、一文字だけ間違っています。たった一文字でもこれは大きな間違いですが、大量のコードの中で、このような間違いを見つけることはとても難しいことです。

1// レモン:消費税込みの金額と改行を出力する。
2echo floor($lemon_price + 1.08) . "\n";

関数にしておけば、書き間違いにより処理が異なってしまう可能性は低くなります。また、自分以外の人が同じ処理を書く場合にも、統一が取れるようになります。

1// レモン:消費税込みの金額と改行を出力する。
2echo_price_inc_tax($lemon_price);

(2)修正するときに一ヶ所を修正するだけで済む

消費税はいつまでも8%であるとは限りません(2015年3月現在)。いずれ10%になってしまったら、1.08になっている部分をすべて1.1に修正しないといけません。他の可能性としては、将来のバージョンアップで税込み価格の後ろの改行("\n")を削除するかもしれません。その場合でも、関数にしておけば一ヶ所を修正するだけで済みます。

01関数を使わない場合の修正部分
02// リンゴ:消費税込みの金額と改行を出力する。
03echo floor($apple_price * 1.1);
04// みかん:消費税込みの金額と改行を出力する。
05echo floor($orange_price * 1.1);
06 
07関数を使う場合の修正部分
08// 消費税込みの金額と改行を出力する関数
09function echo_price_inc_tax($price) {
10    echo floor($price * 1.1);
11}

関数から結果(返り値)を受け取る方法

さて、「税込み金額は知りたいけれど、出力はしたくない」という場合があるかもしれません。そのような場合は、returnを使って関数から結果(返り値)を返すことができます。

1// 消費税込みの金額と改行を返す関数の宣言
2function get_price_inc_tax($price) {
3    return floor($price * 1.08) . "\n";
4}

このように書けば、

1$price_inc_tax = get_price_inc_tax(200);

以下のように実行されます。

1$price_inc_tax = floor(200 * 1.08) . "\n";

また、returnを複数使って、条件によって返り値の求め方を変えることができます。

01// 消費税込みの金額と改行を返す関数の宣言
02function get_price_inc_tax($price, $year) {
03    // 消費税8%時代の場合
04    if ($year >= 2014) {
05        return floor($price * 1.08) . "\n";
06    }
07    // 消費税5%時代の場合
08    if ($year >= 1997) {
09        return floor($price * 1.05) . "\n";
10    }
11    // 消費税3%時代の場合
12    if ($year >= 1989) {
13        return floor($price * 1.03) . "\n";
14    }
15    // 消費税導入前の場合
16    return $price . "\n";
17}

ただしこの例の場合は、以下のように書くほうが一般的です。同じ処理(「 . "\n"」の部分など)は、なるべく繰り返さないようにしましょう。

01// 消費税込みの金額と改行を返す関数の宣言
02function get_price_inc_tax($price, $year) {
03    // 消費税8%時代
04    if ($year >= 2014) {
05        $tax = 8;
06    }
07    // 消費税5%時代
08    else if ($year >= 1997) {
09        $tax = 5;
10    }
11    // 消費税3%時代
12    else if ($year >= 1989) {
13        $tax = 3;
14    }
15    // 消費税導入前
16    else {
17        $tax = 0;
18    }
19    return floor($price * (1 + $tax/100)) . "\n";
20}

引数のデフォルト値を設定する

先ほどの関数「get_price_inc_tax」を使う場合には、2つの引数を両方とも指定しないとエラーになります。

1// 消費税込みの金額と改行を返す関数の宣言
2function get_price_inc_tax($price, $year) {
3    ...
4}
5$apple_price_inc_tax = get_price_inc_tax(100);
6// PHPエラー
7// Warning: Missing argument 2 for get_price_inc_tax(), called in ...

しかし、いちいち$yearの値を指定するのは面倒かもしれません。

1$apple_price_inc_tax = get_price_inc_tax(100, 2015);
2$orange_price_inc_tax = get_price_inc_tax(70, 2015);

この場合、次のように書けばyearyearを指定せずに関数を呼び出すと、代わりに2015が使われます。

1// 消費税込みの金額と改行を返す関数の宣言
2function get_price_inc_tax($price, $year = 2015) {
3    ...
4}
5// $price = 100、$year = 2015が使われる
6$apple_price_inc_tax = get_price_inc_tax(100);
7// $price = 110、$year = 2010が使われる
8$old_apple_price_inc_tax = get_price_inc_tax(110, 2010);

関数の中から別の関数を呼ぶ

関数の中から、さらに別の関数を呼ぶこともできますので、先ほどの「get_price_inc_tax」は以下のように書き換えることができます。

1// 消費税込みの金額と改行を出力する関数の宣言
2function echo_price_inc_tax($price) {
3    // 修正前:echo floor($price * 1.08) . "\n";
4    echo get_price_inc_tax($price);
5}
6// 消費税込みの金額と改行を返す関数の宣言
7function get_price_inc_tax($price) {
8    return floor($price * 1.08) . "\n";
9}

1983年生まれ。大学卒業後、ソフトウェア開発の営業を経て、ソフトウェア開発業務に転向。現在は自社パッケージのフロントエンド開発のほか、PHPでの受託開発案件、日→英のローカライズ案件などを担当。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています