🦔

【PHP】PHP入門

2023/06/27に公開

PHPってなに?

プログラムはコンピュータに与える命令の集まりです。プログラムを書くために仕様を定義したものが「プログラミング言語」であり、PHPもその1つです。インターネットを通して利用するソフトウェアをWebアプリケーションといいますが、PHPはWebアプリケーションを作るためのプログラミング言語と言えます。

PHPプログラムについて

PHPプログラムはドキュメントルート(Document Root)に置きます。ドキュメントルートとは、Webサーバーによって外部に「公開されるフォルダ」のことです。このフォルダの下にあるファイルやフォルダは、たとえば「http://localhost/...」というURLで、Webブラウザからアクセスができます。

ドキュメントルートってなに?

みなさんがこれから作成するPHPプログラムは、すべてこの公開されるフォルダに置くことになりますが、このドキュメントルートの位置は、システムによって異なります。

ローカル環境での開発なら

●MAMP for windows
C:\MAMP\htdocs

●MAMP for Mac
\アプリケーション\MAMP\htdocs

●XAMPP for windows
C:\XAMPP\htdocs

などが「公開されるフォルダ」、つまりドキュメントルートになります。

PHPの基本構文

<?php ここに処理したいプログラムの内容を書く ?>

演算子ってなに?

代数演算子

加算、減算、乗算、除算のような数値演算(計算)をする演算子です。算術演算子と呼ばれることもあります。

比較演算子

大小の比較や、等しいか等しくないかなど、2つの値の関係を調べてTRUEかFALSEを返す演算子です。関係演算子と呼ばれることもあります。

三項演算子

if-else文を省略して記述したような構文です。
条件に対して、TRUEの時に返す値とFALSEの時に返す値を設定できます。
「 □□ ? 〇〇 : ×× ; 」□□が条件、〇〇が真の時、××が偽の時。

論理演算子

「かつ」(AND:論理積)や「または」(OR:論理和)など、TRUEやFALSEの組み合わせを論理演算するための演算子です。複数の条件を組み合わせる際によく利用します。

代入演算子

演算した結果を代入するための演算子です。複数の条件を組み合わせる際によく利用します。

文字列演算子

文字列を連結する演算子です。文字列を連結する「.」と、連結した結果を代入する「.=」の2つの演算子があります。

ビット演算子

ビット操作を行う。

エラー制御演算子

エラーメッセージを無視する。

実行演算子

シェルコマンドを実行する。

型演算子

オフジェクトがどのクラスから作られたのかを調べる。

代数演算子にはどんなものがあるの?

代数演算子は、加算、減算、乗算、除算のような数値の計算に使う演算子です。
代数演算子には、「+」「-」「*」「/」「%」などがあります。

演算子 意味
+ 加算 $a + $b
- 減算 $a - $b
* 乗算 $a * $b
/ 除算 $a / $b
% 剰余(割り算の余り) $a % $b
- 符号を反転(+-を反転させる) -$a

比較演算子にはどんなものがあるの?

比較演算子は、2つの値を比較して、大小や等しいかどうかなどを調べる演算子です。演算結果は、「TRUE」か「FALSE」を返し、条件分岐構文や繰り返し構文の条件としてよく利用されます。

演算子 意味
== 等しい $a == $b
!= 等しくない $a != $b
<> 等しくない $a <> $b
< より小さい $a < $b
> より大きい $a > $b
<= 以下 $a <= $b
>= 以上 $a >= $b
=== 同一(値もデータ型も等しい) $a === $b
!== 同一ではない(または型が異なるとき) $a !== $b

2つの値のデータ型が異なるときは、「==」や「!=」の比較演算子はデータ型を自動的にキャスト(型変換)して、同じデータ型にそろえてから比較を行います。例えば、数値の「5」と文字列の「'5'」を「==」で比較すると、文字列の「'5'」が数値にキャストされて、等しいという意味の「TRUE」を返します。

一方、「===」や「!===」の比較演算子は、データ型を求めて等しいかどうかを調べます。
数値の「5」と文字列の「'5'」を「===」で比較すると、データ型が異なるので、同一ではないという意味の「FALSE」を返します。

論理演算子にはどんなものがあるの?

論理演算子は、「かつ」(AND:論理積)や「または」(OR:論理和)など、複数の条件を組み合わせるときに使う演算子です。

演算子 意味
&& 論理積 ともにTRUEの場合はTRUE $a && $b
|| 論理和 両方またはどちらか片方がTRUEの場合はTRUE $a || $b
! 否定 TRUEとFALSEを反転させる !$a
and より小さい $a and $b
or より大きい $a or $b
xor 以下 $a xor $b

「&&」と「and」はともに論理積、「||」と「or」はともに論理和の演算子ですが、演算する順番(優先順位)に大きな違いがあります。and、or、xorは代入演算子よりも優先順位が低いので、使用する際には注意が必要です。

例えば、

$c = $a && $b;

の場合は「&&」の優先順位が高いので、「$a && $b」
の結果として、TRUEかFALSEが変数の$cに代入されます。反対に、

$c = $a and $b;

の場合は、「=」の優先順位の方が高いので、「$c = $a」
(変数aの値を変数cに代入)が先に行われ、そのあとで、「and $b」
が処理されます。その結果にかかわらず、変数$cに代入されているのは、変数aの値です。

代入演算子にはどんなものがあるの?

代入演算子は、演算の結果を代入するための演算子です。
左辺と右辺の値を演算した結果がそのまま代入されるので、計算式をシンプルにできます。
1つずつ増やしたり、減らしたりする演算子もあります。

演算子 意味
= 代入(右辺の値を左辺に代入する) $a = $b
+= 加算した結果を代入 $a += $b ( $a = $a + $b と同じ)
-= 減算した結果を代入 $a -= $b( $a = $a - $b と同じ)
*= 乗算した結果を代入 $a *= $b( $a = $a * $b と同じ)
/= 除算した結果を代入 $a /= $b( $a = $a / $b と同じ)
%= 剰余を代入 a %= $b(a = $a % $b と同じ)

ビット演算子や文字列演算子を「=」の前に置いた場合も、同じように演算結果が代入されます。

代入演算子の仲間に、加算子(インクリメント演算子)、減算子(デクリメント演算子)と呼ばれるものがあります。これらは値を1加算、もしくは1減算する、特別な代入演算子です。

演算子 意味
++ 1加算(インクリメント) ++a、a++( $a = $a + 1と同じ)
-- 1減算(デクリメント) --a、a--( $a = $a - 1と同じ)

「++$a」のように加算子を前に付けると、1を加算して値を返します。
例えば、「a」に3が入っている時は、「++a」は1を加算して4を返します。
このような加算子を前置加算子といいます。減算子の場合は前置減算子といいます。

「$a++」のように加算子を後ろに付けるときは、元の値を返し、そのあとに1を加算します。
例えば、「a」に3が入っているときは、「a++」は、3を返し、そのあとに $aに1を加算します。
このような加算子を後置加算子といいます。減算子の場合は、後置演算子といいます。

<?php
$a = 3;
++$a; //$a + 1; つまり 3 + 1;
echo $a; //結果 4
?>
<?php
$a = 3;
$a++; //$a; $a + 1; つまり 3; 3 + 1;
echo $a; //結果 4
?>

結果は変わらないけれど、計算式が少し違う。

文字列や配列を連結するには?

文字列をつなげたい時は、結合演算子の「.」を文字列の間に挟みます。

<?php
$dog = 'トイ' . 'プードル';
echo $dog; //結果 トイプードル
?>

「.=」は結合代入演算子と呼ばれ、文字列をつなげた結果を代入する代入演算子です。

例えば、変数dogに「トイプードル」という文字列が入っている時、次のように結合代入演算子を使うと、変数dogには結合された文字列が代入されます。

<?php
$dog = 'トイプードル';
$dog .= 'は小さい犬です。';
echo $dog; //結果 トイプードルは小さい犬です。
?>

配列を結合したい場合には、「.」ではなく、array_merge関数を使います。
例えば、2つの配列dogs1とdogs2を結合したい時は、次のように記述します。

※配列「array();」はPHP5.4以前の書き方です。PHP5.4以降は「[]」という書き方ができるようになりました。

<?php
$dogs1 = ['トイプードル', '柴犬', 'チワワ'];
$dogs2 = ['シェパード', 'ブルドッグ'];
$dogs = array_merge($dogs1, $dogs2);

print_r($dogs1);
print_r($dogs2);
print_r($dogs);

/*結果
Array
(
    [0] => トイプードル
    [1] => 柴犬
    [2] => チワワ
)
Array
(
    [0] => シェパード
    [1] => ブルドッグ
)
Array
(
    [0] => トイプードル
    [1] => 柴犬
    [2] => チワワ
    [3] => シェパード
    [4] => ブルドッグ
)
*/
?>

文字列と数値を結合演算子「.」で連結すると、数値が自動的に文字にキャスト(型変換)されて連結が行われます。

<?php
$price = 300;

echo $price . '円'; //結果 300円
echo "\n\n";

var_dump($price); //結果 int(300) ※intは整数
var_dump($price . '円'); //結果 string(6) "300円" ※stringは文字列
?>

条件分岐ってなに?

通常、プログラムは記述した順に上から下へ「処理」が実行されます。
このプログラムの流れを「条件」によって切り替えることを、条件分岐といいます。

例えば、
年齢によって入場料が変わる遊園地のチケットを例えに考えてみましょう。

こども(16歳未満) おとな(16歳以上) シニア(65歳以上)
600円 1200円 800円

年齢が「16歳未満」であれば、チケットはこども料金の「600円」、「16歳以上」であれば、おとな料金の「1200円」、さらに「65歳以上」だとシニア料金の「800円」になります。

年齢によって(=条件によって)チケットの料金が変わる(=処理が切り替わる)ので、このプログラムは条件分岐で記述できます。

プログラムの流れを線や記号で表したものを「フローチャート(流れ図)」といいます。

if文ってどうやって使うの?

if文は、PHP言語の代表的な条件分岐構文です。
ある条件を満たしたときだけ、特定の処理を実行します。条件を満たさなかったときには、さらに別の処理をさせることもできます。

最も単純なif文は、次のように記述します。

<?php
if(条件){
    条件をクリアした時の処理
}
?>

条件をクリアしたときだけ処理を行う、という記述です。
()の中には条件、{}の中には処理を記述します。
{}の中には、複数行にわたる処理を記述できます。

条件をクリアしないときに、別の処理をさせるには、次のようなif-else分を使います。

