初心者による初心者のためのPHP講座 第8回 ループ処理

初心者による初心者のためのPHP講座 第8回 ループ処理PHPでは、同じ処理を繰り返し実行するための「ループ処理」を記述出来る。

ループ処理は、PHPでは、出番が多い構文であり、必ずマスターしておくこと。

while構文

while構文はシンプルなループを記述するための構文で、if文と似ている。

while (式) {
	処理
}

if文の場合は、式が真の場合に処理を実行するが、while文の場合は、式が真である限り、同じ処理を繰り返し実行する。

下記のサンプルは、$countが6未満であれば処理を繰り返す。

$countの初期値は1であり、処理が実行される度に1加算される。

<?php
$count = 1;
while ($count < 6) {
        echo $count;
	$count++;
}
?>

従って、上記のサンプルを実行すると「12345」と表示される。

for構文

for構文は、while構文と比較すると複雑な構文で、繰り返しの条件を定義するために3つの式を必要とする。

for (式1; 式3; 式3) {
	処理
}

式1は、whileを開始した時に1度だけ実行され、式2は、処理に実行を完了する度に実行される。そして、式3が真であれば処理が繰り返される。

複雑ではあるが、以下のように読み替えると理解しやすい。

for (初期値; 条件式; 増減) {
	処理
}

式1で変数の初期値を定義し、式3で変数の増減を定義しておけば、式2の条件式で変数を評価することで意図した回数ループを繰り返すことが出来る。

<?php
for ($count = 1; $count < 6; $count++) {
        echo $count;
}
?>

上記のサンプルでは、$countの初期値が1で、処理の度に1増える。

そして、$countが6未満なら処理が繰り返されるため、実行すると「12345」と表示される。

次のサンプルでは、複数の変数の初期値と増減を記述している。

<?php
for ($count = 1, $value = 5; $count < 6; $count++, $value--) {
        echo "\$count:".$count." \$value:".$value."<br />";
}
?>

複数の変数の初期値と増減を記述する場合は、それらをカンマで区切ること。

for構文は、次のように記述しても良い。

for (式1; 式2; 式3):
	処理
endfor;

do~while構文

while構文やfor構文が、まず条件式を評価した上で、条件式が真であれば処理を繰り返すのに対して、do~while構文は、まず処理を実行してから、条件式の評価が行われる。

つまり、条件を満たしているか否かに関係なく、少なくとも1回の処理が実行され、2回目以降は、条件式が真である場合のみ繰り返される。

do {
	処理スクリプト
} while(式);

条件評価と処理の順序が逆であるが、基本的にはwhile構文と似ている。

次にサンプルは、$valの初期値が既に条件を満たしていない。

<?php
$val = -1;
do {
	echo $val;
} while ($val > 0);
?>

しかし、do~while構文では、条件の評価より先に処理が実行されるため、「-1」と表示される。

foreach構文

foreach構文は、配列を処理するために使われる配列専用のループ構文である。

だからと言って、配列にfor構文などを使用してはいけないという訳ではない。

foreach構文が優れている点は、ごく簡単な記述で、配列から要素を1つずつ取り出して処理出来る点である。

構文は下記のようになる。

foreach(配列 as $value) {
	処理
}

または

foreach(配列 as $key => $value) {
	処理
}

foreach構文では、配列から要素を取り出し、取り出した要素の値が自動的に変数$valueに代入される。

そして、この処理を、配列の先頭から最後まで繰り返す。

また、演算子「=>」を用いることで、配列から取り出された要素のキーと対応する値を、$key、$valueに代入させることも出来る。

なお、受け皿となる変数名は、$key、$value以外でも構わない。

おそらく、具体的な処理を見た方が理解しやすいだろう。

以下では、全ての要素からキーと値を取り出して表示させてる。

<!doctype html>
<?php echo '<?xml version="1.0" encoding="utf-8"?>'; ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>foreach文で連想配列を処理</title>
</head>
<body>
<?php
$members = array('suzuki' => 13, 'yamada'=> 25, 'tanaka' => 46);

foreach($members as $name => $age) {
	echo "名前:".$name."<br />";
	echo "年齢:".$age."<br /><br />";
}
?>
</body>
</html>

上記のスクリプトの実行結果を表示

下記のサンプルでは、要素の値の書き換えを行なっている。

<?php
$members = array('suzuki' => 13, 'yamada'=> 25, 'tanaka' => 46);

foreach($members as $name => $age) {
	$members[$name] = $age * 2;
}

print_r($members);
?>

処理としては、単に年齢を2倍しているだけであり、下記のサンプルのように変数の「参照渡し」を利用し、直接、要素を書き換えて同様の処理を行うことも出来る。

