「PHP/Webアプリケーション向けの機能」の版間の差分

削除された内容 追加された内容
Ef3 (トーク | 投稿記録)
タグ: 2017年版ソースエディター
Ef3 (トーク | 投稿記録)
→‎3つの分岐構文: PHPには、if, switch, match の3つの分岐構文があります。
タグ: 2017年版ソースエディター
25 行
:このように、生成するHTMLを動的に変更する場合、if文などによる条件分岐が活躍します。
 
== 3つの分岐構文 ==
PHPには、[[#if|if]], [[#switch|switch]], [[#match|match]] の3つの分岐構文があります。
 
=== if ===
=== シンプルでダーティーなログインフォーム ===
;コード例:<syntaxhighlight lang=php>
もし実用的に、PHPで条件分岐をする際は、よくある例として、ウェブサイト画面になにかの入力欄があって、その入力値をもとに条件判定することになるでしょう。
<?php
$n = NAN;
 
// 基本構文
ここでは例として、会員制サイトのログイン画面を考えてみます。
if ($n < 0) {
echo '$n < 0', PHP_EOL;
} elseif ($n > 0) {
echo '$n > 0', PHP_EOL;
} elseif ($n == 0) {
echo '$n < 0', PHP_EOL;
} else {
echo $n, PHP_EOL;
}
echo PHP_EOL;
 
// 代替構文
if ($n < 0):
echo '$n < 0', PHP_EOL;
elseif ($n > 0):
echo '$n > 0', PHP_EOL;
elseif ($n == 0):
echo '$n < 0', PHP_EOL;
else:
echo $n, PHP_EOL;
endif;
?>
 
<?php if ($n < 0): ?>
<?= '$n < 0' ?>
<?php elseif ($n > 0): ?>
<?= '$n < 0' ?>
<?php elseif ($n == 0): ?>
<?= '$n == 0' ?>
<?php else: ?>
<?= $n ?>
<?php endif; ?>
</syntaxhighlight>
;基本構文:<syntaxhighlight lang=php>
if ( 条件1 ) 文1 else if ( 条件式2 ) 文2 elseif ( 条件式3 ) 文3 … else 文
</syntaxhighlight>
: <code>else if</code>は<code>else if</code>のシノニムでそれぞれ0回以上繰り返せる。
: <code>else 文</code>は省略可能。
;代替構文:<syntaxhighlight lang=php>
if ( 条件式1 ):
文1
elseif ( 条件式2 ):
文2
else:
endif;
</syntaxhighlight>
:代替構文では<code>else if</code>は使えない
;埋込構文:<syntaxhighlight lang=php>
<?php if ( 条件1 ): ?>
テキスト1
<?php elseif ( 条件式2 ): ?>
テキスト2
<?php elseif ( 条件式3 ): ?>
テキスト3
<?php elseif ( 条件式n ): ?>
テキストn
<?php else: ?>
テキスト
<?php endif; ?>
</syntaxhighlight>
 
=== switch ===
;コード例:<syntaxhighlight lang=php>
</syntaxhighlight>
;基本構文:<syntaxhighlight lang=php>
</syntaxhighlight>
;代替構文:<syntaxhighlight lang=php>
</syntaxhighlight>
;埋込構文:<syntaxhighlight lang=php>
</syntaxhighlight>
 
=== match ===
;コード例:<syntaxhighlight lang=php>
</syntaxhighlight>
;基本構文:<syntaxhighlight lang=php>
</syntaxhighlight>
;代替構文:<syntaxhighlight lang=php>
</syntaxhighlight>
;埋込構文:<syntaxhighlight lang=php>
</syntaxhighlight>
 
== 条件分岐以外の話題 ==
=== シンプルでダーティーなログインフォーム ===
;login.php:<syntaxhighlight lang="php" line>
<!DOCTYPE html>
121 ⟶ 210行目:
</syntaxhighlight>
 
== 厳密な等価2つの比較演算子<nowiki>===</nowiki> ==
if や while なでの条件式で、使われる比較演算子には2種類あります。
if文などで等価を判定するさいのイコール演算子は、
 
; <code>==</code>:型を厳格には区別しない「緩やかな比較」
PHPでは少なくとも2種類ある。
; <code>===</code>:型を厳格に区別する「厳密な比較」
 
なお、<code>=</code>イコール1個は単なる代入命令ですが条件式で使われると代入された値を真理値として評価されます。
 
=== 緩やかな比較 ===
イコール記号2個の<code>==</code>と、
等号2個の<code>==</code>で評価した場合、
 
イコール記号3個の<code>===</code>である。
 
 
イコール記号2個では、型を区別'''しない'''。
 
イコール記号3個では、型を区別する。
 
 
なお、イコール1個だけでは単なる代入命令であるので、等価演算子としては機能しない。
 
=== 厳密でないイコール2個 ===
イコール記号2個の<code>==</code>で評価した場合、
 
下記コード、
 
:<syntaxhighlight lang="PHP"php>
<?php
 
$a = 1; //
 
if ($a == 1) {
printecho ("数字", "<br>") ;
}
 
if ($a == "1") {
printecho ("文字列", "<br>") ;
}
 
?>
</syntaxhighlight>
;実行結果
 
を実行すると
<pre>
数字
文字列
</pre>
:両方の場合でヒットしてしまいます。
 
のように、両方の場合にヒットしてしまいます。
 
<code>$a =1; </code> を代わりに<code>$a ="1"; </code>と宣言しても同様に両方ヒットの結果になります。
 
このように、数値として定義したつもりの変数が文字列としても解釈されたりする仕様は、便利な場合もありますが、ときには予想外の動作を引きおこすので使いたく無い場合もあります。そこで、下記のように、イコール3個の厳密な判定を行う等価演算子が用意されています。
175 ⟶ 250行目:
イコールの比較のさいの、型についての予想外の動作を防ぐための、より厳密な比較をできるイコール3個の演算子があります。
 
if文などでの比較の際、イコール記号3個の<code>===</code>で評価すると、数値型と文字列型とを区別して比較し、型も含めて同じ場合にだけ真になります。
 
:<syntaxhighlight lang="PHP"php>
<?php
 
198 ⟶ 273行目:
</pre>
 
このように、イコール等号3個で、型を厳密に区別して、等価かどうかを評価します。
 
 
* 余談
余談ですが、PHPは変数に値を代入する際、じつは型の情報も保管しています。なので、上記のように厳密評価も必要に応じて行えるわけです。
 
== match式 ==
2020年11月リリースされたPHP8から条件分岐にmatch式(match expression)が加わりました。
 
match式は、下記のように、引数の数値に基づいて場合分けをするときに、使います。
 
コード例
<syntaxhighlight lang="PHP">
<?php
$x = 1;
 
match ($x) {
0 => print("aaaa" . "\n"),
1 => print("qwer" . "\n"),
2 => print("test" . "\n") ,
};
?>
</syntaxhighlight>
:(※ PHP 8.1.6 で、2Fedora 36 にて 2022年05月24日に動作確認ずみ。)
 
実行結果
<pre>
qwer
</pre>
 
なお、switch文との違いとして、match式ではbreakが不要です。
 
macth式の方が便利なので、今後はmatch式の用例が増えると思います。
 
なお、match「式」(expression)とは言いますが、数学の「式」(equation, formula)とは別物です。プログラミング用語の"expression"とは、単に、関数や変数や演算子などを合わせた表現にすぎません。
 
 
match式では、下記のように、戻り値を変数(下記コードでは変数 $message )に入れることもできます。
 
コード例
<syntaxhighlight lang="PHP">
<?php
$x = 1;
 
$message = match ($x) {
0 => "aaaa",
1 => "qwerffff",
2 => "test" ,
};
 
print($message . "\n");
 
?>
</syntaxhighlight>
:(※ PHP 8.1.6 で、2Fedora 36 にて 2022年05月24日に動作確認ずみ。)
 
実行結果
<pre>
qwerffff
</pre>
 
 
なお、match式の引数の比較は、厳密なイコール3個の等号<nowiki>===</nowiki>で比較判定されています。
 
一方、switch式の引数の比較は、曖昧なイコール2個の等号<nowiki>==</nowiki>で比較判定されています。
 
 
 
;default
match式における条件わけの引数の値を下記のように <code>default</code> で、どれにもヒットしなかった場合の結果を示せます。
 
コード例
<syntaxhighlight lang="PHP">
<?php
$x = 5;
 
match ($x) {
0 => print("aaaa" . "\n"),
1 => print("qwer" . "\n"),
default => print("ddd" . "\n") ,
2 => print("test" . "\n") ,
};
?>
</syntaxhighlight>
 
実行結果
<pre>
ddd
</pre>
 
上記コード例では動作原理の説明のために意図的に default を最後には書きませんでしたが、普通のプログラミングでは下記のように default は最後に書きます。
 
コード例
<syntaxhighlight lang="PHP">
<?php
$x = 5;
 
match ($x) {
0 => print("aaaa" . "\n"),
1 => print("qwer" . "\n"),
2 => print("test" . "\n") ,
default => print("ddd" . "\n") ,
};
?>
</syntaxhighlight>
 
実行結果は同様に<code>ddd </code> です。
 
 
 
分岐後のすべての処理の出だしが print() など共通の処理の場合、下記コードのように<code>print match()</code>とも出来る。
 
;コード例
<syntaxhighlight lang="PHP">
<?php
$x = 0;
 
print match ($x) {
0 => "aaaa" . "\n" ,
1 => "qwer" . "\n" ,
2 => "test" . "\n" ,
};
?>
</syntaxhighlight>
 
;実行結果
aaaa
 
 
=== ※応用: 関数とmatch ===
<!-- 別セクションのenum で関数を使うので、関連事項として説明。 -->
 
プログラミング言語には「関数」という、何度も使う手続きをひとまとめにして、呼び出すたびに使えるという機能がある。PHPにも関数の機能がある。
 
match式を関数で呼び出したい場合、単に一般の関数の中に match 式を入れればいい。
 
コード例
<syntaxhighlight lang="PHP">
<?php
$x = 1;
function f($x){
match ($x) {
0 => print("aaaa" . "\n") ,
1 => print("qwer" . "\n") ,
2 => print("test" . "\n") ,
};
}
 
f($x);
f($x);
 
?>
</syntaxhighlight>
 
実行結果
<pre>
qwer
qwer
</pre>
 
 
関数の戻り値の命令 return と match 式を組み合わせた<code>return match</code>を使うと、下記のような処理も出来る。return match により、アロー分岐後に指定されている値を戻り値に指定できる。
 
コード例
<syntaxhighlight lang="PHP">
<?php
$x = 2;
 
function f($x){
return match ($x) {
0 => "aa" . "\n" ,
1 => "qw" . "\n" ,
2 => "te" . "\n" ,
};
}
 
print(f($x) );
print(f(1) );
 
?>
 
</syntaxhighlight>
 
実行結果
<pre>
te
qw
</pre>
 
== 列挙型 ==
395 ⟶ 285行目:
enum とは何かの説明が難しいのでコードと実行例を先に示します。
 
コード;
:<syntaxhighlight lang="PHP"php>
<?php
 
410 ⟶ 300行目:
$b = gameMode::menu ; // このサンプルコードでは$bは以降は未使用。参考のため書いている。
 
if ($a == gameMode::map ){ print(echo "今マップ画面を操作中です。" ., "\n")PHP_EOL ; }
if ($a == gameMode::menu ){ print(echo "今メニュー画面を操作中です。" ., "\n")PHP_EOL ; }
 
?>
</syntaxhighlight>
:(※ 2022年05月21日にPHP 8.1.6 を、Fedora 36上で動作確認。)
 
 
実行結果
;実行結果
<pre>
今マップ画面を操作中です。
433 ⟶ 323行目:
 
なお、おおむね用語として、
:<syntaxhighlight lang="PHP"php>
enum 列挙体名
{
455 ⟶ 345行目:
 
 
コード;
:<syntaxhighlight lang="PHP"php>
<?php
 
470 ⟶ 360行目:
$b = gameMode::menu ; // このサンプルコードでは$bは以降は未使用。参考のため書いている。
 
if ($a == gameMode::battle ){ print(echo "今、戦闘画面を操作中です。" ., "\n")PHP_EOL ; }
if ($a == gameMode::menu ){ print(echo "今メニュー画面を操作中です。" ., "\n")PHP_EOL ; }
 
?>
</syntaxhighlight>
:(※ 2022年05月21日にPHP 8.1.6 を、Fedora 36上で動作確認。)
 
 
実行結果
;実行結果
<pre>
今、戦闘画面を操作中です。
500 ⟶ 390行目:
このように、あらかじめ value および name というプロパティがenumでは決まっています。
 
コード;
:<syntaxhighlight lang="PHP"php>
<?php
// 装備画面
515 ⟶ 405行目:
 
if ($a == 2 ){
print(echo "{$a}番データベースを編集。" ., "\n")PHP_EOL ;
}
if ($a == 3 ){
print(echo "こっちには来てない。" ., "\n")PHP_EOL ;
}
 
?>
</syntaxhighlight>
:(※ 2022年05月21日にPHP 8.1.6 を、Fedora 36上で動作確認。)
 
 
 
実行結果
;実行結果
<pre>
2番データベースを編集。
537 ⟶ 427行目:
さて、enumで定義した整数値を使って計算したい場合、下記のように<code>->value</code>プロパティで代入値にアクセスする必要があります。
 
コード;
:<syntaxhighlight lang="PHP"php>
<?php
// 装備画面
552 ⟶ 442行目:
// 現状では if 文で事前にenum格納した変数を呼び出さないとエラーになる。
if ($a == 3 ){
print(echo "{$a}番データベースを編集。" ., "\n")PHP_EOL ;
}
if ($a == 4 ){
print(echo "こっちには来てない。" ., "\n")PHP_EOL ;
}
 
?>
</syntaxhighlight>
;実行結果
:(※ 2022年05月21日にPHP 8.1.6 を、Fedora 36上で動作確認。)
 
実行結果
<pre>
3番データベースを編集。
570 ⟶ 458行目:
説明の都合上、上記ではif文を書いてからブロック中でprintを使いましたが、別に事前に if文が無くてもprinttでenum変数のvalue値は表示できます。
 
:<syntaxhighlight lang="PHP"php>
<?php
// 装備画面
580 ⟶ 468行目:
}
 
print(echo "valueごと定義\n");
$a = soubiMode::tate->value ;
print(echo $a);
print(echo "\n");
 
print(echo "print側でvalue指定\n");
$b = soubiMode::buki ;
print(echo $b->value);
print(echo "\n");
 
?>
</syntaxhighlight>
:(※ 2022年06月にFedora 36上で動作確認。)
 
 
実行結果
;実行結果
<pre>
valueごと定義
605 ⟶ 493行目:
match 式の変数と条件式には、下記のように enum変数を入れることも出来ます。このため、下記のように書けます。
 
:<syntaxhighlight lang="PHP"php>
<?php
// 装備画面
619 ⟶ 507行目:
 
match ($a) {
soubiMode::buki, soubiMode::tate => print(echo "{$a->name}データベースを編集。" ., "\n")PHP_EOL,
soubiMode::kabuto => print(echo "カブトのデータベースは未作成。" ., "\n")PHP_EOL,
default => print(echo "宣言されてない装備にアクセスしました。" ., "\n")PHP_EOL ,
 
};
628 ⟶ 516行目:
</syntaxhighlight>
 
;実行結果
<pre>
bukiデータベースを編集。
636 ⟶ 524行目:
その他、matchの各条件(「soubiMode::kabuto」の部分)をもっと短く書きたい場合、下記コードのように、enum要素名をつかって条件分岐する方法もあります。ただし、文字列は内部的なデータ数が長くなるので、処理速度に多少の欠点が考えられる。よって可能なら、なるべく上述のようなenum変数を直接に条件にするコードのほうが良いだろう。
 
:<syntaxhighlight lang="PHP"php>
<?php
// 装備画面
649 ⟶ 537行目:
 
match ($a->name) {
"buki", "tate" => print(echo "{$a->name}データベースを編集。" ., "\n")PHP_EOL,
"kabuto" => print(echo "カブトのデータベースは未作成。" ., "\n")PHP_EOL,
default => print(echo "宣言されてない装備にアクセスしました。" ., "\n")PHP_EOL ,
 
};
658 ⟶ 546行目:
</syntaxhighlight>
 
;実行結果
<pre>
tateデータベースを編集。
666 ⟶ 554行目:
enum は関数の引数にすることもできる。(関数について詳しくは[[PHP/入門/関数とは]]で扱う。)
 
:<syntaxhighlight lang="PHP"php>
<?php
// 装備画面
678 ⟶ 566行目:
// $a = soubiMode::tate->value ;
 
print(echo "enum関数実験" ., "\n")PHP_EOL ;
function f($mode){
print "$mode->name \n";
689 ⟶ 577行目:
?>
</syntaxhighlight>
:(※ 2022年05月21日にPHP 8.1.6 を、Fedora 36上で動作確認。)
 
 
実行結果
;実行結果
<pre>
enum関数実験
703 ⟶ 591行目:
なお、引用符中の <code>$mode->value</code> は、下記のように <code>{$mode->value}</code> と書いてもいい(2022年6月のPHP8.1の時点)。
 
:<syntaxhighlight lang="PHP"php>
<?php
// 装備画面
715 ⟶ 603行目:
// $a = soubiMode::tate->value ;
 
print(echo "enum関数実験" ., "\n")PHP_EOL ;
function f($mode){
print "{$mode->name} \n";
741 ⟶ 629行目:
PHP8では関数の引数に型をつけることができるが、下記のように引数としてenum変数を使う際には型の代わりにenumグループ名をつけることもできる。
 
:<syntaxhighlight lang="PHP"php>
<?php
// 装備画面
761 ⟶ 649行目:
</syntaxhighlight>
 
;実行結果
<pre>
tate