<?php
if(条件){
    条件をクリアした時の処理
} else {
条件をクリアしなかった時の処理
}
?>

先ほどの遊園地のチケットの例で実際にやってみましょう。

<?php
//あなたの年齢は?
$age = 10;

//分岐
if($age < 16) {
    //こども料金(600円)
    $ticket = 600;
} elseif($age >= 65) {
    //シニア料金(800円)
    $ticket = 800;
} else {
    //おとな料金(1200円)
    $ticket = 1200;
}

echo 'あなたのチケット代は', $ticket, '円です。'; //結果 あなたのチケット代は600円です。
?>

PHPのif文の書き方は、2種類あります。以下は{}を使わずに:を使う書き方です。

<?php
if(条件):
    条件をクリアした時の処理
elseif (条件):
    条件をクリアした時の処理
elseif (条件):
    条件をクリアした時の処理
else:
    条件をクリアしなかった時の処理
endif;
?>

if文の中にif文を書くと、さらに複雑な条件分岐を記述することができます。

また、シンプルなTRUEとFALSEの判別の場合、三項演算子を使うと以下のように1行で記述できます。

<?php
//条件 ? 条件がTRUEの時に返す値 : 条件がFALSEの時に返す値;
//変数$ageが16未満なら「600」それ以外なら「1200」を返します。
$ticket = $age < 16 ? 600 : 1200; 

//if文で書くと
if ($age<16) {
	$ticket = 600; //こども料金
} else {
	$ticket = 1200; //おとな料金
}
?>

switch文ってどうやって使うの?

switch文は、変数の値によって処理を切り替える条件分岐の構文です。例えば、占いやゲームのシナリオのように、いくつもの分岐をさせたい時によく使います。

<?php
switch (変数) {
    case1:
        // 値1の時の処理...
        break;

    case2:
        // 値2の時の処理...
        break;

    case3:
        // 値3の時の処理...
        break;
    
    default:
        // caseのどれにも当てはまらない時の処理...
        break;
}
?>

switch文のフローチャート

変数の値を比較して処理を分岐させるので、if文でも記述することができます。
比較する値(切り替える処理)が多いときは、switch文の方がシンプルに記述できるので、用途に
よって使い分けましょう。

例えば、順位によって異なる色のメダルを渡す場合は、次のように記述します。

<?php
//あなたのランクはいくつですか?
$rank = 2;

//分岐
switch ($rank) {
    case 1:
        // 値1の時の処理...
        $medal = 'Gold';
        break;

    case 2:
        // 値2の時の処理...
        $medal = 'Silver';
        break;

    case 3:
        // 値3の時の処理...
        $medal = 'Bronze';
        break;
    
    default:
        // caseのどれにも当てはまらない時の処理...
        $medal = 'なし';
        break;
}
echo 'あなたのランクは', $rank, '位です。', "\n", 'メダルは', $medal, 'です。';

//結果
あなたのランクは2位です。
メダルはSilverです。
?>

breakを省略すると、次のcase文(またはdefault文)が実行されます。
上のプログラムの場合、1位のbreakを省略すると、順位が1位(rankの値が1)のときは変数medalに"Gold"がセットされますが、さらに次の2位のcase文にも進んでしまい、変数medalに"Silver"がセットされてしまいます。breakの付け忘れには注意してください。

繰り返し構文ってなに?

同じ処理を繰り返し行わせたいときに、まったく同じプログラムを何度も書くのは、あまりいい方法ではありません。繰り返し構文は、「ある条件の間、処理を繰り返し実行させる」プログラムです。

繰り返し構文のプログラムの流れ(「処理2」を繰り返すかどうか)

繰り返し構文には、while文やfor文、foreach文があります。

while文ってどうやって使うの?

while文は、PHP言語の代表的な繰り返し構文です。一定の条件に当てはまる間、何度でも繰り返し実行させたいときに使います。

while文は、次のように記述します。

while(条件) {
	//条件をクリアしている間、繰り返す処理...
	//無限ループにならないように注意が必要。
}

例えば、1月、2月、3月と12カ月を表示するプログラムを考えてみましょう。

<?php
//1月をセット
$month = 1;

//12か月まで繰り返し
while($month <= 12) {
	//月を表示
	echo $month, '月';
	
	//月を1加算
	$month++;
}
?>

変数$monthの値が12以下である間は、{}内の処理が繰り返されます。
変数$monthの値が13になると、while文から抜け出します。
while文から抜け出すときは、{}の中の処理は行われません。

while文とよく似たdo-whileってなに?

while文とよく似た繰り返し構文にdo-while文があります。
do-while文は、次のように記述します。

<?php
do {
    //条件をクリアしている間、繰り返す処理
    //無限ループにならないように注意が必要。
} while(条件);
?>

while文は、先に条件を調べるので、条件をクリアしていなければ1回も処理が行われません。do-while文は、あとで条件を調べるので、条件をクリアしていなくても1回目の処理は必ず実行されます。
また、条件式が1つのみの場合には、以下のように{}を省略して書くことも可能です。

do
  実行する処理;
while (条件式);

どんな時に使えばいいのか。
do..while文では、まずブロック内野処理が実行された後で条件式の評価が行われます。その為、少なくとも1回は必ずブロック内の処理が実行されます。条件式の評価が真(TRUE)であれば再度先頭に戻りブロック内の処理を実行します。偽(FALSE)ならばdo..while文を終了します。

<?php
//$numに値を入力
$num = 0;

do{
  echo "num=", $num, "\n"; //とりあえず真偽に関わらず最初1回目の処理「echo」を出力。
  $num += 1; //その後「$num」に1加算して、繰り返す。
}while ($num < 3); //1回目の処理が終わった後に、審議を確かめ、条件を満たしている間は、繰り返す。
?>

まずブロック内の処理が行われてから、繰り返しを継続するかどうか条件式の評価を行っています。
なおwhile文と同じく「break」や「continue」を利用することが可能です。

for文ってどうやって使うの?

for文も代表的な繰り返し構文です。while文と違い、繰り返しの回数をあらかじめ指定することができます。

for(カウンターの初期化; 繰り返しの条件; カウンターの更新) {
    繰り返す処理
}

「カウンターの初期化」部分には、カウンターに使用する変数と、その初期値を記述します。例えば、変数iをカウンターとして初期値0からスタートさせたいときは、「$i = 0」と記述します。
$iとは、整数を表すintだったり、配列の順番を表すindexだったり。。ちょっと詳細は不明。

「繰り返しの条件」部分には、カウンターを使った条件を記述します。
例えば、カウンター(変数i)が10より小さい間は処理を繰り返す場合、「$i<10」と記述します。

「カウンターの更新」部分には、カウンターの増減幅を記述します。
例えば、カウンターを1ずつ増やすときは、加算子「++」を使って「$i++」と記述します。

{}の中には繰り返す処理を記述します。

for文のフローチャート

10回(0から9まで)繰り返す処理は、次のように記述します。

for($i=0; $i<10; $i++) {
    //繰り返す処理
}

1月から12月を繰り返し分を使って出力してみましょう。

for($month=1; $month<=12; $month++) { //$monthに1月をセット
    //月を表示
    echo $month, "月", "\n";
}

while文では、処理の中にカウンターの更新(i++)を含めていたましたが、for文では、「month++」のように、構文の条件式の中にカウンターをセットできます。

逆に、減算子($i--)を使うことで、カウントダウンをさせることができます。
例えば、月の表示を、12月から1月まで逆順に出力するプログラムに作り変える場合には、次ののように変更します。

for($month=12; $month>=1; $month--) { //$monthに12月をセット
    //月を表示
    echo $month, "月", "\n";
}

foreach文ってどう使うの?

foreach文は、配列から要素を1つずつ取り出したいときに使う、特殊な繰り返し構文です。

<?php
foreach(配列 as 変数) {
    繰り変えす処理
}
?>

配列の要素を先頭から1つずつ取り出し、変数にセットします。
{}内の処理は、配列の要素の数だけ繰り替えされます。{}の中には複数行にわたる処理を記述することができます。

foreeach文のフローチャート

例えば、配列dogsに「トイプードル」「柴犬」「チワワ」の3つの値が入っているとします。配列dogsのすべての要素を取り出して、それぞれ「〇〇は愛い犬です。」と表示してみましょう。

<?php
//配列$dogsのグループを作る
$dogs = ['トイプードル','柴犬','チワワ'];

//配列からすべての要素を順番に取り出す
foreach ($dogs as $value) {
    //取り出した要素を1レコードずつ表示
    echo $value, 'は可愛い犬です。', "\n";
}
//結果
//トイプードルは可愛い犬です。
//柴犬は可愛い犬です。
//チワワは可愛い犬です。
?>

同じことを、for文でもやってみましょう。

<?php
//配列$dogsのグループを作る
$dogs = ['トイプードル','柴犬','チワワ'];

//配列の要素を数える
$cnt = count($dogs);
echo "変数dogsに含まれる要素は", $cnt, "つです。", "\n\n";

//0から$cnt未満までの間繰り返し
for ($i=0; $i<$cnt; $i++) {
    //取り出した要素を表示
    echo $dogs[$i], 'は可愛い犬です。', "\n";
}
//結果
//変数dogsに含まれる要素は3つです。
//
//トイプードルは可愛い犬です。
//柴犬は可愛い犬です。
//チワワは可愛い犬です。
?>

繰り返し処理を途中で抜けるにはどうしたらいい?

繰り返し処理を途中で抜けたい(中断したい)ときがあります。そんなときは、break文を使用します。繰り返し分のほか、条件分岐のswitch文のブロックを抜けるときにも使うので、しっかり覚えておきましょう。

while文を使って1月から12月まで表示するプログラムを、6月までの表示に作り替えてみます。

<?php
//1月をセット
$month = 1;

//12月まで繰り返し
while ($month <= 12) {
    //6月を超えたら繰り返し処理を中断
    if ($month > 6) { //1つ上の階層「while ($month <= 12)」の{}処理を全てパスする。
        break;
    }
    //月を表示
    echo $month, '月', "\n";
    //月を1加算
    $month++; //加算や減算を入れないと、while文の場合無限ループになるので注意。
}
//結果
//1月
//2月
//3月
//4月
//5月
//6月
?>

while文の繰り返し処理の最初にif文の条件式を加えています。
変数$monthの値が6より大きくなったときは、break文を実行して、繰り返し処理を中断しています。
break文が実行されると、while文の{}から抜け出すので、月の表示や加算が行われません。