<?php
$members = array('suzuki' => 13, 'yamada'=> 25, 'tanaka' => 46);

foreach($members as $name => &$age) {
	$age = $age * 2;
}

print_r($members);
?>

「$gae」ではなく「&$age」としている点がこの処理のポイントである。

ループのネスト

ループ内にループを記述して多重ループを構成することも出来る。

<?php
$a = 1;

while ($a < 3) {
	$b = 1;

	while ($b < 3) {
		echo "\$a:".$a." \$b:".$b."<br />";
		$b++;
	}

	$a++;
}
?>

上のサンプルでは、外側のwhile文が1回実行される毎に内側のwhile文が3回実行される。

外側のwhile文は3回実行されるので、内側のwhile文内の処理echo()は、計9回実行されることになる。

break

「break」は、switch構文の際にも用いたが、ループ構文に対しても使用可能で、while、for、do~while、foreach構文の処理を中断し、ループを抜けることが出来る。

次の例では、「suzuki」というキーを持つ要素の値を表示している。

<?php
$members = array('suzuki' => 13, 'yamada'=> 25, 'tanaka' => 46);

foreach($members as $name => $age) {
	if ($name == "suzuki") {
		echo $age;
	}
}
?>

上記の例では、「suzuki」に一致するキーが見つかった時点で、以後の繰り返しは無駄になってしまう。

従って、以下のようにbreakを使ってループから抜けるのが適切な処理と言える。

<?php
$members = array('suzuki' => 13, 'yamada'=> 25, 'tanaka' => 46);

foreach($members as $name => $age) {
	if ($name == "suzuki") {
		echo $age;
		break;
	}
}
?>

無駄な処理は、処理の遅延や負荷を生む原因になるため、breakを使用することを心掛ける必要がある。

ネストされたループ処理をbreakで抜ける場合は注意が必要である。

break文では、ループ構造を抜ける回数を指定できるので、例えば2重のループを完全に抜ける場合は、

break 2;

と言った記述を行う必要がある。

なお、サンプルのようにループ構造を抜ける回数を指定しなかった場合は、「1」と見なされる。

continue

ループの中で「continue」が記述されていると、それ以降の処理をスキップして、この回の繰り返しを終了し、条件式の評価を行い、真ならば次の繰り返しを実行する。

以下のサンプルでは、「continue」を使って、キーが「yamada」の場合のみ、echo()による出力を行わないようにしている。

<?php
$members = array('suzuki' => 13, 'yamada'=> 25, 'tanaka' => 46);

foreach($members as $name => $age) {
	if ($name == "yamada") {
		continue;
	}

	echo "名前:".$name."<br />";
	echo "年齢:".$age."<br /><br />";
}
?>

ループとループ内の変数

以下のサンプルの実行結果が予想出来るだろうか?

<?php
$count = 1;
while($count < 6) {
	echo $count;
	$count++;
}

echo $count;
?>

これは、どうだろうか?

<?php
for ($count = 1; $count < 6; $count++) {
        $val = $count *2;
}

echo $count;
?>

答えは、どちらも「6」である。

条件式やループ内で定義した変数は、ループ終了後も解除されず、生きているので、同じ変数を再度利用する場合は、注意が必要である。

特に複数のwhile文やdo~while文で、条件式に使う変数を使い回す場合は、都度、再定義してリセットすること。

続いて、foreach構文の場合を検証してみよう。

<?php
$members = array('suzuki' => 13, 'yamada'=> 25, 'tanaka' => 46);

foreach($members as $name => $age) {
	if ($name == "suzuki") {
		$members[$name] = $age * 2;
	}
}

echo "\$name:".$name."<br />";
echo "\$age:".$age."<br /><br />";
?>

上記のサンプルの実行結果は、

$name:tanaka
$age:46

となる。

つまり、キーや値の受け皿となる変数は解除されず、最後に取得した値が格納されたままになっている。

しかし、同様のforeach構文で同じ変数をキーや値の受け皿として使う場合は、再度、配列の先頭から取得し直すため、現状、どのような値が格納されているかは問題にならない。

とは言え、ループが終了した時点で、これらは基本的に不要な変数となるので、unset()関数で変数の割り当てを解除し、メモリから解放すると良い。

<?php
$members = array('suzuki' => 13, 'yamada'=> 25, 'tanaka' => 46);

foreach($members as $name => $age) {
	if ($name == "suzuki") {
		$members[$name] = $age * 2;
	}
}

unset($name);
unset($age);
?>



PHP, PHP講座, ネット・PCPermalink
  • Bharath Sago

    The Article is Informative. Have a look at bharathsago.com Sago
    Manufacturers.