初心者による初心者のためのPHP講座 第9回 関数の定義

初心者による初心者のためのPHP講座 第9回 関数の定義この講座でも、echo()を始めとして、date()、define()、array()、explode()、extract()などの様々な関数が登場している。(厳密には関数でないものも含まれるが・・・。)

これらは、PHPが標準で備えている関数であり、構文と並んでPHPでのプログラミングの基本となる要素であるが、「ユーザー定義関数」として自身で関数を定義することも出来る。

関数については「初心者による初心者のためのPHP講座 第2回 PHPの基本構造」で触れているので、もう一度おさらいして欲しい。

ユーザー定義関数は、比較的小規模な処理を1つにまとめたもので、PHPのプログラムは、複数の「ユーザー定義関数」を組み合わせて実行させることで成立しているとも言える。

他の言語では、PHPの関数のような、ひとまとまりの処理を「サブルーチン」と呼ぶ場合もある。

ユーザー定義関数は、下記のようにfunction文を用いて定義する。

function 関数名() {
	処理1;
	処理2;
	処理3;
	.
	.
	.
}

関数は、1つまたは複数の引数を取ることもあるが、その場合は

function 関数名(引数1, 引数2, 引数3...) {
	処理1;
	処理2;
	処理3;
	.
	.
	.
}

となる。

関数名には、英数字、アンダースコアを使用することが出来るが、最初の一文字は、アルファベットかアンダースコアでなければならない。

戻り値を参照渡しする場合に、「&」で始まる関数を定義することがあるが、厳密には「&」は変数名の一部ではなく、「&関数名」となっている。

ユーザー定義関数を実行する場合は、標準の関数を実行する場合と同様に

関数名();

または

関数名(引数1, 引数2, 引数3...);

とすれば良い。

また、ユーザー定義関数の戻り値を別の関数の引数として用いることも出来る。

<?php
echo my_string();
round(my_value(), 2);
// my_string()とmy_value()はユーザー定義関数
?>

このあたりは、PHPの標準関数と同じである。

下記の例では、get_date_yesterday()という関数を定義しているが、これは昨日が何曜日だったかを求め、それを戻り値として返す関数である。

<?php
echo get_date_yesterday();

function get_date_yesterday() {
	$yesterday = time() + (60 * 60 * 9) - (60 * 60 * 24 * 1);
	// $yesterday = time() + (60秒 * 60分 * 9時間) - (60秒 * 60分 * 24時間 * 1日);
	$date_yesterday = date('l', $yesterday);
	return $date_yesterday;
}
?>

time()関数は、現在の時刻が、1970年1月1日0時0分から何秒経過したか求める関数であるが、 GMT基準であるため、日本時間に修正した上で、1日分の秒数を引いている。

こうして補正した秒数をdate()関数で整形し、曜日を求めている。

最後にreturn()を使って、戻り値として変数$date_yesterdayの値を返している。

return()は、処理を中断し、その引数を戻り値として返すが、echo()などと同様に厳密には関数ではないため、通常は、()は使わずに

return 引数(戻り値となる値、変数);

のように記述する。

戻り値として値を返さず、echo()関数で表示することが前提なら

<?php
get_date_yesterday();

function get_date_yesterday() {
	$yesterday = time() + (60 * 60 * 9) - (60 * 60 * 24 * 1);
	// $yesterday = time() + (60秒 * 60分 * 9時間) - (60秒 * 60分 * 24時間 * 1日);
	$date_yesterday = date('l', $yesterday);
	echo $date_yesterday;
}
?>

としても良い。これは戻り値を返さない関数になる。

関数は引数を取ることで、更に柔軟になる。

以下の例では、GMTとの時差に部分と、何日前の部分を引数として指定出来るようになっている。

<?php
echo get_date_before(9, 2);

function get_date_before($diff, $ago) {
	$before = time() + (60 * 60 * $diff) - (60 * 60 * 24 * $ago);
	// $before = time() + (60秒 * 60分 * 9時間) - (60秒 * 60分 * 24時間 * 1日);
	$date_before = date('l', $before);
	return $date_before;
}
?>

上記のサンプルでは、日本時間での一昨日前の曜日が表示されるが、