また、多重ループを使用している場合、breakに数字を付けることによって、何階層上のループを抜けるかを指定することができます。「break 2;」で2つ上の階層を抜けることができます。

<?php
while (条件) {
    while (条件) {
        break 2;  // 2階層上(二重ループ)を抜ける場合
	}
}
?>

繰り返し処理を抜けずに、ある条件の時だけ処理をスキップしたい場合はどうしたらいい?

繰り返し処理を抜けるのではなく、その回だけスキップをさせたい場合はbreak文ではなく、continue文を使用します。
continue文が実行されると、その下の処理は行われずに(スキップされて)、次の繰り返し処理に移ります。

<?php
for($i = 0; $i < 5; $i++) {
    if ($i == 2 || $i == 3) {
        continue;
        //$iの値が2または3の時は、下の処理を飛ばして1階層上のfor文に戻って繰り返す。
    }
    echo "iの値: $i\n";
}
//結果
//iの値: 0
//iの値: 1
//iの値: 4
?>

関数の基本

関数は、材料を入れたら結果が出てくる機械のようなものです。「ある値」を渡すと「決まった処理」をして「結果」を返す、といった一連の動きをまとめたものを「関数」と言います。

もともとPHPで用意されている関数に加えて、自分でも作れる「自作関数」も使えるから、よく使う処理を関数にしておくと便利です。

自動販売機を例に考えてみると、お金を入れる(=値を渡す)とジュース(=結果)が出てきます。
自動販売機の中では、入ったお金を数えて、金額が足りていればジュースを出す、というような「決まった処理」が行われています。

関数のメリットは一度定義してしまえば、何度でもその関数を利用できることです。
例えば、ジュースを10本買うために、自動販売機を10台用意する必要はありません。
1台の自動販売機を10回使えば、10本のジュースは手に入ります。

同じように、ジュースを10本買うプログラムでは、「入ったお金を数えて、金額が足りていればジュースを出す」という処理を10回記述する必要はありません。「自動販売機」関数をひとつ作り、10回使うだけで、ジュースを10本買うプログラムはできてしまうのです。

オブジェクト指向プログラム

クラスに定義された関数のことを「メソッド」と呼びます。

引数と戻り値ってなに?

関数に渡す値を「引数(ひきすう)」といいます。また、関数が返す結果(値)を「戻り値(もどりち)」または、「返り値(かえりち)」といいます。

関数には、複数の引数を渡すことができます。
例えば、実際のジュースの自動販売機を使うときは、お金を入れて、欲しいジュースを選びます。この場合、「お金」と「欲しいジュース」が「自動販売機」関数に渡す「引数」になります。

引数を使用しない(引数を渡さない)関数もあります。
例えば、「水道の蛇口をひねると水が出てくる」という動きは、蛇口に何も渡さないので、引数を渡さない関数として記述します。

戻り値は引数とは異なり、返される値は「ひとつ」か「ナシ」のどちらかです。複数の値を戻り値として返すことはできません。複数の要素を持つ配列を返すことはできますが、その場合、戻り値は「ひとつの配列」になります。

例えば、「日記をつける」という動きは、「日付」や「今日の出来事」を引数として渡しますが、日記を書くという処理のあとに、戻り値として返す値はないので、戻り値を返さない(戻り値がない)関数として記述します。

ほかの言語では、戻り値を返さない関数を「プロシージャ」と呼び、関数と区別する場合があります。

関数を定義するにはどうしたらいいの?

関数を作ることを「関数を定義する」といいます。関数には、好きな名前を付けることができます。関数を使うときは、この関数名で呼び出します。

関数は、次のように定義します。

<?php
function 関数名 (引数1, 引数2, 引数3, ...) {
    処理
    return 戻り値;
}
?>

引数を複数渡す場合には、カンマで区切ります。{}の中に処理を記述し、最後にreturn文を使って戻り値を返します。

引数を使わない関数は、次のように定義します。

<?php
function 関数名 () {
    処理
    return 戻り値;
}
?>

また、戻り値(return)を返さない関数は、次のように定義します。

<?php
function 関数名 () {
    処理
}
?>

return文を省略すると、処理を行うだけで戻り値を返さない関数になります。
定義した関数は、引数にそれぞれ値を渡して、次のように呼び出します。

https://arts-factory.net/function/

戻り値を変数に代入する場合

$変数 = 関数名(1,2,3, ...);

戻り値を返さない関数の場合

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

例題

次のようなジュースの自動販売機を関数で記述してみましょう。

ここでは、関数の名前を「get_drink」にしましょう。
関数「get_drink」は、次のように定義することができます。

<?php
//関数「get_drink()」を定義する
function get_drink($money) {
    //金額を調べる
    if($money == 100){
        //100円ぴったりならジュースを販売
        return "ジュースを出すよ!";
    } else {
        //100円ぴったりじゃないならお金を返す
        return $money. '円返却するよ。';
    }
}

//引数に設定した変数「$money」に値を代入する。
$money = 10;

//変数に関数の戻り値を代入する場合
$kekka = get_drink($money);

//変数「太郎(tarou)」が入れた金額50円
$tarou = '太郎には、'. get_drink(50);

//変数「花子(hanako)」が入れた金額100円
$hanako = '花子には、'. get_drink(100);

//出力
echo get_drink(80);
echo "\n";
echo $kekka;
echo "\n";
echo $tarou;
echo "\n";
echo $hanako;
echo "\n";

//結果
//80円返却するよ。
//10円返却するよ。
//太郎には、50円返却するよ。
//花子には、ジュースを出すよ!
?>

変数のスコープってなに?

関数の中で使う変数は、関数の外では使用できません。また、関数の外にある変数を関数内でそのまま使用することもできません。このような、変数の使用できる範囲を「スコープ」といいます。

次のような、ビスケットの歌を例に考えてみましょう。

<?php
//ビスケットが1枚
$biscuit = 1; //関数の外にあるのでグローバル変数

//ポケットをたたく関数
function hit_pocket() {
    //ビスケットが増える
    $biscuit++; //関数の中にあるのでローカル変数。グローバル変数とは区別される。
}

//ポケットをたたく
hit_pocket();

//ビスケットの枚数を表示する
echo 'ビスケットは' . $biscuit . '枚';
?>

さて、ポケットをたたくとビスケットは何枚になるでしょうか?
一見、理に適っているようですが、この関数は、エラーになります。

functionの中で、「$biscuit」の初期値が定義されていないので、「どの位、加算をしていいのかわからない」とプログラムが困っているわけです。

これを解決するために、関数の中でもいったんビスケット5枚の初期値「$biscuit = 5;」を定義したいと思います。

<?php
//ビスケットが1枚
$biscuit = 1; //関数の外にあるのでグローバル変数

//ポケットをたたく関数
function hit_pocket() {
    //ビスケットが5枚
    $biscuit = 5; //関数の外にあるのでグローバル変数
    //ビスケットが増える
    $biscuit++; //関数の中にあるのでローカル変数。グローバル変数とは区別される。
}

//ポケットをたたく
hit_pocket();

//ビスケットの枚数を表示する
echo 'ビスケットは' . $biscuit . '枚';
?>

これはどうでしょうか?
エラーは出ないけど、関数の中で最初に持っているのが5枚だから、出力は1加算して6枚のはずです。なのに結果は「1枚」。これは、グローバル変数として最初に定義されている値「$biscuit = 1;」が表示されているからです。

では、関数の処理結果を表示するためにはどうしたらいいでしょうか?

<?php
//ビスケットが1枚
$biscuit = 1; //関数の外にあるのでグローバル変数

//ポケットをたたく関数
function hit_pocket() {
    //ビスケットが1枚
    $biscuit = 5; //関数の外にあるのでグローバル変数
    //ビスケットが増える
    $biscuit++; //関数の中にあるのでローカル変数。グローバル変数とは区別される。
}

//ポケットをたたいた時のビスケットの数を表示する
echo 'ビスケットは' . hit_pocket() . '枚';

echo "\n";

//ビスケットの枚数を表示する
echo 'ビスケットは' . $biscuit . '枚';
?>

これも「echo 'ビスケットは' . hit_pocket() . '枚';」を実行した所だけ表示されませんね。
それは、処理を実行しただけで、最後に出力する値が返ってきてないからです。
そいういう時にはreturn文を使って「戻り値」を設定しましょう。

<?php
//ビスケットが1枚
$biscuit = 1; //関数の外にあるのでグローバル変数

//ポケットをたたく関数
function hit_pocket() {
    //ビスケットが1枚
    $biscuit = 5; //関数の外にあるのでグローバル変数
    //ビスケットが増える
    $biscuit++; //関数の中にあるのでローカル変数。グローバル変数とは区別される。
    //戻り値を設定
    return $biscuit;
}

//ポケットをたたいた時のビスケットの数を表示する
echo 'ビスケットは' . hit_pocket() . '枚';

echo "\n";

//ビスケットの枚数を表示する
echo 'ビスケットは' . $biscuit . '枚';
?>

これで、「hit_pocket()」関数の結果を出力することができました!

このように、変数の使用できる範囲「スコープ」を間違えると、思ったような結果にならないので、設計を考える時には、「スコープ」を意識「しましょう。

グローバル変数を関数内で使用する方法はないの?

最初のビスケットの歌の例に戻ってみましょう。

<?php
//ビスケットが1枚
$biscuit = 1; //関数の外にあるのでグローバル変数

//ポケットをたたく関数
function hit_pocket() {
    //ビスケットが増える
    $biscuit++; //関数の中にあるのでローカル変数。グローバル変数とは区別される。
}

//ポケットをたたく
hit_pocket();

//ビスケットの枚数を表示する
echo 'ビスケットは' . $biscuit . '枚';
?>

これでは、ローカル変数とグローバル変数でスコープが違ったため、「$biscuit」の結果がうまく表示されず、エラーになってしまいました。しかし、関数内で「global $変数;」と1文追加することで、関数の外で定義されたグローバル変数を関数内でも使用することができるようになります。

<?php
//ビスケットが1枚
$biscuit = 1; //関数の外にあるのでグローバル変数

//ポケットをたたく関数
function hit_pocket() {
    //グローバル変数「$biscuit」を関数内でも呼び出す
    global $biscuit;
    //ビスケットが増える
    $biscuit++; //関数の中にあるのでローカル変数。グローバル変数とは区別される。
}

//ポケットをたたく
hit_pocket();

//ビスケットの枚数を表示する
echo 'ビスケットは' . $biscuit . '枚';
//結果
//ビスケットは2枚
?>

ただし、変数は「変化する値」のため、変数名の管理をよほどしっかりしないと、システムエラーの原因にもなるので、あまり多様しない方が良いでしょう。

PHP言語のグローバル変数とローカル変数、スーパーグローバル変数について

PHP言語では、普通の変数(関数の外にある変数)を「グローバル変数」と呼び、関数の中にある変数を「ローカル変数と呼びます。さらに、PHP言語では「 $_GET 」や「 $_POST 」など、関数の外でも中でも使用できる特別な変数があります。このようにPHPで最初から役割が定義されている変数を「スーパーグローバル変数」もしくは「組み込み変数」と呼びます。

このような変数は、たいてい「_(アンダーバー)」から始まる大文字のアルファベットで生がつけられています。

よく使うスーパーグローバル変数

スーパーグローバル変数 意味
$_SERVER サーバー情報と実行時の環境情報
$_GET GET送信されたデータ
$_POST POST送信されたデータ
$_COOKIE Cookieの値
$_FILES アップロードしたファイルの情報
$_REQUEST HTTPリクエストのすべての情報
$_SESSION セッションに関する情報
$_ENV 環境変数

たとえば、「$_GET」には、通常の変数とは違って変数名の後に[]がついています。
このような変数は「配列」変数といい、1つの変数に複数の値を保存できるという特徴があります。使用する場合は、$変数名[~]の形で使い、~の部分で保存してある複数の値から1つを特定します。

$_GETが配列変数になっているのは、たとえばショッピングサイトでは「商品名」と「単価」と「個数」などをひとくくりで扱いたい場合が多いですし、掲示板では書き込んだ人の「ID」と「メッセージ」を同じくひとくくりで扱いたいことが多いためです。配列を使うと、上記のような複数の値を1つの変数で扱えるので、プログラムを簡素化することが可能です。

https://www.php.net/manual/ja/reserved.variables.php
https://www.php.net/manual/ja/language.variables.superglobals.php

組み込み関数ってなに?

PHP言語には、さまざまな関数があらかじめ用意されています。これらの関数を「組み込み関数」といいます。よく使う関数の名前と機能を覚えておきましょう。

文字列関数

文字列の中身を調べる、一部を取り出す、置換や変換を行うといった組み込み関数が用意されています。

関数名 説明
chr ASCII(アスキー、American Standard Code for Information Interchange)値から文字に変換
explode 文字列の分割
htmlspecialchars HTML特殊文字をHTMLエンティティに変換する
htmlspecialchars_decode 特殊なHTMLエンティティを文字に戻す
implode 配列要素を文字列により連結する
lcfirst 文字列の最初の文字を小文字にする
ltrim 文字列の最初から空白 (もしくはその他の文字) を取り除く
money_format 数値を金額文字列にフォーマット変換する
nl2br 改行文字の前にHTMLの改行タグbrを挿入する
number_format 数字を千の位毎にグループ化してフォーマット変換する
ord 文字列の先頭バイトを、0 から 255 までの値に変換する(ASCII値に変換する)
rtrim 文字列の最後から空白 (もしくはその他の文字) を取り除く
similar_text 2つの文字列の間の類似性を計算する
str_getcsv CSV文字列をパースして配列に格納する
str_ireplace 大文字小文字を区別しない str_replace()
str_pad 文字列を固定長の他の文字列で埋める
str_repeat 文字列を反復する
str_replace 検索文字列に一致したすべての文字列を置換する
str_split 文字列を配列に変換する
stripos 大文字小文字を区別せずに文字列が最初に現れる位置を探す
stristr 大文字小文字を区別しない strstr
strlen 文字列の長さを得る
strpos 文字列内の部分文字列が最初に現れる場所を見つける
strstr 文字列が最初に現れる位置を見つける
strtolower 文字列を小文字にする
strtoupper 文字列を大文字にする
substr 文字列の一部分を返す
substr_replace 文字列の一部を置換する
trim 文字列の先頭および末尾にあるホワイトスペースを取り除く
ucfirst 文字列の最初の文字を大文字にする
ucwords 文字列の各単語の最初の文字を大文字にする
wordwrap 指定した文字数で文字列を分割する

https://www.php.net/manual/ja/book.strings.php

数学関数

三角関数や指数、対数計算などの数学で使用される関数のほか、数値の丸めや10進数と2進数の変換などの組み込み関数が用意されています。

関数名 説明
sin 三角比の正弦(サイン)
cos 三角比の余弦(コサイン)
tan 三角比の正接(タンジェント)
asin 正弦(アークサイン)
acos アークコサイン
atan アークタンジェント
exp 指数関数
log 自然対数
log10 底が10の対数
pow べき乗
sgrt 平方根
ceil 切り上げ
floor 切り捨て
round 四捨五入
abs 絶対値
max 最大値
min 最小値
rand 乱数
pi 円周率
deg2rad 度をラジアンに変換
rad2deg ラジアンを度に変換
bindec 2進数を10進数に変換
decbin 10進数を2進数に変換
dechex 10進数を16進数に変換
hexdec 16進数を10進数に変換
is_nan 数値の判定
is_finite 有限の数値の判定
is_infinite 無限大の判定

https://www.php.net/manual/ja/book.math.php

日付関数

日付のチェックや取得、操作、書式変更などの組み込み関数が用意されています。

関数名 説明
checkdate 日付(グレゴリオ暦)/時刻の妥当性を確認します
date タイムスタンプを日付文字列に変換
getdate 日付/時刻情報を取得する
time 現在のタイムスタンプを取得
gettimeofday 現在の時刻を取得
localtime ローカルタイムを取得
mktime 日付をタイムスタンプに変換
strtotime 日付文字列をタイムスタンプに変換

https://www.php.net/manual/ja/book.datetime.php

PHP5.2以降では、DateTimeクラスのメソッドとしても用意されています

メソッド 説明
DateTimeコンストラクタ DateTimeオブジェクトを生成
DateTime::format 指定した書式に変換
DateTime::setDate 日付を設定
DateTime::setTime 時刻を設定
DateTime::add 年月日時分秒の値を足す
DateTime::sub 年月日時分秒の値を引く
DateTime::diff 2つの日付の差
DateTime::modify タイムスタンプを変更
DateTime::getTimestamp タイムスタンプを取得
DateTime::setTimestamp タイムスタンぷから日付と時刻を設定
DateTime::getTimezone タイムゾーンを取得
DateTime::setTimezone タイムゾーンを設定

https://www.php.net/manual/ja/book.datetime.php

DateTimeクラスのメソッドは、次の関数としても使用できる

メソッド 説明
date_create 新しいDateTimeオブジェクトを作成(生成)する
date_format 指定した書式に変換
date_date_set 日付を設定
date_time_set 時刻を設定
date_add 年月日時分秒の値を足す
date_sub 年月日時分秒の値を引く
date_diff 2つの日付の差
date_modify タイムスタンプを変更
date_timestamp_get タイムスタンプを取得
date_timestamp_set タイムスタンプから日付と時刻を設定
date_timezone_get タイムゾーンを取得
date_timezone_set タイムゾーンを設定

https://www.php.net/manual/ja/ref.datetime.php

これらのほかにも、ファイル操作やデータベース操作、画像処理やメール関連、ネットワーク関連など、さまざまな組み込み関数が用意されています。

文字列の中身を調べるにはどうしたらいいの?

PHP言語には、文字列の長さや含まれる文字を調べたり、文字列の一部を取り出したりするための組み込み関数が用意されています。ここでは、よく使う関数をいくつか紹介します。

strlen

文字の長さ(バイト数)を求める関数です。

strlen(文字列);

例:変数$zipにセットされた郵便番号の長さを調べる。

$zip = '123-4567';
$length = strlen($zip);
echo $length; //結果 8

strpos

文字列の中から調べたい文字列を探し、最初に現れる位置を返す関数です。先頭の文字の位置は0です。文字列が見つからないときはFALSEを返します。

strpos(文字列, 調べたい文字列);

例:変数$emailにセットされたメールアドレスの中に「@」が入っているかどうかを調べる。

$email = 'taro@example.co.jp';
$position = strpos($email, '@');
echo $position; //結果 4

文字列の中に、「@」が入っていなければ、変数$positionには、FALSEがセットされます。
https://www.php.net/manual/ja/function.strpos.php

strstr

文字列の中から調べたい文字列を探し、最初に現れた位置から最後までの文字列を取り出す関数です。文字列が見つからないときはFALSEを返します。

strstr(文字列, 調べたい文字列);

例:変数$emailにセットされたメールアドレスから「@」以降のドメイン名を取り出す。

$email = 'taro@example.co.jp';
$domain = strstr($email, '@');
echo $domain; //結果 @example.co.jp

文字列の中に、「@」が入っていなければ、変数$domainには、FALSEがセットされます。

substr

文字列の1部を取り出す関数です。第2引数で指定した開始位置から第3引数で指定した長さ(バイト)の文字列を取り出します。先頭の文字の位置は0です。

substr(文字列, 開始位置, 長さ)

例:変数$birthdayにセットされた誕生日から誕生月を取り出します。
変数$birthdayにセットされた文字列の5番目から2文字(2バイト)の文字列を取り出します。

$birthday = '1917/05/29';
$month = substr($birthday, 5, 2);
echo $month; //結果 05

長さを省略すると、開始位置から最後までの文字列を返します。

$birthday = '1917/05/29';
$month_day = substr($birthday, 5);
echo $month_day; //結果 05/29

substr関数は、strpos関数と組み合わせてよく使用されます。

変数$birthdayにセットされた誕生日から誕生月を取り出したいけれども、月の位置が「5」番目かどうかわからない場合は、次のようにstrpos関数で最初に出てくる「/」の位置を調べます。

$birthday = '1917/05/29';
$position = strpos($birthday, '/');
$month = substr($birthday, $position + 1, 2); //「/」の1つ後ろなので「+1」
echo $month; //結果 05

strlenやstrpos、substrなどの文字の長さや位置を扱う関数は、シングルバイト文字列に対応した組み込み関数です。日本語のようなマルチバイト文字列(1文字が2バイト以上の文字列)を扱うと、想定外の結果となってしまいます。
マルチバイト文字列を扱う場合は、次のような組み込み関数を使用します。これらの関数は、マルチバイト文字を1文字とカウントします。

strlen → mb_strlen
strpos → mb_strpos
strstr → mb_strstr(※PHP5.2以降)
substr → mb_substr

※「mb」はマルチバイト(MultiByte)の略。