echo get_date_before(-8, 1);

とすれば、(夏時間の時期を除く)アメリカ太平洋標準時での昨日の曜日となる。

また、下記のように関数の定義内で別の関数を定義し、それを実行することも出来る。

<?php
echo check_holiday(9, 1);

function check_holiday($diff, $ago){

	function get_date_before($diff, $ago) {
		$before = time() + (60 * 60 * $diff) - (60 * 60 * 24 * $ago);
		// $before = time() + (60秒 * 60分 * 9時間) - (60秒 * 60分 * 24時間 * 1日);
		$date_before = date('l', $before);
		return $date_before;
	}

	$date = get_date_before($diff, $ago);

	if ($date == 'Saturday' || $date == 'Sunday') {
		return "休日";
	} else {
		return "平日";
	}

}
?>

この関数は、曜日が土曜日か日曜日なら「休日」と返す。

このように別の関数の定義をネストする場合は、関数を呼び出す前に、関数を定義しておくことがポイントになる。

また、上記のサンプルは、下記のように記述することも出来る。

<?php
echo check_holiday(9, 1);

function check_holiday($diff, $ago){
	$date = get_date_before($diff, $ago);

	if ($date == 'Saturday' || $date == 'Sunday') {
		return "休日";
	} else {
		return "平日";
	}

}

function get_date_before($diff, $ago) {
	$before = time() + (60 * 60 * $diff) - (60 * 60 * 24 * $ago);
	// $before = time() + (60秒 * 60分 * 9時間) - (60秒 * 60分 * 24時間 * 1日);
	$date_before = date('l', $before);
	return $date_before;
}
?>

このように記述することでget_date_before()関数を別の処理でも再利用しやすくなる利点もある。

更に下記のように記述すれば、check_holiday()関数は、単に与えられた曜日が平日か休日かを判断する関数となり、汎用性が高くなる。

<?php
echo check_holiday(get_date_before(9, 1))."<br />";
echo check_holiday(get_date_before(-8, 2))."<br />";
echo get_date_before(-8, 2);

function check_holiday($date){

	if ($date == 'Saturday' || $date == 'Sunday') {
		return "休日";
	} else {
		return "平日";
	}

}

function get_date_before($diff, $ago) {
	$before = time() + (60 * 60 * $diff) - (60 * 60 * 24 * $ago);
	// $before = time() + (60秒 * 60分 * 9時間) - (60秒 * 60分 * 24時間 * 1日);
	$date_before = date('l', $before);
	return $date_before;
}
?>

関数を定義する際は、出来る限り再利用しやすい形にした方が、プログラミングの効率も良い。

また、似たような処理を複数回記述する必要がある場合は、その部分をユーザー定義関数として独立させた方が良い。

以上のような処理は、ユーザー定義関数を使わなくとも簡単に記述できる。

<?php
$diff = 9;
$ago = 1;

$before = time() + (60 * 60 * $diff) - (60 * 60 * 24 * $ago);
// $before = time() + (60秒 * 60分 * 9時間) - (60秒 * 60分 * 24時間 * 1日);
$date_before = date('l', $before);

if ($date_before == 'Saturday' || $date_before == 'Sunday') {
	echo "休日";
} else {
	echo "平日";
}
?>

しかし、処理の再利用を前提とした場合、ユーザー定義関数が重要であることの理解は難しくないだろう。

関数を自身で定義し、複雑な処理を記述出来るようになると、必ず「変数のスコープ」を意識する必要が生じる。

「変数のスコープ」については、別の機会にお話ししたいと考えている。



PHP, PHP講座, ネット・PCPermalink
  • http://twitter.com/kwauch みーにゃ

    こんにちは!みーにゃと申します。他の文具ブロガーさんのコメント欄でお名前は何度か拝見したことありましたが、phpについて検索していてたどり着きました。ああ~、お名前知ってる方だ~と嬉しくなったので足跡を残させてもらいます。
    Wordpressを使い始めましたが、PHPはよく分からないので勉強させてもらいます~!
    トップの写真も素敵ですね!

    • RedCocker

      文具とPHPとは奇遇ですね。これからもよろしくお願いいたします。