なお、マルチバイト文字列関数を使用する際は、プログラムを記述した文字コードとPHP側の内部エンコーディングを一致させる必要があるので、注意しましょう。

文字列を置換・変換するにはどうしたらいいの?

文字列の置換や、大文字/小文字を変換するための組み込み関数をいくつか紹介します。

str_replace

文字列の中にある文字列を探し、別の文字列に置換する関数です。置換した結果の文字列を返します。

str_replace(探す文字列, 置換する文字列, 文字列);

例:変数$message1にセットされた文字列を置換する。

$message1 = 'キミ、誰?キミも来ちゃいなよ。';
$message2 = str_replace('キミ', 'You', $message1);
echo $message2; //結果 You、誰?Youも来ちゃいなよ。

「キミ」という言葉を探し、2箇所にあったすべての「キミ」を「You」に置き換えて、$message2に代入しています。

strtolower

アルファベットを小文字に変換する関数です。文字列の中の半角文字のアルファベットをすべて小文字に変換した文字列を返します。

strtolower(文字列);

例:変数$message1にセットされた文字列に含まれるアルファベットを、すべて小文字に変換する。

$message1 = '失敗は成功のMother。';
$message2 = strtolower($message1);
echo $message2; //結果 失敗は成功のmother。

strtoupper

アルファベットを大文字に変換する関数です。文字列の中の半角文字のアルファベットをすべて大文字に変換した文字列を返します。

strtoupper(文字列);

例:変数$message1にセットされた文字列に含まれるアルファベットを、すべて大文字に変換する。

$message1 = '失敗は成功のMother。';
$message2 = strtoupper($message1);
echo $message2; //結果 失敗は成功のMOTHER。

全角文字を半角文字(半角文字を全角文字)に変換するマルチバイト文字列用の組み込み関数もあります。

mb_convert_kana(文字列, 変換オプション)

変換オプションには次の値を指定できます。オプションは"KV"のように組み合わせて使用します。

数値を丸めるには?

数値を丸めるための組み込み関数をいくつか紹介します。

ceil

小数点以下を切り上げて整数の値を返す関数です。大きいほうの整数値を返します。

ceil(切り上げたい数値);
$a = ceil(4.1);
echo $a; //結果 5

floor

小数点以下を切り捨てて整数の値を返す関数です。小さいほうの整数値を返します。

floor(切り捨てたい数値);
$a = floor(4.1);
echo $a; //結果 4

round

任意のケタを四捨五入する関数です。整数に丸めるだけでなく、任意のケタの少数に丸めることもできます。

round(四捨五入したい数値, 少数点以下のケタ数);

第2引数の「小数点以下のケタ数」は省略できます。省略すると、「小数点以下のケタ数」には「0」がセットされ、小数点第1位以下が四捨五入された整数の値が返ります。

$a = round(4.4);
$b = round(4.5);
echo $a; //結果 4
echo $b; //結果 5

round関数の第2引数「少数点以下のケタ数」に「2」を指定すると小数点第3位が四捨五入されて小数点第2位までに丸めることができます。

$a = round(4.444, 2);
$b = round(4.445, 2);
echo $a; //結果 4.44
echo $b; //結果 4.45

マイナスの値(例:「-4.5」)を丸めると次のような結果となります。

$a = ceil(-4.5);
$b = floor(-4.5);
$c = round(-4.5);
echo $a; //結果 -4
echo $b; //結果 -5
echo $c; //結果 -5

日付や時刻を操作するには?

日付や時刻は、数値や文字列とは計算方法や扱い方が違います。ここでは、日付や時刻の計算や値の取り出し方、書式を設定するための組み込み関数をいくつか紹介します。

checkdate

日付の妥当性チェックを行う関数です。指定した日付に問題がなければTRUE、日付として問題があればFALSEを返します。

checkdate(,,);

引数の月、日、年には、数値を渡します。
例:うるう年を調べる。

$check = checkdate(2, 29, 2012);
var_dump($check); //結果 bool(true)
echo $check; //結果 1

2012年の2月29日は存在するので、変数$checkには、boolean型のTRUEがセットされる。

$check = checkdate(2, 29, 2013);
var_dump($check); //結果 bool(false)
echo $check; //結果 空

2013年の2月29日は存在しないので、変数$checkには、boolean型のFALSEがセットされる。

DateTimeコンストラクタ

DateTimeクラスのオブジェクト(DateTimeオブジェクト)を生成する特別なメソッドです。new演算子とともに使用し、DateTimeオブジェクトを返します。このようなメソッドをコンストラクタといいます。

DateTime(日付);

引数の日付には、「Y-m-d」(年-月-日)の書式の文字列を渡します。引数を省略すると、現在の日付のDateTimeオブジェクトが生成されます。

$date = new DateTime('2012-02-29');

変数dateに、2012年2月29日のDateTimeオブジェクトがセットされる。
日付として妥当ではない文字列が渡された場合は、例外(Exception)が発生します。

$date_creat関数

DateTimeコンストラクタの代わりにdate_create関数を使って、DateTimeオブジェクトを生成することもできます。

date_creat(日付);

引数の日付には、「Y-m-d」(年-月-日)の書式の文字列を渡します。引数を省略すると、現在の日付のDateTimeオブジェクトが生成されます。

<?php
$date = date_create('2012-02-29');
var_export($date);
//結果
/*
DateTime::__set_state(array(
   'date' => '2012-02-29 00:00:00.000000',
   'timezone_type' => 3,
   'timezone' => 'UTC',
))
*/
?>

日付として妥当ではない文字列が渡された場合には、FALSEを返します。

DateTime::format ※クラス「DateTime」のメソッド「format」

DateTimeオブジェクトから、指定した日付フォーマットに変換した文字列を取り出すメソッドです。

DateTime::format(日付フォーマット);

formatメソッドに指定できる日付フォーマットについては、56ページの表を参照してください。
オブジェクト指向プログラミングでは、メソッドは「->」を使って次のように呼び出します。

クラスのオブジェクト -> メソッド(引数1, 引数2, ...

例:変数dateにセットされた2012年2月29日のDateTimeオブジェクトから、年、月、日をそれぞれ文字列として取り出す。

$date = new DateTime('2012-02-29'); //new ~ はクラスを使う時のルール
$year = $date->format('Y'); //クラスに対するメソッドを「->」で使う
$month = $date->format('m');
$day = $date->format('d');

date_format関数

formatメソッドの代わりにdate_format関数を使って、指定した日付フォーマットに変換した文字列を取り出すこともできます。

date_format(DateTimeオブジェクト, 日付フォーマット);

例:date_format関数を使って、変数dateにセットされた2012年2月29日のDateTimeオブジェクトから年、月、日をそれぞれ文字列として取り出す。

$date = date_create('2012-02-29'); //こっちはクラスではなく関数
$year = date_format($date, 'Y'); //こっちはクラスではなく関数
$month = date_format($date, 'm');
$day = date_format($date, 'd');
var_dump($date);
var_dump($year);
var_dump($month);
var_dump($day);

DateTime::modify ※クラス「DateTime」のメソッド「modify」

DateTimeオブジェクトの日付(タイムスタンプ)を変更するメソッドです。

DateTime::modify(変更したい日付の文字列);

引数に渡す文字列は日付フォーマットで記述できる日付のほかに「+1 day」「-1 month」「tomorrow」「yesterday」などの相対的な日付の記述も指定することができます。
例:変数dateにセットされた2012年2月29日のDateTimeオブジェクトを翌日に変更する。

$date = new DateTime('2012-02-29');
$date->modify('+1 day');

変数dateの値が、2012年3月1日のDateTimeオブジェクトに変更される。
「+1 day」は1日プラスするという意味です。「-5 day」と指定すると、5日前の日付になります。数字は自由に指定できます。

date_modify関数

modifyメソッドの代わりにdate_modify関数を使って、Datetimeオブジェクトの日付を変更することもできます。

$date = date_create('2012-02-29');
$next_date = date_modify($date, '+1 day');

変数$next_dateに、2012年3月1日のDateTimeオブジェクトがセットされる。
date_modify関数は変更されたDateTimeオブジェクトを返します。

変数dateにセットされた2012年の1月31日のDateTimeオブジェクトを翌月に変更したいときには、「+1 month」を使ってもいいのでしょうか?

$date = new DateTime('2012-01-31');
$date->modify('+1 month');

変数$dateの値は2012年3月2日のDateTimeオブジェクトに変更される。
「+1 month」では、単に月に1プラスされるのではなく、経過する月の日数分が加算されます。2012年1月の日数は31日なので、2012年1月31日+31日の2012年3月2日がmodifyメソッドの結果として返されます。

count()関数

配列、またはCountableオブジェクトに含まれるすべての要素の数を数える関数です。

https://www.php.net/manual/ja/function.count.php
https://www.sejuku.net/blog/21809

変数が存在するか調べるisset()関数、empty()関数

引数に指定した変数が既に存在していればTRUEを返します。存在していても
格納されている値がNULLの場合はFALSEとなります。
また、複数の変数を引数に指定した場合は、全ての変数が存在している場合にTRUE
となります。

引数:var 調べる変数。
返り値:varが 存在している場合に TRUE 、それ以外の場合に FALSE

<?php
$var1 = 'test';
if (isset($var1)){
   print('変数$var1は存在し、値は'.$var1.'です<br><br>');
}else{
   print('変数$var1は存在しないかNULLです<br><br>');
}

//配列の値を確認することも可能
if (isset($a['name'])) {
	// 存在し、nullではありません
} else {
	// 存在しない、もしくはnullです
}

//issetの特徴
if (isset($hoge)) {
    echo '値を持っている';
} else {
    echo '値を持ってない';
}

//emptyの特徴
if (empty($hoge)) {
    echo '「値がない」or「0」or「false」or「null」';
} else {
    echo '値を持っている';
}
?>

エラーについて

PHP Parse error: syntax error,

コードに文法のエラーがある場合に表示されますがほとんどの原因が入力ミスです。エラーメッセージの解釈や行番号のように集中してしまうと解決が遅れてしまいます。
また、PHPをバージョンアップしたタイミングで、バージョンの違いによる構文ミスが発生し、Parse errorになることもあります。

PHP Parse error: syntax error, unexpected token

<エラーケース>

  • コメントアウト「//」の前に半角ではなく、全角スペースが入っていた。
  • 処理の最後に「;」が抜けていた。特にreturn文の後の抜けに注意。

PHP Fatal error: Uncaught ArgumentCountError: Too few arguments

  • 引数が設定されている関数を呼び出す際に、引数の値を入力していなかった時。

PHP Warning: Undefined variable #変数 in 対象ソースの箇所

  • 「#変数」がNULLまたは、定義されていません。
  • 呼び出す変数に値が入っていなかった場合。引数が設定されている関数も含む。

PHP Fatal error: Uncaught Error: Object of class DateTime could not be converted to string in 対象ソースの箇所

「DateTime」オブジェクトは「String」にコンバートして「echo」で出力はできないというエラー。
var_dump()で中身を確認。

Warning: Undefined array key "a" in 対象ソースの箇所

  • GET送信した時に、まだ、「a」というkeyが存在していない場合。

ブラウザの種類を判定するプログラムを書いてみよう

echo getenv('HTTP_USER_AGENT'); //オンラインエディタでは表示されない場合があります。

各ブラウザで開いて実行してみると、以下のような結果が返ってきます。

Google Chrome(114.0.5735.199(Official Build)/ 64bit)

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36

Firefox(114.0.2 / 64bit)

Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0

Microsoft Edge Chromium版(114.0.1823.67(公式ビルド)/ 64bit)

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.67

Microsoft Edge(IEモード)

Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; Touch; .NET4.0C; .NET4.0E; Tablet PC 2.0; Zoom 3.6.0)

ブラウザ判定してみよう

$ua = getenv('HTTP_USER_AGENT');

if (stristr($ua, 'Edge')) {
  echo "あなたが今見ているブラウザは「Microsoft Edge」ですね。";
} elseif (stristr($ua, 'Edg')) {
  echo "あなたが今見ているブラウザは「Microsoft Edge(Chromium版)」ですね。";
} elseif (stristr($ua, 'Chrome')) {
  echo "あなたが今見ているブラウザは「Chrome」ですね。";
} elseif (stristr($ua, 'Firefox')) {
  echo "あなたが今見ているブラウザは「Firefox」ですね。";
} elseif (stristr($ua, 'Safari')) {
  echo "あなたが今見ているブラウザは「Safari」ですね。";
} else {
  echo "判定ができないブラウザを使用されています。";
}

各ブラウザで表示してみてください。
※オンラインエディタではうまく判定されず、表示されない場合があります。

getenv()関数は、環境変数の値をひとつ、または全て取得します。
phpinfo()関数を使えばすべての環境変数の一覧を見ることができます。

getenv関数のenvとは、一致する並び(environment list)のこと。

※PHP7.1.0から「name」は、すべての環境変数の連想配列を取得するために 省略することができるようになりました。

また、$_ENV(環境変数)とは $_ENVは、PHPの定義済み変数の環境変数です。 この変数は、現在のスクリプトに渡された環境の値の変数です。 ドキュメントルートのルートディレクトリやサーバーのIPアドレスなどの環境情報を取得することが出来ます。

https://www.php.net/manual/ja/function.getenv.php
https://blanche-toile.com/web/php-useragent-browser
https://www.twilio.com/ja/blog/working-with-environment-variables-in-php-jp

プログラムの基本「Hello World」を表示しよう

HTMLの基本、スケルトンを用意しましょう。
HTMLの基本骨格をスケルトン(skeleton)と呼びます。
最低限あればHTMLを表示できる、基本構文の事です。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  実際にwebページで表示される内容
</body>
</html>

HTMLスケルトンの「body」の中に入力をしていきます。

<?php echo 'Hello World'; ?>

PHPの構文ルール

  • すべて半角で入力する
  • 大文字・小文字を区別する
  • スペルを絶対間違えないようにする
  • 全角スペースを入れない
  • 命令文の最後には必ず「;(セミコロン)」をつける
  • 波括弧「{}」は命令文ではないので、{}の最後には、「;(セミコロン)」はつけない
  • 関数は、「関数名();」のように関数名のあとに「()」をつけた形で記述される
  • 変数は、先頭に「$」をつける
  • 変数名には、アルファベットか数字、または「_(アンダースコア)」を使う
  • 変数名は、数字を先頭にすることはできない

コンピュータとジャンケンで戦ってみよう

rand()関数を使ってみよう

rand()関数とは、乱数(規則性のない数字)を生成します。
ここでの乱数とは、0以上の整数を意味し、上限はこれを実行するOSごとに異なります。

<?php
echo rand(); 
//結果
//1回目:449271482
//2回目:2138447674
//3回目:1498269555
//4回目:187930075
//5回目:267791180
?>

rand()関数は、引数無しの場合、0以上2147483647以下(64ビット版Windowsの場合)の整数を返します。OSによっても違います。引数(min-最小値,max-最大値)を設定することで、最小値から最大値の間の整数を返します。つまり「rand(1,3)」は、整数「1」「2」「3」のどれかを返します。

この乱数を変数に保存してジャンケンのプログラムを書いてみます。

<?php
//ジャンケンは、分岐が「グー」「チョキ」「パー」の3パターン

$janken = rand(1,3); //引数(min-最小値,max-最大値)を渡す

//変数「$janken」は最小が1~最大3までの整数を返します。
echo '変数jankenの値は「' . $janken .'」です。' . "\n";

//分岐
if ($janken == 1) {
    echo 'コンピュータは、グーを出しました';
} elseif ($janken == 2) {
    echo 'コンピュータは、チョキを出しました';
} else {
    echo 'コンピュータは、パーを出しました';
}
?>

https://www.php.net/manual/ja/function.rand.php

GET送信について知ろう

「データを送るWebページ」、そして「送られたデータを処理する」プログラムを作ってみましょう。

ショッピングサイトで何かを購入する場合、数量を指定すると指定した数値が確認画面に表示されますよね。この場合、ユーザーが入力した数量をWebサーバーが受け取って、その数量を確認画面に表示するようなプログラムを書く必要があります。そのようなときに利用できるのが「$_GET」です。

最初に作っていただくプログラムは「echo $_GET['送信データ名']」のたった1行だけです。やっていることは単純です。

①まず最初にphpファイルに以下のプログラムを書く。

test.php
echo $_GET['a'] //送信データ名「a」の値を取得する。

②ブラウザを開いて、urlの後に、「?a=testGET」と入力する。
すると、ブラウザに「a=」の中に入れた文字「testGET」が表示されます。

https://wepicks.net/phpref-get/

GET送信を使って送信用フォームを作ろう

HTMLフォームの基本構造

<form method="post" action="CGIのURI">
..(入力コントロールや説明)
</form>
sample.html
<form method="post" action="CGIのURI">
 <p>
 氏名:<input type="text" name="氏名" />
 性別:
 <input type="radio" name="性別" value="男" checked="checked" /> 男 
 <input type="radio" name="性別" value="女" /> 女
 所持品:
 <input type="checkbox" name="properties" value="CellPhone" /> 携帯電話
 <input type="checkbox" name="properties" value="Car" /> 自動車
 <input type="checkbox" name="properties" value="Cottage" /> 別荘 
 好きな果物:
 <select name="好きな果物">
   <option>りんご</option>
   <option>みかん</option>
   <option>バナナ</option>
   <option>パイナップル</option>
 </select>
 <textarea name="freeans" rows="4" cols="40">自由に意見を記述してください</textarea>
 <input type="submit" value="送信" /> 
 <input type="reset" value="取り消し" />
 </p>
</form>

簡単な例:

入力.html
<p>何か、入力して!</p>
<form method="get" action="受け取り側.php">
  <input type="text" name="a">
  <input type="submit" value="送信するよ">
</form>
受け取り側.php
<p>受け取ったデータの表示</p>
<?php
echo $_GET['a'];
?>

GETで送信をすると、受け取り側のURLの最後に、「?a=フォームから送信された文字列」が追加されていることが確認できます。ただし、フォームから送られた文字列が日本語(2バイト文字列)の場合、ブラウザによっては「%E5%9B%B0%E3・・・」のような意味不明の文字列で表示される場合もあります。これはURLエンコーディングという技術が関連しているのですが、ここでは詳しく解説しません。

https://www.kanzaki.com/docs/html/htminfo31.html
https://sejuku.net/blog/81862

GETとPOSTについて

GET送信は、「URLにデータをくっつけて送る」という仕組みでした。フォームから送信しても結局、URLに「?a=~」のようにデータをつけて送ることになります。

GET送信では、URLにむき出しのデータがくっつけられてネットワークを流れますので、セキュリティ上はあまり好ましくありません。データの受け渡しにはGET送信だけでなくPOST送信という方法もあり、formタグのmethod属性に「post」を指定するとPOST通信になります。実際、フォームによるデータ送信はPOST送信が使われるのがほとんどです。POST送信の場合、データはURLではなく別の方法で送られるほか、GET送信にはないメリットがあります。

GET送信とPOST送信の特徴

GET送信の特徴

  • URLに送信データを付けるため、外部から丸見え。不正なデータを送信される可能性もある。
  • formタグでmethod属性「method="get"」を省略でき、「$_GET」でデータを受け取る。
  • 送信できるデータはテキストだけ。送信できる情報量に制限がある。

POST送信の特徴

  • URLにデータを付けないので、外部から見えにくい
  • formタグで「method="post"」と指定し、「$_POST」でデータを受け取る。
  • 画像など、すべての種類のデータが送信できる。大量のデータも送信可。

POST送信で送られたデータは「_GET」ではなく、「_POST」というスーパーグローバル変数に格納されます。先ほどのGET送信のサンプルをPOST送信に置き換えた場合、次のように書くことができます。

入力.html
<p>何か、入力して!</p>
<form method="post" action="受け取り側.php">
  <input type="text" name="a">
  <input type="submit" value="送信するよ">
</form>
受け取り側.php
<p>受け取ったデータの表示</p>
<?php
echo $_POST['a'];
?>

上記のサンプルでは、入力側と、受け取り側でファイルを分けていましたが、実は、1ファイルのみでも送信と結果を表示することができます。

何か入力して.php
<p>何か、入力して!</p>
<form method="get" action="">
  <input type="text" name="a">
  <input type="submit" value="送信するよ">
</form>

<p>受け取ったデータの表示</p>
<?php
echo $_GET['a'];
?>

このように、フォームの「action」属性で送信先の省略をすると、自分自身(同一のファイル)にデータが送られてくるのです。

また、同一ファイルで実行すると分かるように、初回URLにアクセスしたときに、「Warning: Undefined array key "a" in 対象ソースの箇所」の警告が出ます。

そのため、isset()関数を使って、「$_GET['a'];」がまだ無い場合の時の表示もさせましょう。

何か入力して.php
<p>何か、入力して!</p>
<form method="get" action="">
  <input type="text" name="a">
  <input type="submit" value="送信するよ">
</form>

<p>受け取ったデータの表示</p>
<?php
echo isset($_GET['a'])?$_GET['a'] . 'であ~る!' : 'フォームに文字を入力して送信すると、文字の最後に「であ~る!」と表示されるよ。';
?>

※「isset() ? 真の場合の処理内容 : 偽の場合の処理内容 ;」三項演算子で、if-else分の省略系。

ちなみに、if文で書くと

<?php
if(isset($_GET['a'])) {
  echo $_GET['a'] . 'であ~る!' ;
} else {
  echo 'フォームに文字を入力して送信すると、文字の最後に「であ~る!」と表示されるよ。';
}
?>

何も入力されずに送信されば場合、「であ~る!」だけが表示されてしまうので、入力されなかった時の分岐処理も入れておきましょう。

echo isset($_GET['a']) && $_GET['a']!='' ? $mozi . 'であ~る!' : 'フォームに文字を入力して送信すると、文字の最後に「であ~る!」と表示される

「isset(_GET['a'])」は、「a」が存在するかどうかなので、「_GET['a']!=''」を使って、「a」の値が空でない場合にはという条件を追加します。
さらに「&&」を使うことで、「aが存在している」かつ「aの値が空でなければ」という条件にすることができます。

https://tech.hipro-job.jp/column/500
https://chusotsu-program.com/php-isset/
https://webgroove.work/php-if-isset-is_null-empty-elvis-null-operator-table/

「isset」などのオーバーロード

public __isset(string $name): bool

https://www.php.net/manual/ja/language.oop5.overloading.php
https://www.php.net/manual/ja/language.oop5.php

フォーム送信時の注意「悪意のあるタグを体験する」

例えば入力フォームに「<body bgcolor=yellow></body>」と入力したとする。
すると、どうでしょう。ブラウザの背景が、一面黄色くなってしまいました。

このように、送る人に悪意がある場合は予想外の実行結果が返ってくる場合があります。
このままでは、完全な欠陥プログラムです。

タグを無効化する

入力された文字を直接Webページに書き出してしまうアプリケーションは危険だ、ということが分かりました。一般に公開するWebアプリケーションでは、タグによる攻撃を防ぐ仕組みを作ることは必須です。

そんなときは、「htmlspecialchars」を使います。タグなどの特殊文字を無害な文字に変換する関数です。

通常「<」と「>」で囲まれた部分はタグだとブラウザから判断されてしまいますので、上記のようにそのまま表示されることはありません。この「htmlspecialchars」を使うと、「<」や「>」や「"」がなくなって、別の文字「実態参照」といった文字に置き換えられます。

htmlspecialchars(タグを無効化する文字列, ENT_QUOTES)

変換される記号

変換前 変換後 画面表示
< < <
> > >
" " "
' ' '
& & &

https://www.php.net/manual/ja/function.htmlspecialchars.php

取得したデータを記録する

フォームで入力した内容は、更新すると消えてしまうので、取得したデータを保存できるようにしましょう。

//悪意のあるプログラムタグを除去して、変数$moziに格納
$mozi = htmlspecialchars($_GET['a'] , ENT_QUOTES); //「ENT_QUOTES」シングルクオートとダブルクオートを共に変換します。

//いったん確認のため表示してみる
echo $mozi;

//第1引数に指定したファイルをオープンする、第2引数の「at」はファイルの末尾にどんどん追加されるモード
$fp = fopen('chat.txt','at'); //$fpとはファイルポインタのこと

//
fwrite($fp, $mozi . "\n");

fclose($fp);

テキストファイルに書き込むときは、まずファイルを「オープン」し「書き込み」、そしてファイルを「クローズ」します。プログラムの世界では、ファイルを扱う場合、「オープン」→「処理」→「クローズ」という流れが基本になっています。

fopen()関数

ファイルやURLをオープンする関数です。

$fp = fopen(オープンするファイル名またはURL,モード);

第1引数にはオープンするファイルを指定します。サンプルでは、「fopen('chat.txt','at');」となっていますので、「chat.txt」というファイルをオープンして処理できる状態にします。fopenを実行したときに、この「chat.txt」というファイルが無かった場合には、「chat.txt」を新規で作成してくれます。

また第2引数はファイルを開く場合の設定を指定しますが、「at」とするとファイルの末尾に追記するモードでテキストファイルを開きます。このほか、読み取り専用モードの「r」や、上書き保存するモードの「r+」など、いろいろなモードが指定できます。

ちなみに、「at」の場合はテキストモードで開き、「ab」の場合はバイナリモードで開きます。

オープンすると、fopenはファイルハンドルと呼ばれるものを返します。
サンプルプログラムでは、このファイルハンドルを変数「$fp」に代入しています。

メッセージの書き込みは、ファイルハンドル「$fp」を第1引数にして、メッセージそのものを第2引数にしてfwrite関数を実行します。

fwrite($fp, $mozi);

fwrite()関数

fwrite(ファイルハンドル, 書き込む内容);

fclose()関数

作業が終わったら、ファイルハンドルを引数として、fclose関数で、ファイルをクローズします。

fclose(ファイルハンドル);

記録したデータをWebページに表示する

テキストファイルに保存したデータを、表示するプログラムを作成します。
本来ファイルを読み込む場合も、「ファイルのオープン」→「ファイルの読み込み」→「ファイルのクローズ」という手順を踏む必要がありますが、ファイルの中身を表示するだけなら「readfile関数」を使って簡単に行う方法もあります。

readfile(ファイル名);

出力してみると、テキストファイルの中身では改行されていますが、表示されたテキストは、改行されてないことが確認できます。改行されない原因は、HTMLでは改行コードが無視されてしまう為です。

readfile関数は、「ファイルの全内容を標準出力に出力する関数」です。標準出力ってピンときませんが、コンピュータによる処理のデフォルトの出力先のことです。何も設定しなければ、標準出力はディスプレイ、標準入力はキーボードを意味します。

readfile関数で出力したテキストを改行して表示させるには

データを保存したテキストファイルには「\n」の改行コードを入れていました。readfile関数でWEBページに出力する時には、この改行は表示されません。

HTMLでは、改行コードや「"(ダブルクォーテーション)」で囲まない半角のスペースは無視されてしまうからです。HTMLで改行をする場合は「
」タグを使用しますが、すでに存在するファイルに書き込まれた文字列の合間に
タグを追加するのは、なかなか面倒な作業です。

そういう場合は、readfile関数の出力全体を「<pre>」タグで囲むという手法が便利です。
<pre>は文字列内の改行コードや半角スペースを、そのまま表示するタグです。ただし、<pre>~</pre>の中であっても「htmlspecialchars」でエンコードしていない場合は、「<」や「>」などはタグとして認識されてしまいますので、その点は注意してください。

echo "<pre>";
readfile("chat.txt");
echo "</pre>";

データを記録する時に、余計な改行が保存されないようにする

サンプルでは、以下のようにフォームに入力された「$mozi」に改行コード「\n」を付け足しています。

fwrite($fp, $mozi . "\n"); //$fpとは、ファイルポインタのこと。

しかし、このコードは$_GETが空の場合も実行されてしまうため、最初にphpファイルにアクセスしたときににも改行コードだけがどんどんファイルに保存されてしまいます。

これを解決するには、最初のアクセスなのか、フォームからメッセージを送信した後のアクセスなのかを調べて、メッセージ送信後の場合だけ、ファイルのへの書き込みを行うプログラムを作成します。そのためには「$_GET['a']」に文字がセットされているかを「isset関数」で調べます。

fwrite($fp, $mozi . "\n");

getやpostで送信したデータが重複しないようにリロード対策をしよう「自分自身にリダイレクトさせて解決しよう!」

sample.php
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>

<h1>GET送信のデータを処理して、取得したデータを保存して、出力してみよう(リロード時の重複対策含む)</h1>

<h2>送信フォームを作ろう</h2>
<p>何か、入力して!</p>
<form method="get" action="">
  <input type="text" name="a">
  <input type="submit" value="送信するよ">
</form>

<hr>

<h2>送信フォームからデータを「送信」して受け取ろう</h2>
<h3>プログラムの結果を表示</h3>

<?php
//記録するためのファイル名(ファイルパス)を指定
$filepath = 'chat.txt';

if(!isset($_GET['a'])){
  //パラメータ「a」が存在していない、またはNULLの場合の処理
  echo 'フォームに文字を入力して、送信してください。';

} elseif($_GET['a']==''){
  //パラメータ「a」は存在しているが、値が空だった場合の処理
  echo 'フォームに文字を入力して、送信してください。';

} elseif($_GET['a']!=''){
  //パラメータ「a」は存在していて、値が空でなかった場合の処理
  echo '値があります。入力データを記録します。';

  //指定したファイルパスにデータを記録します。
  $fp = fopen($filepath, 'at'); //$fpはファイルポイントの略。
  $mozi = htmlspecialchars($_GET['a'], ENT_QUOTES); //「ENT_QUOTES」シングルクオートとダブルクオートを共に変換します。
  fwrite($fp, $mozi . "\n\n");
  fclose($fp);
} else {
  //上記のどの条件に当てはまらなかった場合の処理
  echo '予期せぬ分岐です。プログラムを確認してください。';
} //END


//記録したデータをブラウザに出力します。
if (!file_exists($filepath)) {
  //もし対象のファイルパスが存在していないか、NULLの場合
  echo '<hr>';
  echo '<h3>データを出力しています...</h3>';
  echo '対象のファイル「' . $filepath . '」が見つかりません。';
} else {
  echo '<hr>';
  echo '<h3>データを出力しています...</h3>';
  echo '<pre>';
  readfile($filepath);
  echo '</pre>';
  echo '<br><br>';
}

//フォームの不具合を解消するリダイレクトのため現在のURLを取得
$url = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

//現在のURL取得(「パーセントエンコード」になっている文字をデコードして表示)
$url_decode = urldecode($url);

//現在のURLからパラメータのみを取得
$param = parse_url($url_decode, PHP_URL_QUERY);

//パラメータ分割
parse_str($param, $param_out);
echo "<h3>パラメータを分割して、aの値を表示</h3>" .  $param_out['a'] . "<br><br>";  // value

//パラメータの値をunsetで削除して、キーの「a=」部分を削除する文字列として代入
//unset($param_out['a']);
$param_delete_key = "a=" . $param_out['a'];
echo "<h3>URLから削除するパラメータの文字列を表示</h3>" . $param_delete_key . "<br><br>";  // value

//文字列置換を使って、検索置換を行う
$url_replace = str_replace($param_delete_key,"",$url_decode);

//preg_replaceしたURLでパラメータの繋ぎ目が「?&」となっていた場合「?」のみにする。
$url_replace_fix = str_replace("?&","?",$url_replace);


//パラメータが1つもなければ、現在のURL($url)を返して終了
if (!$param) {
  echo "パラメータが1つも存在していないので、returnに「 " . $url . " 」を渡して離脱します。<br><br>";

  if(mb_substr($url , -1) == '?'){
    echo "URLの最後が「?」で終わっているので「?」を削除してURLを返します";
    $url_judge = mb_substr($url ,0 , -1);

    //header関数を使用し、リダイレクトさせる。
    //header('Location:' . 'http://localhost/suzune/testtest04.php' );
    header('Location:' . $url_judge );
    exit;
  } else {
    echo "returnの戻り値は「 " . $url . " 」になりました。分岐1<br><br>";
    return $url;
    exit;
  }
  
} else {
  echo "パラメータが1つ以上存在しています。";

  if(mb_substr($url_replace_fix , -1) == '?'){
    echo "URLの最後が「?」で終わっているので「?」を削除してURLを返します";
    $url_replace_fix_judge = mb_substr($url_replace_fix ,0 , -1);
    
    //header関数を使用し、リダイレクトさせる。
    //header('Location:' . 'http://localhost/suzune/testtest04.php' );
    header('Location:' . $url_replace_fix_judge );
    exit;
  } else {
    echo "returnの戻り値は「 " . $url_replace_fix . " 」になりました。分岐2<br><br>";
    return $url_replace_fix;
    exit;
  }
}
?>

</body>
</html>

https://www.google.com/search?q=php+get送信+リロード&oq=php+get送信 リロード&aqs=chrome..69i57j69i64.9008j0j7&sourceid=chrome&ie=UTF-8

PHPでファイルの存在チェック「file_exists関数」

fputcsv関数

fputcsv関数を使うと、配列の値をCSV形式(カンマ「,」で区切られたデータ形式)でファイルに書き込むことができます。

排他制御「flock関数」について

操作の途中に登場するファイルのロックは排他制御といい、同じファイルに対して複数のユーザーから同時にアクセスされる可能性がある場合にデータの整合性を保つため、先にファイルを開いたユーザーがそのファイルを閉じるまでは他のユーザーからは操作出来ないようにする仕組みとなります。

排他制御はflock関数を使って行い、読み込み時と書き込み時でそれぞれ共有ロック、排他ロックという方法をモードの指定によって使い分けます。

PHPでURLやパラメータを取得する方法

https://blog.codecamp.jp/php-request-url
https://kakechimaru.com/php_url/

PHPでURLからパラメータを全て削除する方法

https://nullnull.dev/blog/php-remove-url-parameters/
https://www.google.com/search?q=php+対象のパラメータを削除&oq=php+対象のパラメータを削除&aqs=chrome..69i57j0i546l2j69i64.8118j0j7&sourceid=chrome&ie=UTF-8
https://blog.megefeps.info/20201207/phpurlからパラメータを削除する方法/
https://minamiblog-0601.com/php_header/
https://dgcolor.info/blog/87/
https://www.google.com/search?q=php パラメータ削除&ei=Jxi1ZIKbNp-O2roPgraFmAI&ved=0ahUKEwjCytq-xJWAAxUfh1YBHQJbASMQ4dUDCA8&uact=5&oq=php パラメータ削除&gs_lp=Egxnd3Mtd2l6LXNlcnAiG3BocOOAgOODkeODqeODoeODvOOCv-WJiumZpDIFEAAYgARIgk5QlRlYkktwAXgBkAEAmAGzAaAB1hqqAQQwLjI0uAEDyAEA-AEBwgIKEAAYRxjWBBiwA8ICBxAAGIoFGEPCAgoQABiKBRixAxhDwgIHEAAYBBiABOIDBBgAIEGIBgGQBgo&sclient=gws-wiz-serp
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q11228897706
https://blog.fkoji.com/2012/02262148.html

unset()関数

https://www.php.net/manual/ja/function.unset.php

header()関数を使ってリダイレクトさせよう

https://minamiblog-0601.com/php_header/
https://qiita.com/fujisawakoichi/items/e954d2210c83f94125bd

parse_url()関数

URL を解釈し、その構成要素を返します。
https://www.php.net/manual/ja/function.parse-url.php

parse_str()関数

文字列を処理し、変数に代入する関数です。
https://www.php.net/manual/ja/function.parse-str.php

strtok()関数

文字列をトークンに分割する関数です。
https://www.php.net/manual/ja/function.strtok.php
https://webkaru.net/php/function-strtok/

preg_replace()関数

https://www.google.com/search?q=Warning%3A+preg_replace()%3A+Delimiter+must+not+be+alphanumeric%2C+backslash%2C+or+NUL+in&oq=Warning%3A+preg_replace()%3A+Delimiter+must+not+be+alphanumeric%2C+backslash%2C+or+NUL+in&aqs=chrome..69i57j69i58.455j0j7&sourceid=chrome&ie=UTF-8
https://1-notes.com/php-error-delimiter-must-not-be-alphanumeric-or-backslash/
https://okwave.jp/qa/q3075639.html

file_exists()関数

ファイルまたはディレクトリが存在するかどうか調べる関数です。
指定したパスがファイルまたはディレクトリの場合に論理値のtrueを返します。
存在しなかった場合は、falseになります。

is_file関数を使うと、ファイルが存在するか確認できました。
ディレクトリかファイルかどちらのパスでもtrueにしたいときにはfile_exists関数を使っていきましょう。
https://www.php.net/manual/ja/function.file-exists.php

is_file()関数

is_file関数を使うと、指定したパスがファイルだった場合に論理値のtrueを返してくれます。
存在しないパスを指定してファイルがなかったり、ディレクトリだった場合はfalseが返ってきます。

is_file関数を使うと、ファイルが存在するか確認できました。
ディレクトリかファイルかどちらのパスでもtrueにしたいときにはfile_exists関数を使っていきましょう。
https://codelikes.com/php-file-exists/

urlencode()関数とurldecode()関数

https://www.php.net/manual/ja/function.urlencode.php
https://www.php.net/manual/ja/function.urldecode.php
https://www.sejuku.net/blog/25909
https://tech-unlimited.com/urlencode.html
https://www.findxfine.com/programming/php/995561507.html
https://phpjavascriptroom.com/?t=php&p=string

表示しているページのURLからフラグメント(ハッシュタグ)取り出す

PHPに詳しい方なら$_SERVER[xxx]でなんとかできそうかなと思いつくと思うのですが、あれこれ調べてみた結論としてはPHPでは実現することができません。
じゃあ他の方法はというとJavaScriptでは下記のように簡単に実装できる。

const output = location.hash;     // '#abcde'

なぜなら、フラグメントはクライアントサイドのための文字列であるということだと思います。
アクセスログのURLには#から先がなくなっていました。 明確な挙動について読み解けなかったんですが、#より後ろの文字列はサーバに届かないようです。
URI#fragent?query=1 このようにクエリパラメータを#以後に付けてしまうとサーバまで届かないのでご注意を。

https://www.web-dev-qa-db-ja.com/ja/php/phpのurlからフラグメント(ハッシュ「#」の後の値)を取得します/968478824/
https://www.tairaengineer-note.com/php-parse_url/
https://goke.work/programing/407
https://www.suzu6.net/posts/200-redirect-fragment-identifier/
https://koseki.hatenablog.com/entry/20120210/phpuri
https://twotone.me/web/1860/

https://www.php.net/manual/ja/function.fopen.php
https://trios.pro/php-fopen/
https://www.sejuku.net/blog/24369
https://it-kyujin.jp/article/detail/1061/
https://pointsandlines.jp/server-side/php/fopen-1
https://www.javadrive.jp/phpfunc/file/index1.html
https://codelikes.com/php-file-write/
https://yu-nix.com/archives/php-fopen/
https://www.flatflag.nir87.com/file_exists-888
https://tech.amefure.com/php-redirect
https://minamiblog-0601.com/php_header/
https://www.php.net/manual/ja/function.urlencode.php
https://sossy-blog.com/useful/3539/
https://www.t3a.jp/blog/web-develop/get-page-url/
https://arma-search.jp/article/php-url

php 文字削除

置換したい。
末尾の最後の文字を削除したい。
などいろいろな削除の仕方があります。
https://www.google.com/search?q=php+文字削除&oq=php 文字削除&aqs=chrome..69i57j0i512j0i30l2j0i8i30j69i64.4562j0j7&sourceid=chrome&ie=UTF-8
https://qiita.com/SOJO/items/bb24e7d09320ea96cfc3
https://renoji.com/IT.php?Contents=Program_PHP/String_Delete_Text.html
https://qumeru.com/magazine/82
https://qumeru.com/magazine/261

PHPでヘッダーやフッターを読み込む方法

https://blanche-toile.com/web/web-common-php

PHPのデバッグ方法

https://techplay.jp/column/571
https://took.jp/post-421/
https://teratail.com/questions/196359
https://arrown-blog.com/php-vardump/
https://codeclub965.com/?p=1878
https://office-obata.com/report/memorandum/post-4494/

参考サイト

https://paiza.io/ja/projects/new

https://www.sejuku.net/blog/21685

https://webukatu.com/wordpress/blog/25212/

https://se-tomo.com/2018/12/08/【php】html内でのif文の書き方【endif】/

https://beyondjapan.com/blog/2020/02/intelephense-vscode-php/

https://wp-p.info/tpl_rep.php?cat=php-biginner&fl=r28

https://udemy.benesse.co.jp/development/system/php-while.html

https://www.javadrive.jp/php/for/index3.html

https://www.javadrive.jp/php/for/index4.html

https://www.javadrive.jp/php/for/index5.html

https://tektektech.com/doll-at-mean/

https://techplay.jp/column/491

https://itrice580.com/2019/10/18/php-5/
https://acceliv.com/2021/01/php-parse-error-syntax-error-unexpected
https://www.javadrive.jp/phpfunc/var/index4.html
https://1-notes.com/php-is-set/
https://lighthouse-dev.hatenablog.com/entry/2018/01/25/013729

https://medium-company.com/php-break-continue/
https://ja.wikipedia.org/wiki/ASCII

https://develop.hateblo.jp/entry/php-datetime-string

Discussion