教材

PHP

PHPとは

PHPとは、動的にWebページを生成するプログラミング言語です。
「動的なWebページ」とは、アクセスしたタイミングや状況によって表示内容が変わるページのことです。
「静的なWebページ」とは、時間や誰がアクセスしたかによらず同じように表示されるページのことです。
例えば、Q&Aサイトでは質問に対しての回答が増える度に表示される内容が変わりますよね。これが「動的なWebページ」の例です。

前準備①

ここでは「Google Chrome」というブラウザを使用して学習を進めていきます。
無料でダウンロード・インストールできますので、持っていない方はダウンロード・インストールしたてください。

以下リンクに手順が記載されています
https://support.google.com/chrome/answer/95346?co=GENIE.Platform%3DDesktop&hl=ja

前準備②

以下よりご自身のOSに対応するツールを無料ダウンロード、インストールしましょう。

Macの方は「MAMP」をインストール
https://www.mamp.info/en/mac/

・「MAMP」インストールの参考サイト
https://techacademy.jp/magazine/5102#sec2

Windowsの方は「XAMPP」をインストール
https://www.apachefriends.org/jp/index.html

・「XAMPP」インストールの参考サイト
https://techacademy.jp/magazine/1722
https://itsakura.com/php-xampp
https://www.adminweb.jp/xampp/install/index1.html

初期設定が完了したら、
Apache、MySQL を起動してください。

MAMPの起動方法
①MAMPを開く。
②Start Serverボタン押す。

XAMPPの起動方法
①XAMPPのコントロールパネルを開く。
②Apache、MySQLの横のSTARTボタンをそれぞれ押す。

画面に表示してみよう

まずは以下の手順でindex.phpフォルダを作成してください。

①MAMP(もしくはXAMPP)のフォルダの中から
 「htdocs」という名前のフォルダを見つけ開く。
② htdocsフォルダの中に「test」というフォルダを新たに作成する。
③ testフォルダの中に「index.php」という名前のファイルを作成する

参考

index.phpは作成できましたか?

作成できたら、次にindex.phpをエディタで開き、以下のコードを記入もしくはコピペして保存しください。

<?php
  echo "はじめてのPHP";
?>

そして、ブラウザを開き、URL入力欄に
http://localhost/test
と入力してください。

以下のように表示されれば、成功です。

※うまくいかなかったとき
以下を確認してください
・Apache、MySQLは正常に起動しているか。
・フォルダ名、ファイル名は間違っていないか。
・コードは間違っていないか。(例:半角文字、半角スペースのはずが全角になっている等)

PHPの書き方とechoについて

ここからはPHPの書き方の説明をしていきます。
まずHTMLと違ってPHPは書いたコードが必ず画面に出てくるわけではありません。
そこで、まず文字や数字を画面に出力するための方法から学んでいきましょう。

PHPは「 <?php(開始タグ)」 ではじまり、 「?>(終了タグ)」 で閉じます。開始タグと終了タグの中にPHPのコード(プログラム、命令文)を書きます。

先ほどのコードをもう一度見てください。
参考例

<?php
  echo "はじめてのPHP";
?>

開始タグと終了タグの中には

echo “はじめてのPHP”; 

と書かれています。
echo とは 文字を出力するための言語構造です。
この例では「はじめてのPHP」という文字列を画面する役割を担っています。

そして、PHPでは処理の行末にセミコロンをつけます。
命令文の区切りを判定するためです。

index.phpについて

先ほどtestフォルダの中にindex.phpを作成し、
URLでhttp://localhost/testを入力したとき

index.phpの中に書いてある

<?php
  echo "はじめてのPHP";
?>

を読み込んで、「はじめてのPHP」を出力しました。

では、testフォルダの中に新たにabc.phpを作成しましょう。

そして
abc.phpの中に以下のコードを記入してください。

<?php
  echo "abc.phpから出力";
?>

ブラウザからURLでhttp://localhost/test/abc.phpを入力して開いてください

abc.phpから出力

と出力されたと思います。

では次に
http://localhost/test/index.php
と入力して開いてください

はじめてのPHP

が出力されましたね。

では最後に
http://localhost/test
でもう一度入力して開いてください

「はじめてのPHP」から変わらないと思います。

これはどういうことかというと

http://localhost/test/で
MAMP(もしくはXAMPP)内のhtdocsフォルダ の中の test というフォルダを参照しています。

フォルダを参照した時にindexという名前はデフォルトドキュメントという意味を持ち、
省略してもブラウザで表示されます。

そのためファイル名を指定しない場合は自動的にindex.phpが参照されます。

つまり
http://localhost/test/

http://localhost/test/index.php
も同じファイルを参照しています。

var_dump

var_dumpは変数の情報を表示する関数です。

変数の値、型、バイト数などの詳細な情報を表示することができます。配列の中身も見ることができます。

PHPでは、エラーが発生した場合、原因を特定するために(デバッグといいます)このvar_dump関数を用いてよく変数の中身を確認します。

以下のように()の中に変数を入れて使います。
var_dump(変数);

後に説明する変数と一緒に使いながら学んでいきましょう。

変数

それではプログラムの基本となる「変数」について教えていきたいと思います。

PHPにおける「変数」とは「箱」のようなものです。
使い方。

基本的な記述は、下記のように変数名と値を同時に設定します。

$変数名 = 値;
です。

補足ですがPHPでは行末に「;(セミコロン)」を入れます。
セミコロンを省略すると、プログラムが機能しなくなります。

コードを書いてみてみましょう!
参考例

<?php

  $box = 5;

  var_dump($box);

?>

ブラウザを更新してみてください。

「 5 」 が入っていますよね?

順を追って説明して行きます。

まず基本的にPHPのコードは上から順に実行されていきます。

$box = 5;

これは「box」という変数の中に数字の「5」を入れています。
ここで使われる「=」は「等しい」という意味ではなく、
あくまで代入として使われます。

そしてvar_dumpで$boxを表示したときに、
箱の中の値が出力された。

ということになります。

変数の名前は任意です。ただし以下の点に注意しましょう。
・名前には半角英数字とアンダースコア「_」のみ使用するようにしてください。
・先頭に数字を使うのは避けてください。
・先頭に大文字を使うのは避けてください。
・予約語を使わないでください。

インデントとは

インデントとは、コードの行頭に空白を挿入して先頭の文字を右に押しやることです。
インデントをすることでプログラムの動きにかかわったりはしませんが、
わかりやすいコードを書くというのは重要で、
システム開発の現場では様々な人が同じソースコードに触ります。
その際、あなたが書いたソースコードも別の人が触って追記や修正をします。
そのため視覚的にわかりやすいコードを書くことが作業の効率化につながります。

注意
環境にもよりますが、
ここでは基本的にインデントは半角スペースを使いましょう。

本教材ではインデントを半角スペース2つでやっています。

ソースとは

プログラミングの世界ではよく「(情報などの)出どころ、源」の意味として使われます。
プログラミングコードのことを「ソース」もしくは「ソースコード」とも言います。

先ほどの

<?php

  $box = 5;

  var_dump($box);

?>

もソースコードです。

コメント

「コメント」について

「コメント」はプログラムとして実行されないので、
書いたコードの説明、メモに使えます。

書き方

スラッシュを2回続けて、その後にコメント文を書きます。

参考例

<?php
  // これで一行コメントをかけます。
?>

複数行コメントの書き方

参考例

<?php
  /*
    コメント
    コメント
    コメント
  */
?>

/* 〜 */で囲むことで囲った部分がコメントになります

データ型

データ型とは、その名の通り
「データ」の「型(かた、type)」のことです。

PHPで扱うデータにはそれぞれ種類があります。
例えば整数、文字列、配列、論理値、オブジェクトなどです。

初めて聞く言葉ばかりだとは思うので、
ここではまず「文字列」と「整数」を例にとって説明していきます。

文字列
PHPでは、文字列を”(ダブルクォート)または、’(シングルクォート)で囲んで表現します。
そのため変数の中に文字列を入れたい場合は以下の記述をします

$mycat = “たま”; //これはOK
$mycat = たま; //これはNG

整数
整数を入れたい場合はそのまま書いてOKです。
整数をクォートでくくってしまうと、文字列として扱われてしまうので注意してください。

$num = 1; //これはOK
$num = “1”; //これは文字列の1として扱われる

var_dumpで見るとわかりやすいと思います。
以下を記入して実行してみてください。

<?php
  var_dump(15);
  var_dump("15");
?>

15は「 int(15) 」と表示されて
“15”は「 string(2) “15” 」と表示されます。
(それぞれ整数型の15, 文字列型の15という意味です。stringのカッコ内の数値は文字列のバイト数を表しています。)

このように文字列と数値で処理の結果が変わってきてしまいますので注意しましょう。
特に変数に値を入れて使い回していると自分が扱っているデータの「型」を見失いがちです。
自分が扱っているデータの「型」は把握できるようにしていきましょう。

データ型はgettype関数でも確認することができるので、
わからなくなったら確認してみるとよいでしょう。

使い方は以下です。

<?php
  $box1 = 15;
  var_dump($box1);
  var_dump(gettype($box1)); //integer(整数)が表示される
?>

<?php
  $box2 = "15";
  var_dump($box2);
  var_dump(gettype($box2)); //string(文字列)が表示される
?>

表示は英語なので対応表を張っておきます

gettype関数 … 値のデータ型を表す文字列を返す。
整数 (integer)
文字列 (string)
論理値 (boolean)
オブジェクト (object)
配列 (array)
関数 (function)

ポイント
文章や文字を使いたいときは ”(ダブルクォート)か ’(シングルクォート)で囲む。
※教材では、”(ダブルクォート)で統一します。

関連課題

変数、データ型

配列

配列とは
配列を活用すると、複数の値をまるで1つのデータのように取り扱うことができるようになります。

例えば、変数は以下のように1つの値しか格納できませんよね?

$box = “太郎”;

$num = 5;
など。

しかし、10個や100個など多くの値を扱いたい場合に、
いちいち変数を1つずつ作るのは大変です

そのような時に、配列データを作成することで大量の値をまとめて1つのデータのように扱えるわけです。

配列の使い方

入れたいデータを [ ] の中に入れて、それぞれを,(カンマ)で区切って入れていきます。

では以下のコードを書いて出力してみましょう。

<?php
  $hairetu = ["太郎","花子",33,"あいうえお",24];

  var_dump( $hairetu );
?>

実行結果

array(5) { [0]=> string(6) “太郎” [1]=> string(6) “花子” [2]=> int(33) [3]=> string(15) “あいうえお” [4]=> int(24) }
が出力されたと思います。

配列に入れた値の取り出し方
以下のコードを書いてみてください

<?php
  $hairetu = ["太郎","花子",33,"あいうえお",24];
  
  var_dump( $hairetu[4] );
?>

何が起きたかというと、
宣言した配列の変数名の後に[4]を入れることによって

その配列の「4」番目に入っているデータを取得できます。

ん?でも

[“太郎”,”花子”,33,”あいうえお”,24];

24は左から数えても5番目じゃない?と思ったと思います。

実は配列の数え方にはルールがあって、それは
「0から数える」というものです。

例でいうと
「太郎」が0番目
「花子」が1番目
「 33 」が2番目
「あいうえお」が3番目
「 24 」が4番目
となります。

そのため

<?php
  $hairetu = ["太郎","花子",33,"あいうえお",24];
  
  var_dump( $hairetu[0] ); //太郎が出力
  var_dump( $hairetu[1] ); //花子が出力
  var_dump( $hairetu[2] ); //33が出力
  var_dump( $hairetu[3] ); //あいうえおが出力
  var_dump( $hairetu[4] ); //24が出力
?>

となります。

関連課題

配列と変数

連想配列

配列とは、一つの変数に複数のデータを入れておくものでした。

連想配列とは、配列を使いやすくしたものです。

配列は、先頭から順に番号を振ることで中身のデータを区別していましたが、連想配列では番号でなく名前をつけて区別することができます。

実際にコードを書くと以下のようになります。
$hairetu = [“苗字”=>”山田”,”名前”=>”花子”,”出席番号”=>33,];

上のコードの”苗字”や”名前”のことをキー、”山田”や”花子”のことを値やvalueといいます。

以下のコードを書いてみましょう。

<?php
  $hairetu = ["苗字"=>"山田","名前"=>"花子","出席番号"=>33,];

  var_dump( $hairetu["苗字"] );
?>

“山田”が出力されたと思います。

“苗字”の部分を”名前”や”出席番号”に変えて試してみてください。”花子”、33がそれぞれ出力されることが確認できると思います。

演算子

演算子について説明していきます。

「 + (足す)」、
「 – (引く)」、
「 * (かける)」、
「 / (割る)」
そして
「 %(割り算のあまりを出せる)」
ものがあります。

この5種類を「算術演算子」と言います。

参考例

<?php
  //数値の計算 演算子の両側には半角スペースを入れてください。
  var_dump(5 + 1 + 2);
  var_dump(5 - 1);
  var_dump(5 * 1);
  var_dump(6 / 3);
  var_dump(16 % 7);  //16を7で割ったときの余り
  var_dump(6 / 3 * 4 + 5 - 7); //もちろん一度に複数個使えます
?>

補足ですが掛け算と割り算の方が優先的に実行されるルールがありますので、
足し算引き算を先に計算したい場合は()で括ります

<?php
  var_dump((5 + 1) * 2);  //12が出力されます
  var_dump(5 + 1 * 2);  //7が出力されます
?>

補足
「 %(割り算のあまりを出せる)」を使うことで倍数の判断ができます。
割り切れる数というのは言い換えると「余りが0」ということです。

15 ÷  3 = 5余り0
つまり15は3の倍数ということです。

<?php
  var_dump(15 % 3)//0が出力される。
?>

また数値等を比較する演算子もあります。
「比較演算子」と言います
a > b ・・・a が b より大きい
a >= b ・・・a が b 以上
a < b・・・ a が b より小さい
a <= b・・・ a がb 以下
a == b ・・・a と bが等しい(データ型は見ない)
a === b ・・・a と bが等しい(データ型も見る)※事項で説明

真偽値

真偽値(しんぎち)について。真偽値はBoolean(ブーリアン)や論理値(ろんりち)と呼ばれます。PHP含めプログラミングではとてもよく使います。
後に説明するif文などでよく使いますが、今はどういった使い方をするのかイメージしづらいと思うので、どんなものか。というのを覚えていただければよいです。

一言でいうと「真(true)が偽(false)」か。というものになります。

真とは「正しい、正規の」という意味でよく使われますよね、
それの反対として
偽とは「正しくない、偽物」として使われます。このイメージでオッケーです。

比較の演算子をvar_dumpで出力した時などに出てきます。
a > b ・・・a が b より大きい
この演算子を参考にしてみましょう
以下の処理を実行してみてください

<?php
  var_dump(5 > 3);  //5は3より大きい
?>

trueと出ていますね?
上記の比較の結果は「正しい」という意味です。
では、あえて間違った比較結果を入れてみましょう。

<?php
  var_dump(5 > 99999);  //5は99999より大きい
?>

falseと出ましたね。「正しくない」という意味です。

では以下の比較結果を予想してみましょう。

<?php
  var_dump(99999 > 5 );
  var_dump(99999 < 5);
  var_dump(5 == 5);
  var_dump(5 === "5");
  var_dump("5" === "5");
  var_dump(15 % 5 === 0);
?>

正解は

<?php
  var_dump(99999 > 5 );  //true
  var_dump(99999 < 5);  //false
  var_dump(5 == 5);  //true データ型は問わない
  var_dump(5 === "5"); //false 数値の「5」と文字列の「5」
  var_dump("5" === "5");  //true 文字列の「5」と文字列の「5」
  var_dump(15 % 5 === 0);  //true この式は倍数の判断によく使われる。
?>

です。

関連課題

演算子と真偽値

文字列結合

文字列を結合する方法は、いくつか方法があります。

  1. .」(連結演算子)を使った方法
  2. “”を使った方法
  3. {}を使った方法
  4. sprintf()を使った方法

では、順番にどのように使うのかをお伝えしていきます。

1.「.」(連結演算子)を使った方法

<?php
  // .を使うことで文字列の連結もできます
  var_dump("僕は" . "太郎" . "です");

  // 文字列と数値を連結できます。連結後は、数値も文字列扱いになります。
  var_dump("太郎は" . 15 . "才です");

  // この記法は、変数を交えて書く時に便利です。
  $name = "太郎";
  $age = 8;
  $str1 = $name . "は" . 15 . "才です";
  $str2 = $name . "は" . $age . "才です";
  var_dump($str1);
  var_dump($str2);
?>

上記の場合半角スペースを入れなくても動きますが、 他の演算子と同じように両脇に半角スペースを入れて使うと見やすくてよいでしょう。

また、共に数値の連結にはスペースを特に気をつけましょう!

<?php
  var_dump(12 . 25); // 文字列 1225(いち に に ご)
  var_dump(12.25);   // 浮動小数点数 12.25(じゅうに てん に ご)
?>

その他の連結方法で、結合代入演算子があります。

<?php
  $box = "Hello ";
  $box .= "World!";  // $box は、"Hello "に "World!"が結合された状態になります。

  var_dump($box);    // "Hello World!" が表示される。
?>

2.”” を使った方法

<?php
  $name = "太郎";
  $age = 8;
  $str1 = "$name は15才です";
  $str2 = "$name は $age 才です";
  var_dump($str1);
  var_dump($str2);
?>

※注意※
変数の後ろには、半角スペースが必要になります。

3.{} を使った方法

<?php
  $name = "太郎";
  $age = 8;
  $str1 = "{$name}は15才です";
  $str2 = "{$name}は{$age}才です";
  var_dump($str1);
  var_dump($str2);
?>

※注意※
{} を使う場合、 “” も記述する必要があります。

4.sprintf()を使った方法

<?php
  $name = "太郎";
  $age = 8;
  $str1 = sprintf("%sは15才です", $name);
  $str2 = sprintf("%sは%d才です", $name, $age);
  var_dump($str1);
  var_dump($str2);
?>

sprintf関数は、第一引数に生成する文字列のフォーマットを指定し、
第二引数以降で生成する文字列や値を指定します。

上記のコードに書かれている「%s」や「%d」は、「型指定子」と呼ばれるものです。

%s・・・引数を文字列として扱い、表現します。
%d・・・引数を整数として扱い、10進数として表現します。

他にも、型指定子はありますので、「型指定子 一覧」などで検索してみましょう!

if文

「if」を翻訳すると「もしも」になります。
PHPでも同じ意味で、

もしも変数の中身が1だったら、処理Aを実行する
もしも変数の中身が2だったら、処理Bを実行する

というように、値や状況に応じて処理を分岐させることができます
構文は以下の通りです。

if( 条件式 ) {
  //trueの場合の処理を書く
}

条件式の場所に値を入れ、それがtrueの時に中の処理が実行されます

if文には他にも
else if、
elseという仲間が存在します。

else if・・・別の条件分岐を作成する
elseは、if文の最後に書かれます。
ifやelse ifで指定した条件以外の時の分岐先です。

if( 条件式 ) {
  //trueの場合の処理を書く
} else if( 条件式 ) {
  //ifの条件式がfalseでelse ifの条件式がtrueの場合の処理を書く
}

else ifは最初のif文に当てはまらない時の処理なので、
必ずifのあとに書かれるという点に注意しておきましょう。

if( 条件式 ) {
  //trueの場合の処理を書く
} else if( 条件式 ) {
  //ifの条件式がfalseでelse ifの条件式がtrueの場合の処理を書く
} else if( 条件式 ) {
  //else ifは複数書けます。
} else {
  //if、else ifの条件式にいずれも当てはまらない場合の処理を書く
}

参考例

<?php 
  $box =15;

  if ($box < 5) {
    var_dump("boxは5より小さい");
  }else if($box < 20){
    var_dump("boxは20より小さい");
  }else if($box < 30){
    var_dump("boxは30より小さい");
  }else {
    var_dump("それ以外");
  }
?>

出力結果
「boxは20より小さい」 が表示されます。
上から処理が流れていってbox < 20の条件がtrueになったからです。
ちなみにbox < 30もtrueになるはずですが
if文では上の処理が実行されるとそれ以降の処理は実行されないのです。

したがって
var_dump(“boxは20より小さい”); のみが実行されたことになります。

また条件分岐の基準になる真偽値(Boolean)ですが、
1と1.0はtrue、0と0.0はfalse、
空文字””と空配列はfalseなど、
間違えやすいものもあるので気を付けましょう。

関連課題

if文

スキルチェック課題: if文

論理演算子

特殊な演算子をご紹介いたします。
先ほどif文でtrueとfalseについての条件分岐をやったと思いますが、
条件分岐に役立つ演算子が3つあるのでご紹介します。

&& AND
これは && を挟んでいる両方がtrueの時に true を返します。

参考例

<?php 
  var_dump(true && true);     //trueを返す
  var_dump(true && false);    //falseを返す
  var_dump(false && false);   //falseを返す
?>

|| OR
これは || を挟んでいるどちらか片方がtrue の時に true を返します。

参考例

<?php 
  var_dump(true || true);     //trueを返す
  var_dump(true || false);    //trueを返す
  var_dump(false || false);   //falseを返す
?>

! NOT
これはtrue,falseを逆の意味で返します。

参考例

<?php 
  var_dump(!true);     //falseを返す
  var_dump(!false);    //trueを返す
  var_dump(5 != 5);   //falseを返す
?>

switch文

switch文も条件分岐ができます。
構文は以下の通りです。

switch( 式 ) {
    case 値:
        // 処理
        break;
 
    case 値:
        // 処理
        break;
    
 default:
        // 処理
        break;
}
 

まず最初に式をチェックし、次に値を見ていき、「式」と「値」が一致する「case」を発見したらその処理を実行した後、「switch文」を抜けます。
ただし、break;を書き忘れると、次のcase処理を続けて実行してしまうので注意してください。

<?php 
  $money = "福沢";

  switch( $money ) {
    case "野口":
        var_dump("小");
        break;

    case "樋口":
        var_dump("中");
        break;

    case "福沢":
        var_dump("大");
        break;
    
    default :
      var_dump("該当なし");
      break;
  }
?>

for文

Webページではある数値や数式、文字列を繰り返し用いるシーンは数多く見られます。
PHPでループ(繰り返し)処理をおこなうときは、用途に応じて
for文と while文 という2種類を使い分けます。

一般的には
繰り返す回数が決まっている場合は for文
繰り返す回数が決まっていない場合は while文
を使います。

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

条件式がtrueの場合は処理を繰り返します。

参考例

<?php 
  for ($i = 0; $i < 5; $i++) {
    var_dump($i);
  }
?>

画面を見ると「$i」の値が1上がっているのがわかると思います。

$i = 0;
 「$i」という変数を定義して、0を代入しています。
条件式 $i < 5;
  $i < 5がtrueの場合に処理を繰り返すことを意味しています。
増減式 $i++
 処理を繰り返すたびに $i に1を足していくことを意味しています。
 ($i++は1ずつ足していく、$i–は1ずつ減らしていく、という意味)

つまり
4
が出力された後は「$i」の値が 5になる。
その場合条件式が 5 < 5になり、falseが返るため、繰り返し処理をしない。

ということになります。

while文、do while文

while 文

while (条件式){
  //処理
}

条件式がtrueの場合処理を実行します。

つまり以下のようなコードを実行すると、無限に処理を繰り返してしまいます。

while (true){
  var_dump("無限");
}

繰り返し処理が終わるような仕組みを書いておかなければなりません。

参考例

<?php 
  $count = 5;

  while ($count > 0){
    var_dump($count);
    $count--;
  }
?>

do…while 文

do…while 文は指定された条件が false になるまで繰り返します。

do…while 文は以下のような形です

do {
  //文
}while (条件式);

文は条件式がチェックされる前に毎回一度実行されます。

do while文の特徴は、処理の後に条件式が記述されているので、
条件にかかわらず最初の一回はまず処理が実行されるというところです。

foreach文

foreachは配列の時に使えるループ処理で、配列の中に入っている要素の数分、繰り返し処理をしてくれます。

2種類あります。

一次元配列の書き方

foreach ($array as $value){
 //処理
}

連想配列の書き方

foreach ($array as $key => $value){
 //処理
}

$arrayは配列 ,
$valueは$arrayに入っている要素,
$keyは配列の番号を意味します。

参考例

<?php
  $box = ["いちご", "りんご", "メロン", "オレンジ"];
  
  foreach ($box as $nakami){
    var_dump($nakami);
  }
?>

関連課題

繰り返し処理

繰り返し処理2


ここで一旦以下課題に取り組んでください。

PHPスキルチェック課題: for文

スキルチェック課題: for文

PHPスキルチェック課題: if文とfor文

スキルチェック課題: if文とfor文

関数

ブラックボックスというものをご存じでしょうか。
例えばこんなような。

上記の場合だと入ってきた値を倍にして出していますね。

関数とは、このブラックボックスのような働きをするものです。
また、関数の中の処理は自分で作ることができます。
さらに、PHPで最初から用意されている関数もあります。

変数のように、呼び出せば何度も使えるように名前を付けておくのが一般的です。

var_dump();も関数のひとつです

まずはブラックボックスのような関数を作る前に、
書き方を順を追って説明します。

書き方
関数宣言
まず関数の宣言としてfunction と書きます。
その次に関数名を付けます。

<?php


  function sample() {
 
    //ここに処理を書いていく
 
  }


?>

この例では、「sample」という関数名を付けて関数宣言を行なっています。

関数は宣言したあとに呼び出すことで、はじめて利用することができます。ここでは「呼び出し」という表現を使っていますが、
簡単に言えば、作成した関数を実行するという意味です。

呼び出しかた
まずは以下のコードを書いてください
return ○○;は「戻り値」といって関数を呼び出した際に
返却される値になります。
return ○○;で指定した「○○」は上のブラックボックス図でいうと「出」にあたります。

<?php

  function sample() {
    return "初めての関数";
  }

?>

これだけでは関数を宣言しただけなので実行はされません。

作成した関数を実行するためには「呼び出し」を行います。
以下のように書きます。
呼び出したい関数名();

では、作成した関数をvar_dumpのなかで
「呼び出し」 しましょう。

<?php

  function sample() {
    return "初めての関数";
  }

  var_dump(sample());

?>

うまく表示されましたでしょうか。

補足
・return の値は無しでもOK
・関数内でreturnが実行されると、そこで関数の処理が終了します。
・関数を作成した際、必ずしもreturnを書く必要はないです。

<?php

  function sample() {
    var_dump(1); //実行される
    var_dump(2); //実行される
    var_dump(3); //実行される
    return;  //強制終了
    var_dump(4); //実行されない
    var_dump(5); //実行されない
    var_dump(6); //実行されない
  }

  sample();

?>

関連課題

関数

引数

関数名の後の()の中に値を入れることができます。
この値を「引数」といいます。

実際のコードを見てもらうとわかりやすいです。

function sample( $num ) {
   
}

ここに入れた変数を、中の処理で使うことができます。

<?php
  function sample( $box ) {
    var_dump($box);
  }
?>

そして、呼び出す際に引数に値を入れます。

<?php
  function sample( $box ) {
    var_dump($box);
  }
  
  sample(3);
?>

そうすると、呼び出す際に入れた値が関数内の処理で使えるようになります。

「 3 」が出力されるはずです。

これが引数です。

ブラックボックスの図で見てみましょう。

そして、
この「入」にあたるのが「引数」です。

コードを見ていきましょう
例えば上の図を関数に表すとこんな感じです。

<?php
  function sample( $box ) {
    return "引数は「" . $box . "」です!";
  }
  
  var_dump(sample(3));
  var_dump(sample("あああ"));
?>

また、引数は複数個指定することもできます。

<?php
  function sample( $val1, $val2 ) {
    return "第一引数は「" . $val1 . "」で、第二引数は「" . $val2 . "」です!";
  }
  
  var_dump(sample( 3, 777));
  var_dump(sample("あああ", "おいう"));
?>

関連課題

引数


ここで一旦以下課題に取り組んでください。

PHPスキルチェック課題: 関数、引数、戻り値

スキルチェック課題: 関数、引数、戻り値

関数の理解を深めよう

関数の理解を深めよう①

関数の理解を深めよう②


ここまで学習した内容を踏まえて、以下の課題に取り組んでください。

PHP応用課題

PHP応用課題①

PHP応用課題②

グローバル変数とローカル変数

関数に関する注意点。関数の内側で宣言された変数は、
その関数の外側からはアクセスできません。

このように、変数には使える有効範囲が限られており、
この範囲のことを「スコープ」と言います。

PHPでは、関数の外側で宣言した変数は「グローバル変数」
として扱われます。
一方、関数の内側で宣言された変数は「ローカル変数」として扱われ、宣言された関数内からのみアクセスできます。

以下のコードをご覧ください

<?php
  $box = "最初に定義したBOX";

  var_dump($box);
?>

これを実行すると「最初に定義したBOX」が出力されますね?

では、以下を実行してみてください。

<?php
  function test(){
    $box = "test関数内で定義したBOX";//ローカル変数
  }
  test();
  var_dump($box);
?>

実行結果
NULLになります。
上記例のtest関数のなかで定義した変数は、test関数の中でしか使えないからなんです。

では次にグローバル関数をtesu関数の中(ローカルスコープ)で呼び出してみましょう。

<?php
  $box = "グローバルで定義したBOX"; //グローバル変数

  function test(){
    var_dump($box);
  }

  test();
?>

実行結果
これもNULLになります。

PHP では、グローバル変数を、関数の内部で使用する場合、関数の内部でグローバルとして宣言する必要があるからです。

global  と記述し宣言することでグローバルで定義した$boxを参照できます。

<?php
  $box = "グローバルで定義したBOX"; //グローバル変数

  function test(){
    global $box; //グローバルを宣言
    var_dump($box);
  }

  test();
?>

実行結果
グローバルで定義したBOX が出力されます。

スーパーグローバル

説明:
PHPではすべてのスコープで使用できる組み込みの変数が存在します。
それはスーパーグローバルと呼ばれていて、
以下のようなものがあります。

後々登場しますのでここでは一覧だけ載せておきます。

  • $GLOBALS
  • $_SERVER
  • $_GET
  • $_POST
  • $_FILES
  • $_COOKIE
  • $_SESSION
  • $_REQUEST
  • $_ENV

三項演算子について

三項演算子を使うことで、if文の条件式を省略して書くことができます。

書き方

条件式 ? Trueの処理 : Falseの処理

参考例

<?php 
  var_dump( 5 > 0 ? "aaa" : "bbb");  //5 > 0 はtrueなので"aaa"が出力されます。
?>

class構文

class構文を使うことによって、変数や関数をひとまとめにして使い回すことができます。

書き方

class クラス名 {
 
  //プロパティやメソッドを定義する
 
}

class文の中に各変数や関数を定義していくことになります。
ちなみに、class文の中に定義している変数はプロパティ、関数はメソッドと呼びます。
プロパティもメソッドも頻出の単語なのでしっかりと覚えておきましょう!

classの使い方は主に以下の流れです。

  1. classの中にプロパティやメソッドを定義する
  2. classをインスタンス化する
  3. プロパティやメソッドを呼び出す

では、実際の使い方を見ていきましょう。

参考例

<?php
  class TestClass {
    public function testFunc(){     // 1.classの中にメソッドを定義する
      echo "初めてのclass構文";
    }
  }
  $test_class = new TestClass();    // 2.classをインスタンス化する
  $test_class->testFunc();        // 3.メソッドを呼び出す
?>

ここでは、TestClassというclassにtestFunc()というメソッドを定義しています。
※メソッドの前についている「public」については次項「アクセス修飾子」で解説します。

その後、new TestClassでclassをインスタンス化し、$test_classという変数に代入します。
この処理を行うことで$test_classという変数にTestClassが格納されます。

最後に$test_class->testFunc();のように記述することでTestClassの中で定義されたメソッドを呼び出すことができ、「初めてのclass構文」と画面に表示されます。

「->」はそのクラスのプロパティやメソッドを呼び出す際に使用します。

インスタンス化とは…

インスタンス化とは、classの中に定義されているプロパティやメソッドを操作できる状態にすることです。

「操作できる状態にする」と言っても具体的にイメージすることは難しいと思うので、身の回りのもので考えてみましょう。

例えばスマートフォンを例として考えてみます。
スマートフォンを作るためにはまず、どんな機能を持ったスマートフォンにするのかを書いた設計書を作ります。
そして設計書を元にその機能を持った、スマートフォンの実物を作成します。
実物ができたらようやくスマートフォンの機能を使用することができるようになりますね。

この設計書がclassの中にプロパティやメソッド定義した状態です。
定義しただけでは、設計書を作っただけなのでプロパティやメソッドを操作することはできません。
そして実物を作成することがインスタンス化です。
classのインスタンス(実態)を作成することでようやくclassの中のプロパティやメソッドを操作することができるようになります。

$this

$thisとはクラスのメソッドからそのクラスが持っているプロパティやメソッドを呼び出す際に使用することができます。

参考例

<?php
  class TestClass {
    public $name = "山田";

    public function testFunc(){
      echo $this->name;
    }
  }
  $test_class = new TestClass();
  $test_class->testFunc();
?>

※プロパティとメソッドの前についている「public」については次項「アクセス修飾子」で解説します。

こちらではメソッドtestFunc()の中で、$this->nameと記述することでそのクラスの持つ$nameというプロパティを呼び出すことができます。
$test_class->testFunc();でメソッドを呼び出した結果「山田」と画面に出力することができます。

このように「$this->プロパティ名またはメソッド名;」と記述することでクラスのメソッドから、そのクラスにあるプロパティやメソッドを呼び出すことができます。

__construct

__construct(コンストラクタ)とはクラスがインスタンス化される際に自動で実行されるメソッドのことです。

書き方

class クラス名 {

  public function __construct(){

  //  ここに処理を書く

  }

}

※メソッドの前についている「public」については次項「アクセス修飾子」で解説します。

コンストラクタは「__construct」のようにconstructの前にアンダーバーを2つ記述します。
メソッドの中にはクラスをインスタンス化した際に実行したい処理を記述していくことになります。

参考例

<?php
  class TestClass {
    public $name;

    public function __construct(){
      $this->name = "山田";
    }

    public function testFunc(){
      echo $this->name;
    }
  }
  $test_class = new TestClass();
  $test_class->testFunc();
?>

※プロパティとメソッドの前についている「public」については次項「アクセス修飾子」で解説します。

こちらの参考例では、new TestClassでクラスのインスタンスを生成した際にコンストラクタのメソッドが実行され、クラスが持つプロパティ$nameに「山田」が代入されます。
そして、この$nameに「山田」が代入された状態のインスタンスが$test_classに代入されます。

その結果、$test_class->testFunc();でメソッドtestFunc()を呼び出した際に、
TestClassの持つプロパティ$nameに代入されている「山田」が画面に出力されるようになります。

継承

継承とは、クラスが持っているプロパティやメソッドを別のクラスに引き継がせることです。

継承されるクラスを親クラス、継承するクラスを子クラスと言います。

書き方

class 親クラス名 {

  //プロパティやメソッドを定義する

}

class 子クラス名 extends 親クラス名 {

  //プロパティやメソッドを定義する

}

子クラスのクラス名の後にextendsと親クラスのクラス名をつけることで継承することができます。

参考例

<?php
  class ParentClass {
    public function parentFunc(){
      echo "親クラスのメソッド";
    }
  }
  class ChildClass extends ParentClass {
    public function childFunc(){
      $this->parentFunc();
    }
  }

  $child_class = new ChildClass();
  $child_class->parentFunc();        //  1
  $child_class->childFunc();         //  2

?>

※メソッドの前についている「public」については次項「アクセス修飾子」で解説します。

  1. $child_class->parentFunc();では
    1. 子クラス(ChildClass)のインスタンスから親クラス(ParentClass)の持つメソッド(parentFunc)を実行
    2. 実行結果「親クラスのメソッド」が画面に出力される
  2. $child_class->childFunc();では
    1. 子クラス(ChildClass)のインスタンスから子クラスのメソッド(childFunc)を実行
    2. 子クラスのメソッド(childFunc)から親クラスのメソッド(parentFunc)を実行
    3. 実行結果「親クラスのメソッド」が画面に出力される

このように継承することで、親クラスが持っているプロパティやメソッドを子クラスから呼び出すことができるようになります。

継承は、機能が重複したclassを共通化して、コードの無駄を省くために使用します。
複数のクラスで同じ処理を行なっている場合に、親クラスに処理をまとめて記述することで、すっきりしたコードとなり、保守性や可読性が向上します。

アクセス修飾子

プロパティやメソッドを定義するときにアクセス修飾子というものを指定することができます。
アクセス修飾子を指定することで、class外部から使う必要がないclass内部のプロパティやメソッドを隠し、より安全性の高いプログラムとすることができます。

アクセス修飾子は3種類あり、それぞれの意味は次のようなものです。

  • public
    class内部からもclass外部からもアクセス可能。
    アクセス修飾子がない場合は、publicを指定したものと同じになります。
  • private
    class内部からのみアクセス可能。
  • protected
    class内部からと子classからアクセス可能。

書き方

public プロパティ名;

private function メソッド名() {
  // 処理
}

このように、各プロパティ名とメソッド名の前にアクセス修飾子を記述していきます。

publicとprivateから使い方を見ていきましょう。

参考例

<?php
  class TestClass {
    public $public_box = "パブリック";
    private $private_box = "プライベート";

    // 1.class内部からアクセス修飾子「public」のプロパティを呼び出すメソッド
    public function testFuncA(){
      echo $this->public_box;
    }

    // 2.class内部からアクセス修飾子「private」のプロパティを呼び出すメソッド
    public function testFuncB(){
      echo $this->private_box;
    }
  }
  $test_class = new TestClass();

  // 1.class内部からアクセス修飾子「public」のプロパティを呼び出し
  $test_class->testFuncA();
  // 2.class内部からアクセス修飾子「private」のプロパティを呼び出し
  $test_class->testFuncB();

  // 3.class外部からアクセス修飾子「public」のプロパティを呼び出し
  echo $test_class->public_box;
  // 4.class外部からアクセス修飾子「private」のプロパティを呼び出し
  echo $test_class->private_box;
?>

こちらでは下記2つのプロパティを用意しました。

  • クラスの内部からも外部からもアクセスできるプロパティ$public_box
  • クラスの内部からのみアクセスできるプロパティ$private_box

それぞれクラス内部、外部から呼び出して確認してみましょう。

まずはクラス内部から呼び出した場合の実行結果です。

  1. class内部からアクセス修飾子「public」のプロパティを呼び出し
    実行結果:パブリックと画面に出力
  2. class内部からアクセス修飾子「private」のプロパティを呼び出し
    実行結果:プライベートと画面に出力

どちらもクラス内部からは問題なくアクセスできますね。

では、クラス外部から呼び出した場合の実行結果を見てみましょう。

  1. class外部からアクセス修飾子「public」のプロパティを呼び出し
    実行結果:パブリックと画面に出力
  2. class外部からアクセス修飾子「private」のプロパティを呼び出し
    実行結果:エラー

クラス外部から呼び出した場合、publicはアクセスできますが、privateはエラーとなります。

では次に継承クラスを準備してprotectedを見ていきましょう。

参考例

<?php
  class ParentClass {
    protected $protected_box = "プロテクティド";

    // 1.class内部からアクセス修飾子「protected」のプロパティを呼び出すメソッド
    public function parentFunc(){
      echo $this->protected_box;
    }
  }
  class ChildClass extends ParentClass {
    // 2.子classからアクセス修飾子「protected」のプロパティを呼び出すメソッド
    public function childFunc(){
      echo $this->protected_box;
    }
  }

  $child_class = new ChildClass();

  // 1.class内部からアクセス修飾子「protected」のプロパティを呼び出し
  $child_class->parentFunc();
  // 2.子classからアクセス修飾子「protected」のプロパティを呼び出し
  $child_class->childFunc();
  // 3.class外部からアクセス修飾子「protected」のプロパティを呼び出し
  echo $child_class->protected_box;

?>

こちらではアクセス修飾子protectedのプロパティを用意して、クラス内部、子クラス、クラス外部からそれぞれ呼び出してみます。

  1. class内部からアクセス修飾子「protected」のプロパティを呼び出し
    実行結果:プロテクティドと画面に出力
  2. 子classからアクセス修飾子「protected」のプロパティを呼び出し
    実行結果:プロテクティドと画面に出力
  3. class外部からアクセス修飾子「protected」のプロパティを呼び出し
    実行結果:エラー

class内部と子classからはアクセスできますが、class外部からはエラーとなりますね。

どのアクセス修飾子を使うべきか

アクセス修飾子を指定せず、すべてをpublicにしてもプログラムの動作に支障はありません。
ですが、プログラムの安全性を高めるためには、privateにできるものはprivateにしたほうが良いでしょう。
特にプロパティは、外部から変更されると困るというケースが多いです。

その為、クラス外部からアクセスする必要のないプロパティやメソッドは、privateに設定し、
そのクラスと子クラスからしかアクセスしないプロパティやメソッドは、protectedを設定しましょう。

活用例

classを活用する方法を「チャットツールにチャットを送信する機能」を例として紹介します。
※今回はクラスの活用方法を紹介するのが目的のため、実際の処理は割愛しています。

親クラスの処理:チャットに送信する文章を成形
子クラスの処理:各チャットツールのAPIを使用してチャットを送信
        送信内容を画面に表示

<?php

  // 親クラス
  class prepareContents {

    protected $contents;  // チャットに送信する文章を入れるプロパティ

    //コンストラクタ
    public function __construct($contents) {   // 1
      $this->set_content($contents);           // 2
    }

    // チャットに送信する文章を成形してプロパティに代入
    private function set_content($contents) {  // 2
      // $contentsの中身を成形する処理            // 3

      $this->contents = $contents;             // 4
    }
  }

  // 子クラス
  class sendSlack extends prepareContents {
    // APIを使ってチャットを送信
    public function send_slack($user_key,$send_to) {      // 6
      // slackのAPIを使ってチャットを送る処理                    // 7

      echo $user_key."を使って".$send_to."にスラックを送りました";  // 8
      echo "<br>";
      echo "送った内容は".$this->contents."です";
      echo "<br>";
    }
  }

  $send_result = new sendSlack("スラックに送る内容");       // 1
  $send_result->send_slack("user_key", "宛先のアドレス");   // 6
?>

親クラスにはprepareContentsクラス、子クラスにはsendSlackクラスを準備します。

処理の流れ
  1. new sendSlack(“スラックに送る内容”);
    1. sendSlackクラスのインスタンスを生成
    2. 親クラスのコンストラクタメソッドを呼び出し
    3. 引数$contentsに「スラックに送る内容」を渡す
  2. $this->set_content($contents);
    1. 親クラスのset_contentメソッドを呼び出し
    2. 引数$contentsに「スラックに送る内容」を渡す
  3. $contentsの中身を成形する処理
    • 実際の処理は割愛します
  4. $this->contents = $contents;
    1. $contentsを成形したものをクラスの持つプロパティ$contentsに代入
  5. $send_result = new sendSlack(“スラックに送る内容”);
    1. 4までの処理が行われた状態のインスタンスを$send_resultに代入
  6. $send_result->send_slack(“user_key”, “宛先のアドレス”);
    1. 子クラスのsend_slackメソッドを呼び出し
    2. 引数$user_keyに「user_key」、$send_toに「宛先のアドレス」を渡す
  7. slackのAPIを使ってチャットを送る処理
    • 実際の処理は割愛します
  8. 画面に出力
ポイント〜アクセス修飾子編〜
  • $contents
    親クラスと子クラスどちらからもアクセスしているのでprotectedを指定
  • set_contentメソッド
    親クラスのコンストラクタからのみアクセスしているのでprivateを指定
  • コンストラクタ・send_slackメソッド
    クラス外部からアクセスしているのでpublicを指定

このように、どこからアクセスするのかによってアクセス修飾子を使い分けましょう。

ポイント〜継承編〜

今回の例では、親クラスと子クラスを1つずつ用意しましたが、なぜクラスを分けて記述する必要があるのでしょうか?

1つのクラスで全ての処理を記述してしまっても処理は問題なく動きます。

継承は複数のクラスで同じような機能を実装したい時に役立ちます。

例えば、今回の例だとslackだけではなくChatworkにもチャットを送る機能を実装したい、という時です。

<?php

  class prepareContents {
    protected $contents;

    public function __construct($contents) {
      $this->set_content($contents);
    }

    private function set_content($contents) {
      // $contentsの中身を成形する処理

      $this->contents = $contents;
    }
  }

  class sendSlack extends prepareContents {
    public function send_slack($user_key,$send_to) {
      // slackのAPIを使ってチャットを送る処理

      echo $user_key."を使って".$send_to."にスラックを送りました";
      echo "<br>";
      echo "送った内容は".$this->contents."です";
      echo "<br>";
    }
  }

  class sendChatwork extends prepareContents {
    public function send_chatwork($user_key,$send_to) {
      // ChatworkのAPIを使ってチャットを送る処理

      echo $user_key."を使って".$send_to."にチャットワークを送りました";
      echo "<br>";
      echo "送った内容は".$this->contents."です";
      echo "<br>";
    }
  }

  $send_result = new sendSlack("スラックに送る内容");
  $send_result->send_slack("user_key", "宛先のアドレス");

  $send_result = new sendChatwork("チャットワークに送る内容");
  $send_result->send_chatwork("user_key", "宛先のアドレス");
?>

sendChatworkという子クラスを追加しました。

親クラスの$contentsの中身を成形する処理はどちらのチャットツールに送信するとしても、必要な機能です。

子クラスのAPIを使ってチャットを送る処理はどちらのチャットツールに送るのかを分けるために、それぞれのクラスを準備します。

このように、複数のクラスで同じような処理を行う場合に親クラスに処理をまとめることで、無駄なコードを省くことができます。

参考
https://rightcode.co.jp/blog/become-engineer/php-object-orientation

emptyとnullの違い

プログラミングには、emptyとnullという概念があります。emptyは「からっぽ」という意味で、nullは「存在しない」という意味です。

たとえば、以下の配列があったとします。

$hairetsu = [" ", "山田", " "];

$hairetsu[0]や$hairetsu[2]はemptyですが、$hairetsu[3]や$hairetsu[4]はnullになります。

以下のコードを書いて確かめてみましょう。

<?php 
  $hairetsu = [" ", "山田", " "];

  var_dump($hairetsu[0]); //empty
  var_dump($hairetsu[2]); //empty
  var_dump($hairetsu[3]); //null
  var_dump($hairetsu[4]); //null
?>

isset(), empty(), is_null関数

isset, empty, is_nullは判定する値によってtrueかfalseを返します。
判定したい情報によってそれぞれ使い分けます。
issetはその変数が存在するかを判定します。
emptyはその変数の中身が空かどうかを判定します。
is_nullはその変数の中身がnullかどうかを判定します。

以下対応表なので参考にしてみてください。

if($var)issetemptyis_null
$var=1truetruefalsefalse
$var=””;falsetruetruefalse
$var=”0″;falsetruetruefalse
$var=0;falsetruetruefalse
$var=NULL;falsefalsetruetrue
$varfalsefalsetruetrue
$var=array()falsetruetruefalse
$var=array(1)truetruefalsefalse

try catch文

try catch文を理解するためには、まず例外処理について理解する必要があります。

例外処理とは、あるプログラムがを動かしてエラーが起こった際に処理されるプログラムのことです。

それでは、実際のtry catch文を見ていきましょう。

<?php 
  try {
    var_dump(1 + 1);
  } catch ( Exception $e ) {
    var_dump("error");
  }
?>

上のコードは、1 + 1という処理をvar_dumpで出力するという一連の過程でエラーが出た場合、”error”という文字列を出力するという意味を表しています。

セッション

セッションとは、コンピュータのサーバー側に一時的にデータを保存する仕組みのことです。

Web上でのログイン情報,最終アクセスなど、
ユーザーに直接紐づくような大切なデータをセッションに格納して使ったりします。

PHPではこのセッションを使ってページを訪れたのが
同一ユーザーかどうか判断したり、
1回ログインしたら2回目からは自動でログインされる。
などの機能を実装できます。

使い方
$_SESSIONを使用します。
PHPのスーパーグローバル変数の1つであり、現在のセッションに登録されている値の変数です。
また、連想配列として使用します。
まず、session_start関数を使用してセッションをスタートします。
session_start();

session_start();は通常プログラムの最初に書きます

$_SESSIONの領域に好きな値を入れることができます

参考例

<?php
  session_start();
  $_SESSION["name"] = "abc";
  var_dump($_SESSION["name"]);
?>

削除にはunsetを使います

<?php
  session_start();
  $_SESSION["name"] = "abc";
  unset($_SESSION["name"] );
  var_dump($_SESSION["name"]);
?>

ページの訪問回数を表示する処理は
以下のように書けます。
参考例

<?php
  // セッション管理開始
  session_start();
  
  if (!isset($_SESSION["count"])) {
      // キー"count"が登録されていなければ、1を設定
      $_SESSION["count"] = 1;
  } else {
      //  キー"count"が登録されていれば、その値をインクリメント
      $_SESSION["count"]++;
  }
  
  echo $_SESSION["count"]."回目の訪問です。";
?>

セッションの参考
https://wepicks.net/phpref-session/
http://skillcamp.tech/blog/?p=462

正規表現

正規表現とは、文字列の照合をするために用いられるパターンです。
機能でいうとユーザー情報入力画面などで、メールアドレスが確認用と一致しているか、
半角英数字のみ記入の欄に全角文字を使っていないかなどを
判断するときによく用いられます。

正規表現によって意図しない値を入力させないことを「バリデーション」と言います。

使い方
主にpreg_match()メソッド、preg_replace()メソッドと組み合わせて使用します。
次のように、スラッシュによって囲んで表現します。

参考例

<?php 
  $str = "僕は太郎だよ。";

  var_dump(preg_match("/太郎/", $str));
  var_dump(preg_replace("/太郎/","龍之介",$str));
?>

・preg_match()メソッド

マッチした場合は1を返します。
マッチがなかったら0が返ります。

・preg_replace()メソッド
マッチした箇所に置換した文字列を返します。
マッチがなかった場合は文字列をそのまま返します。

HTMLへの埋め込み

さて、ここからHTMLとの連携についてやっていきます。
HTML単体では静的なWebページしか作れませんが、PHPを埋め込むことで動的なWebページを作ることができます。

今までは <?php から始まり ?> で完結していました。
今度はそれを逆にHTMLソースの中に埋め込んで使います。
つまり  <?php から ?> までの一連の処理を埋め込みます。

ファイルの拡張子は.phpのままで大丈夫です。
まず今回はechoでやってみましょう。
以下を書いてみて下さい。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>HTMLへのPHP埋め込み</title>
  </head>
  <body>
    <h1><?php echo "タイトル"; ?></h1>
  </body>
</html>

以下のように表示されれば、成功です。

if文やforeach文を使って下記のように書くこともできます。
※実際にコピペしてどのような表示になるのか見てみましょう

<?php
$test_fruit = ["ミカン", "ブドウ", "イチゴ", "メロン", "ミカン"];
$test_person = ["name" => "山田太郎", "age" => 18, "country" => "Japan"];
$test_num = 80;
?>

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>HTMLへのPHP埋め込み</title>
  </head>
  <body>
    <!-- if文を埋め込む -->
    <?php if ($test_num === 80) :?>
      <p>80です</p>
    <?php else :?>
      <p>80以外です</p>
    <?php endif ?>

    <!-- foreach文を埋め込む -->
    <!-- シンプルな配列パターン -->
    <?php foreach ($test_fruit as $fruit) :?>
      <p><?php echo $fruit ?></p>
    <?php endforeach ?>

    <!-- 連想配列のパターン -->
    <?php foreach ($test_person as $key => $value) :?>
      <p><?php echo $key ?>:<?php echo $value ?></p>
    <?php endforeach ?>

    <!-- if文とforeach文を組み合わせてもOK -->
    <?php foreach ($test_fruit as $fruit) :?>
      <?php if ($fruit === "ミカン") :?>
        <p><?php echo $fruit ?></p>
      <?php endif ?>
    <?php endforeach ?>
  </body>
</html>

MVCモデルについて

MVCモデルのMVCは、
それぞれ「Model(モデル)」「View(ビュー)」「Controller(コントローラー)」の頭文字から来ています。

Model, View, Controller毎に役割が決まっており、該当する処理について、これから説明していきたいと思います。

Model

Modelとは、ビジネスロジックを書くファイルです。
簡単に言えば、データを処理したり、データをDBへ保存したりするファイルで、
DBからデータを取得して、Controllerへ送るファイルでもあります。

※注意
ModelでDBへの処理を記述するので、誤解されがちですが、ModelとDBは別物です。

View

Viewとは、ユーザーが実際に見る画面を書くファイルです。
主にHTML (*1) で書かれていますが、if文の様なプログラムのコードも頻繁に書かれます。
また、ユーザーからのリクエストをControllerへ送る役割も果たしており、
ユーザーが入力した値をControllerへ送って、その後の処理を行うイメージです。

*1・・・HTMLで書かれていると記載していますが、拡張子は「.php」です。

Controller

Controllerとは、ViewとModelを操作するファイルです。
Viewからリクエストを受け取り、Modelへ処理の命令を出します。
また、Modelから処理の結果を受け取り、レスポンスとしてViewへ返したりします。
VIewとModelの仲介のイメージです。

上記の内容だけ、お伝えしてもイメージがつかないと思いますので、
ユーザーの新規登録機能の流れを使って、イメージしてみましょう。

ユーザー登録の流れは、
画面に入力フォームが用意されており、ユーザーは必要項目を入力後、登録ボタンを押す。
次に、入力された値を受け取り、
問題がなければ、DBへデータ登録し、「登録完了」の画面をユーザーへ返す。
という流れになります。

上記の流れを画面や処理に分けて考えると

  1. 入力フォーム画面
  2. 入力された値を受け取り、確認する処理
  3. DBへ登録する
  4. 登録完了画面

のように分けることが出来ます。

では、これをMVCに置き換えると

  1. 入力フォーム画面(View
  2. 入力値の確認(必要に応じてバリデーション等の処理)(Controller
  3. DBへ登録する(Model
  4. 登録処理結果を確認し、登録完了画面を表示する処理(Controller
  5. 登録完了画面(View

のように分けることが出来ますよ!

HTMLのformからデータを受けとる

HTMLのform要素を使ってデータを受け取ることができます。

PHPにおけるデータの受け取り方には、GET と POST を使う2通りの方法があり、それぞれ次のような特徴、メリットがあります。

GET:データがURLで引き渡される(画面に出て分かる)
POST:データがURLで引き渡されない。また、大量に送るのに適している。

URLにデータを含めてもいい内容かどうかで、双方を使い分けましょう。

また、画面にされないことから、秘匿にしたいデータを送る際はPOSTにして送ることで、
見られるリスクが軽減されます。
ただ、デベロッパーツールを使えば見えてしますので、セキュリティ対策は別途で必要になります。

ですが今回はまず使い方を覚えていきましょう。

以下の手順でいきます。
①送信する側(index.php)と受け取る側(receive.php)のファイルを用意。
②送信する側にHTMLでフォームを作る。
③form の action属性に データの行き先(受け取るファイルのパス)を指定。
④form の method属性に 送信の際の転送方法(HTTPメソッド)を指定。
⑤input の name属性に 任意の値 を指定する。
⑥受け取る側で 任意の値 を受け取る処理を書く。
⑦送信する側で値を入力し送信する。

事項から手順を踏んでGET、POSTそれぞれやってみましょう!

GETでデータを受け取る

それではやっていきましょう。

①送信する側(index.php)と受け取る側(receive.php)のファイルを用意。
index.phpとreceive.phpを作成します。

②送信する側にHTMLでフォームを作る。

ソース:

<!DOCTYPE html>
<html>
  <head>
    <title>HTMLのformからデータを受けとる</title>
    <meta charset="UTF-8">
  </head>
  <body>
    <form action="" method="">
      <br>
      ニックネーム:<input type="text">
      <br>
      メールアドレス:<input type="text">
      <br>
      <input type="submit" value="送信">
      <br>
    </form>
  </body>
</html>

ブラウザ表示:

③form の action属性に データの行き先(受け取るファイルのパス)を指定。

<form action="./receive.php" method="">

④form の method属性に 送信の際の転送方法(HTTPメソッド)を指定。
通常メールアドレスをGET送信したりはしないですが
今回はGETでやってみましょう。

<form action="./receive.php" method="GET">

⑤input の name属性にそれぞれ任意の値を指定する。

ニックネーム:<input type="text" name="nickname">

メールアドレス:<input type="text" name="email">

送信ボタンはそのままで大丈夫です。

全体:

<!DOCTYPE html>
<html>
  <head>
    <title>HTMLのformからデータを受けとる</title>
    <meta charset="UTF-8">
  </head>
  <body>
    <form action="./receive.php" method="GET">
      <br>
      ニックネーム:<input type="text" name="nickname">
      <br>
      メールアドレス:<input type="text" name="email">
      <br>
      <input type="submit" value="送信">
      <br>
    </form>
  </body>
</html>

これで送信側は準備OKです。

⑥受け取る側で 任意の値 を受け取る処理を書く。

今回はGETで受け取りたいので
$_GET[ ] を使います。

使い方
$_GET[“受け取りたいフォームのname属性”];

なので今回は
$_GET[“nickname”];
$_GET[“email”];
となります。

これはPHPの記述なので <?php と ?>を忘れないようにしましょう。

また、この記述だけでは画面に出てこないので
var_dump()で画面出力できるように記述。

参考例

<?php
  var_dump($_GET["nickname"]);
  var_dump($_GET["email"]);
?>

⑦送信する側で値を入力し送信する。
ソースも編集したので
更新も兼ねて再度、
http://localhost/test/index.php
にアクセスしフォームに値を入力しましょう。


山田太郎
test@example.com

そして、送信ボタンで送信するとform要素のaction属性で指定したファイルに飛びます。

以下のようになれば、成功です!

上記の画像のURLに注目してください


localhost/test/receive.phpの後に
?nickname=山田太郎&email=test%40example.comと記述されていると思います
?から始まって & でそれぞれのデータが区切られています。
分解すると


?
nickname=山田太郎
&
email=test%40example.com

となります

この時
email の test%40example.com の
「@」 が 「%40」に変換されています。
これはURLの都合上自動で変換(エンコード)されたものが表示されてますが、


受け取るデータとしては
var_dump()で表示されているように、

変換前のtest@example.com
で受け取れているので、心配はご無用です。

任意でクエリパラメータを設定する

先ほどの処理ではform要素に入力した値をGET方式で送信すると
URLにクエリパラメータが自動で設定されていましたね。

このクエリパラメータは任意で設定することができます。

先ほどのindex.phpに追記してみましょう。

<!DOCTYPE html>
<html>
  <head>
    <title>HTMLのformからデータを受けとる</title>
    <meta charset="UTF-8">
  </head>
  <body>
    <form action="./receive.php" method="GET">
      <br>
      ニックネーム:<input type="text" name="nickname">
      <br>
      メールアドレス:<input type="text" name="email">
      <br>
      <input type="submit" value="送信">
      <br>
    </form>
    <!-- 下記の1行(a要素)を追記 -->
    <a href="./receive.php?test=これはテスト用のクエリパラメータです。">テスト用のリンク</a>
  </body>
</html>

aタグは別のページに遷移させるための要素でしたね。
このaタグには遷移先のページのファイルパスを記載します。

そのファイルパスの後ろに

?<キーの名前>=<渡したいデータ>

のように記載します。

次に遷移先のphpを下記のように編集してみましょう。

<?php
  var_dump($_GET["test"]);
?>

これでデータを受け取る側の準備もOKです。

実際に動作確認してみましょう。

index.phpを開き、テスト用のリンクをクリックします。

下記のような画面が出れば成功です!

クエリパラメータを使用してindex.phpからreceive.phpに任意の値を渡すことができました。

この方法は遷移先のページで使用したい値(データ)がある場合に
使用することができるので覚えておきましょう。

POSTでデータを受け取る

それではやっていきましょう。

①送信する側(index.php)と受け取る側(receive.php)のファイルを用意。
index.phpとreceive.phpを作成します。

②送信する側にHTMLでフォームを作る。

ソース:

<!DOCTYPE html>
<html>
  <head>
    <title>HTMLのformからデータを受けとる</title>
    <meta charset="UTF-8">
  </head>
  <body>
    <form action="" method="">
      <br>
      ニックネーム:<input type="text">
      <br>
      メールアドレス:<input type="text">
      <br>
      <input type="submit" value="送信">
      <br>
    </form>
  </body>
</html>

ブラウザ表示:

③form の action属性に データの行き先(受け取るファイルのパス)を指定。

<form action="./receive.php" method="">

④form の method属性に 送信の際の転送方法(HTTPメソッド)を指定。
特段理由がない時はPOSTを使います。

<form action="./receive.php" method="POST">

⑤input の name属性にそれぞれ任意の値を指定する。

ニックネーム:<input type="text" name="nickname">

メールアドレス:<input type="text" name="email">

送信ボタンはそのままで大丈夫です。

全体:

<!DOCTYPE html>
<html>
  <head>
    <title>HTMLのformからデータを受けとる</title>
    <meta charset="UTF-8">
  </head>
  <body>
    <form action="./receive.php" method="POST">
      <br>
      ニックネーム:<input type="text" name="nickname">
      <br>
      メールアドレス:<input type="text" name="email">
      <br>
      <input type="submit" value="送信">
      <br>
    </form>
  </body>
</html>

これで送信側は準備OKです。

⑥受け取る側で 任意の値 を受け取る処理を書く。

今回はPOSTで受け取りたいので
$_POST[ ] を使います。

使い方
$_POST[“受け取りたいフォームのname属性”];

なので今回は
$_POST[“nickname”];
$_POST[“email”];
となります。

これはPHPの記述なので <?php と ?>を忘れないようにしましょう。

また、この記述だけでは画面に出てこないので
var_dump()で画面出力できるように記述。

参考例

<?php
  var_dump($_POST["nickname"]);
  var_dump($_POST["email"]);
?>

⑦送信する側で値を入力し送信する。
ソースも編集したので
更新も兼ねて再度、
http://localhost/test/index.php
にアクセスしフォームに値を入力しましょう。


山田太郎
test@example.com

そして、送信ボタンで送信するとform要素のaction属性で指定したファイルに飛びます。

以下のようになれば、成功です!

POSTの場合はURLに表示されません。

このように、

URLを誰かとシェアしたりしたい場合は、「GET」

ログイン時など、パスワードのやりとりの場合は、
URLに表示されては困るので、「POST」

が適しているでしょう。

DBとの連携


ここからはデータベースとSQLの知識が必要となります。
先にSQL教材&課題に取り組んでください。


前準備1-1

※すでに本教材のSQL教材にて
db_testとtest01,test02テーブルを作成している方は
前準備1-1〜前準備1-4は不要ですので飛ばしてください。

ブラウザのURLにhttp://localhost/phpMyAdmin/と打ち込むか、
もしくは
以下を参考にphpMyAdminを開いてみてください

MAMP
MAMP初期画面から赤枠をクリック

もしくは参考サイト
https://pc-karuma.net/mamp-phpmyadmin-db-create/

XAMMP

参考サイト
https://itsakura.com/php-xampp-sql
https://pc-karuma.net/mamp-phpmyadmin-db-create/

開けたら、

言語を日本語に設定

これで
初期設定は完了です。

前準備1-2 データベースを作成する

以下の手順を追って学習用のデータベースを作成していきましょう。
1.メニュータブの「データベース」をクリック。

2.データベース名を入力。
今回は「db_test」という名前のDBを作りましょう。

db_testと入力し、作成。

これでデータベースが作成できました。

前準備1-3 テーブルを作成する

次にdb_testというデータベースの中にテーブル(表)を作りましょう。

1.テーブル名を入力
「test01」という名前のテーブルを作りましょう。

カラム数は 「4」で設定し、作成を押してください。

.カラムを入力
ここではテーブルの項目の名前やデータ型、長さ等を入力します。
データ型についてはこちらを参考
https://programmingnavi.com/695/

INTの長さはデフォルト値でよいので今回は入力しません。
以下のように記入できたら右下の保存するを押して保存しましょう。

このようにdb_testの中にtest01というテーブルができていれば、成功です。

前準備1-4 データを登録する

データを登録していきます。
今回は下記画像のようにデータを登録したいと思います。

以下の手順で登録できます。
1.データを登録したいテーブルをクリック。

2.挿入をクリック

3.値を入力

データ型に適したものを入れます。

入力したら実行しましょう。

4.無事に一行挿入できたようですね。それではメニュータブから、表示を押しましょう。

上記のように1,サトウ,23,001のレコードが登録されていたら、成功です。

5.データを確認する。

では、このようにtd_test_test01の他のデータも登録していきましょう。


登録できたら、
この容量で

も作成してしまいましょう。

DB接続

PHPのPDOクラスを使って接続していきます。
PDO(PHP Data Object)とは、PHP標準(5.1.0以降)のデータベース接続クラスのことです。
PHPは標準でMySQLやPostgreSQLやSQLiteなど、色々なデータベースに接続するための命令が用意されています。データベースの種類によって条件分岐させて命令を呼び出せば、プログラムを複数のデータベースに対応させることもできます。

PDOクラスはnewでインスタンス化してから使いましょう。

参考例

<?php

  try {
    // データベースに接続
    $pdo = new PDO(
        "mysql:dbname=db_test;host=localhost;charset=utf8",//dbname=で参照DB名を切り替えられます。
        "root",//初期設定ではユーザー名は「root」になっています。
        "root",//初期設定ではパスワードは「root」もしくは「""(空文字)」になっています。「"root"」でうまくいかない場合は「""」で試してみて下さい。
        [
          PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
          PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]
    );
    echo "DB接続に成功しました。";
    /* ↓↓↓↓↓ データベースから値を取ってきたり,データを挿入したりする処理 ↓↓↓↓↓ */


    /* ↑↑↑↑↑ データベースから値を取ってきたり,データを挿入したりする処理 ↑↑↑↑↑ */

  } catch (PDOException $e) {
    //エラー発生時
    echo $e->getMessage();
    exit;
  }
?>

DB接続に成功しました。
が出力されたら、成功です!

データの取得、画面表示

では実際にDBからデータを取得しましょう。

以下の一連の動作でクエリを実行しています

$stmt = $pdo->prepare(SQL文);
$stmt->execute();
$stmt->fetchAll(PDO::FETCH_ASSOC);

prepareは準備、executeは実行、fetchは読み込む動作です。

流れとしては
インスタンス化した$pdoクラスのprepare関数の引数にSQL文を渡し、
execute関数を実行して準備したクエリを送信。
fetchAllで結果を読み込んでいます。

SQL文は文字列として変数に格納してから使うのが良いでしょう。
読みこんだものを変数に格納し、表示すると、

参考例

<?php

  try {
    // データベースに接続
    $pdo = new PDO(
        "mysql:dbname=db_test;host=localhost;charset=utf8",//dbname=で参照DB名を切り替えられます。
        "root",//初期設定ではユーザー名は「root」になっています。
        "root",//初期設定ではパスワードは「root」もしくは「""(空文字)」になっています。「"root"」でうまくいかない場合は「""」で試してみて下さい。
        [
          PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
          PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]
    );

    // SQL実行
    $sql = "SELECT * FROM db_test.test01";
    $stmt = $pdo->prepare($sql);
    $stmt->execute();
    $data = $stmt->fetchAll(PDO::FETCH_ASSOC);

    //結果の出力
    var_dump($data);
    
  } catch (PDOException $e) {
    //エラー発生時
    echo $e->getMessage();
    exit;
  }
?>

データが取れましたね。

外部ファイルを読み込む

システムが大きくなればなるほと
DBとの接続は様々なファイル内で行われます。
そのため
DB接続の一連の処理をまとめて、その処理を呼び出すようにしましょう。

まずtestフォルダーの中に、commonsフォルダを作成し、
dbconnect.phpを作成しましょう。

dbconnect.phpの接続処理を関数内に書いておけば、
接続したいときにだけ、関数を実行する。という動作が可能になります。

dbconnect.phpに以下を記入して保存しましょう。

<?php
  function dbconnection() {
    global $pdo, $e;
    try {
      // データベースに接続
      $pdo = new PDO(
        "mysql:dbname=db_test;host=localhost;charset=utf8",//dbname=で参照DB名を切り替えられます。
        "root",//初期設定ではユーザー名は「root」になっています。
        "root",//初期設定ではパスワードは「root」もしくは「""(空文字)」になっています。「"root"」でうまくいかない場合は「""」で試してみて下さい。
        [
          PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
          PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]
    );
    } catch (PDOException $e) {
      //エラー発生時
      echo $e->getMessage();
      exit;
    }
  }
?>

そしてindex.php(DBの値を使いたいファイル)に
・dbconnectファイルを読み込む処理。
・dbconnection()関数を実行する処理。
を書きます。

<?php
  require_once( "./commons/dbconnect.php" );//require_once関数で外部ファイルを読み込めます。
  dbconnection();//関数を実行
?>

関数を実行したことで
global $pdo, $eが走り、使えるようになります。

では実際にデータを取得しましょう。

参考例

<?php
  //DB接続処理
  require_once( "./commons/dbconnect.php" );
  dbconnection();

  // SQL実行
  $sql = "SELECT * FROM db_test.test01";
  $stmt = $pdo->prepare($sql);
  $stmt->execute();
  $data = $stmt->fetchAll(PDO::FETCH_ASSOC);

  //結果の出力
  var_dump($data);
?>

DB接続の処理を別ファイルに書いているので
よりコードがスッキリしました。

テーブルの作成

ではPHPからの操作で新規にテーブルを作成しましょう。
以下画像のような内容のテーブルを作成します。

そのため以下のSQLを実行したいです。

CREATE TABLE db_test.testphp (
  id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  nickname VARCHAR(255) NOT NULL,
  email VARCHAR(255) NOT NULL,
  iv VARCHAR(255) NOT NULL,
  password VARCHAR(255) NOT NULL,
  created_at TIMESTAMP NULL
);

ちなみに長い文字列を扱いたい場合は「ヒアドキュメント」という手法が便利です。
使い方

$変数 = <<<終了の文字列
 
「文字列を記述」
 
終了の文字列;

※ 終了の文字列には大文字のアルファベットを使います。
よく見かけるのは「EOM」「EOF」「EOD」ですが、「ABC」でも何でも構いません。
ちなみに「EOM」は End Of Message、「EOF」は End Of File、「EOD」は End Of Document の略です。

では以下を記入し、ブラウザ更新で実行しましょう。
今回は取得するわけではないのでfetchで読み込む処理はいりません。

<?php
  //DB接続処理
  require_once( "./commons/dbconnect.php" );
  dbconnection();

  // SQL実行
  $sql = <<<EOM
  CREATE TABLE db_test.testphp (
    id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    nickname VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL,
    iv VARCHAR(255) NOT NULL,
    password VARCHAR(255) NOT NULL,
    created_at TIMESTAMP NULL
  );
  EOM;
  $stmt = $pdo->prepare($sql);
  $stmt->execute();
?>

phpMyadminの画面もしくはSELECT文で取得して確認してみましょう。

ちなみに一つのDB上に同じテーブル名は複数存在できないので、
testphpテーブルがある状態で
CREATE TABLE db_test.testphpの処理を実行するとエラーになってしまうので気を付けましょう。

foreach,whileを使ったレコードの取得

foreach,whileを使うと、レコードを取得する

この方法によりレコード一つずつに処理を組むことができます。
認証の処理で役に立ちます。

参考例

<?php
  //DB接続処理
  require_once( "./commons/dbconnect.php" );
  dbconnection();

  $stmt = $pdo->query("SELECT id,name FROM test01");
  foreach ($stmt as $row) {
    $id = $row["id"];
    $name = $row["name"];
    echo $id;
    echo $name;
  }

  $stmt2 = $pdo->query("SELECT id,name FROM test01");
  while ($row2 = $stmt2->fetch()) {
    $id2 = $row2["id"];
    $name2 = $row2["name"];
    echo $id2;
    echo $name2;
  }
?>

上記のようにquery()を使うことで、
prepare()やexecute()を使わずともクエリを実行できますが、
後々セキュリティ対策でもprepare()やexecute()が必要になるので、
今のうちから覚えておきましょう。

ハッシュ化

ハッシュ化とは、ハッシュ関数によって文字列を置換して、元の文字を推測できなくすることです。

例えばECサイトの会員登録をするときにユーザーがフォームにパスワードをします。
そしてPHPで受け取ったデータをDBに保存する際にハッシュ化してから保存します。
ハッシュ化をする理由は2つあります。
・パスワードをサイトの管理者に知られないようにするため。
・DBの攻撃によるパスワード情報の流出や不正利用を防止するため。

パスワードをハッシュ化する方法

password_hash関数を使います。
使い方

password_hash(ハッシュ化したいパスワード , アルゴリズムの指定 , オプションの指定(任意))

参考例

<?php
  var_dump(password_hash("aaabbbcccddd", PASSWORD_BCRYPT));
?>

また、認証するにはpassword_verify()を使います。
この関数はhash化されたものを戻すものではなく、
あくまで第一引数と第二引数のハッシュ化の整合性が取れているかを判断するものです。

参考例

<?php
  $hashed = password_hash("aaabbbcccddd", PASSWORD_BCRYPT);

  var_dump(password_verify("aaabbbcccddd", $hashed)); //true
  var_dump(password_verify("aaacccddd", $hashed));  //false
?>

暗号化

暗号化とは
元のデータに対して特別な処理を行い、別データに変換する処理のことです。
それに対して暗号化されたデータを元のデータに戻す処理のことを「復号化」と言います。

暗号化や復号化の処理にはアルゴリズムに応じた「鍵」が必要になります。
同じ暗号アルゴリズムを採用しても、「鍵」が違っていると、処理の結果が変わります。

暗号化とハッシュ化の違い
暗号化は「鍵」があれば元に戻せますが、
ハッシュ化は一度変換してしまうと元に戻せません。

セキュリティ対策が必要になる情報として
・メールアドレスは サイトから案内メールを送信する際に必要となるので「暗号化」
・パスワードは ユーザーのみが知っていればよいので「ハッシュ化」
するとして使い分けます。

今回は暗号化には
opensslを使います。

参考例

<?php
  // 暗号化するデータ
  $str = "test@example.com";
    
  // 暗号化パスワード
  $password = "secpass";

  // 暗号化方式
  $method = "aes-256-cbc";

  // 方式に応じたIVに必要な長さを取得 ランダムな文字列
  $ivLength = openssl_cipher_iv_length($method);

  // IV を自動で生成
  $iv = openssl_random_pseudo_bytes($ivLength);

  // OPENSSL_RAW_DATA と OPENSSL_ZERO_PADDING を指定可
  $options = 0;

  // 暗号化
  $encrypted = openssl_encrypt($str, $method, $password, $options, $iv);
  echo "<br>";
  echo $encrypted;


  // 復号化
  $decrypted = openssl_decrypt($encrypted, $method, $password, $options, $iv);
  echo "<br>";
  echo $decrypted;
?>

暗号化の参考サイト

https://qiita.com/asksaito/items/1793b8d8b3069b0b8d68
https://qiita.com/zaburo/items/e2f08d40d8f8d9ae875f

エンコード

エンコードとは
データを他の形式へ変換することをいい、
デコードとは
データ形式を変換前に戻すことを言います。

DBへの保存や、文字化け、日本語をURLに使える値に変換する時など、
このエンコード、デコードを使います。

参考例

<?php
  $url_str_encode = urlencode("日本語文字列");
  var_dump($url_str_encode);
  echo"<br>";

  $url_str_decode = urldecode($url_str_encode);
  var_dump($url_str_decode);
  echo"<br>";

  $base64_str_encode = base64_encode("日本語文字列");
  var_dump($base64_str_encode);
  echo"<br>";
  
  $base64_str_decode = base64_decode($base64_str_encode);
  var_dump($base64_str_decode);
?>

FROMからデータの検索

今回はHTMLのfrom送信からPHPで値を受け取り、
受け取った値をDBに保存する流れをやっていきましょう。

以下の流れを機能を実装する予定です。
①HTMLでidをPOST送信
②PHPでidを受け取る
③DB(db_test)のtest01テーブルから、
 受け取ったidをもつレコードを取得。
④取得したものを画面に出力する。

まずはindex.phpで以下のフォームを作りましょう

<!DOCTYPE html>
<html>
  <head>
    <title>HTML-PHP-DB</title>
    <meta charset="UTF-8">
  </head>
  <body>
    <form action="./receive.php" method="POST">
      <h1>ID検索</h1>
      id:<input type="text" name="input_id">
      <input type="submit" value="検索">
    </form>
  </body>
</html>

以前作ったreceive.php側で、
・受け取る処理
・DB接続
・検索
・表示
を書いてみましょう

参考例

<?php
  // 受け取る処理
  if (isset($_POST["input_id"])) {// 受け取ったときのみ実行
    $input_id = $_POST["input_id"];
  
    // DB接続
    require_once( "./commons/dbconnect.php" );
    dbconnection();

    // 検索
    $sql = "SELECT * FROM db_test.test01 WHERE id = " . $input_id . ";";
    $stmt = $pdo->prepare($sql);
    $stmt->execute();
    $data = $stmt->fetchAll(PDO::FETCH_ASSOC);

    // 表示
    var_dump($data);
  }
?>

保存したら、
http://localhost/test/index.php
を開き
id欄に 「3」を入力して検索しましょう。

以下の様にデータが取得できたら、成功です。

SQLインジェクション

SQLインジェクションの「インジェクション」とは、
「注入」を意味します。
不正なSQLの命令を、攻撃対象のウェブサイトに「注入する(インジェクションする)」のが、
SQLインジェクションです。
つまりハッキング(厳密に言うとクラッキング)の手法です。
過去多くの企業がSQLインジェクションによる攻撃を受け、莫大な被害を被っています。
webサービスを作る上でSQLインジェクションへの対策は必須なので、学んでいきましょう。

原理としては簡単です。

先ほどのソースコードを拝借すると

$sql = "SELECT * FROM db_test.test01 WHERE id = " . $input_id . ";";

ですよね。
例えば$input_id の中身が3であったときには

SELECT * FROM db_test.test01 WHERE id = 3;

3のところは、ユーザーが入力したものが入るので、
例えば以下の様にも書けます。

3 OR TRUE

この様に入力すると

SELECT * FROM db_test.test01 WHERE id = 3 OR TRUE;

というSQL文が実行されます。

WHERE句の条件式で、OR の右側にTRUEが入っているので全てのレコードが
取得できます。

では実際に実行してみましょう。

全てのレコードが取得できたと思います。

これでも十分クラッキングですが、
もっと酷いこともできます。

例えばこの手法を使ってこのテーブルを削除してしまうことも、
データを改竄してしまうこともできます。

では実際にハッキングしてみましょう。
(他のサイトで試すと犯罪になります。必ず学習環境のみで試してください。)

以下のSQLを実行したいので

SELECT * FROM db_test.test01 WHERE id = 3; DROP TABLE db_test.test01;

入力欄には
3; DROP TABLE db_test.test01

を書けばいいですね。

そして検索を押すと、
SELECTの後にDROP処理が実行されます。
phpMyAdminを見てみるとtest01テーブルが削除されてしまっているのを確認できるかと思います。

これがもし実際のサービスのユーザー情報だったら非常に恐ろしいですよね。
次からはこの対策をやっていきます。

ちなみに消してしまったtest01テーブルとそのデータは以下SQLで作り直しておきましょう。

CREATE TABLE db_test.test01 (
  id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(255) NOT NULL,
  age INT NOT NULL,
  code VARCHAR(255)
);
INSERT INTO 
  db_test.test01
  (id, name, age, code)
  VALUES 
  (1, "サトウ", 23, "001"),
  (2, "スズキ", 37, "001"),
  (3, "コジマ", 19, "003"),
  (4, "ササキ", 51, "002"),
  (5, "ナカタ", 25, "001");

SQLインジェクションの対策

対策としては
・入力時のバリデーション
・SQL文の組み立てをプレースホルダで実装する。
があります。

バリデーションは以前の例で説明したので今回はプレースホルダを使った
SQLの組み立てを実装していきます。

元のソース

$sql = "SELECT * FROM db_test.test01 WHERE id = " . $input_id . ";";
$stmt = $pdo->prepare($sql);
$stmt->execute();

実装後

$sql = "SELECT * FROM db_test.test01 WHERE id = :id;";
$stmt = $pdo->prepare($sql);
$stmt->bindValue(":id", $id, PDO::PARAM_INT);
$stmt->execute();

:idがプレースホルダです
bindValue(“:id”, $input_id, PDO::PARAM_INT);
この処理によって”:id”と$input_idをバインド(結びつけ)ています。
PDO::PARAM_INTはデータ型を指定しています。
idカラムなのでINTですよね。

ほかにはこんなものがあります。
PDO::PARAM_BOOL
ブールデータ型を表します。
PDO::PARAM_NULL
SQL NULL データ型を表します。
PDO::PARAM_STR
SQL CHAR, VARCHAR, または他の文字列データ型を表します。
参考
https://www.php.net/manual/ja/pdo.constants.php

参考例

<?php
  // 受け取る処理
  if (isset($_POST["input_id"])) {// 受け取ったときのみ実行
    $input_id = $_POST["input_id"];
  
    // DB接続
    require_once( "./commons/dbconnect.php" );
    dbconnection();

    // 検索
    $sql = "SELECT * FROM db_test.test01 WHERE id = :id;";
    $stmt = $pdo->prepare($sql);
    $stmt->bindValue(":id", $input_id, PDO::PARAM_INT);
    $stmt->execute();
    $data = $stmt->fetchAll(PDO::FETCH_ASSOC);

    // 表示
    var_dump($data);
  }
?>

こうすれば

3 OR TRUE

と入力しても全てのデータを取られることはありません。

3; DROP TABLE db_test.test01

と入力しても、テーブルは消えません。

SQLインジェクションの対策は必須となっていますので、
PHPでユーザー入力のあるSQL文を書く場合は必ず実装しましょう。

ちなみに
個人情報の流出による損害賠償金額は一人につき5000~20000円と言われています。
これが何万人ともあるDBであれば何億円規模になってきますので、充分注意しましょう。

また、セキュリティ対策については以下のURLが参考になりますので、
目を通しておきましょう。
https://blog.codecamp.jp/php_security

作成時刻、更新時刻、削除時刻

これはDBの構造でよくあるものですが
作成時刻・・・created_at
更新時刻・・・updated_at
削除時刻・・・deleted_at
といって、該当時刻のtimestampをレコードに記録することがよくありますので、覚えておきましょう。

created_atを例に見ていきましょう。
以下はtestphpテーブルにデータを挿入する例です。
通常emailやiv,passwordは暗号化やエンコード 、ハッシュ化して登録しますが
今回は例なのでその処理は割愛します。

<?php
  //DB接続処理
  require_once( "./commons/dbconnect.php" );
  dbconnection();

  $id = "1";
  $nickname = "テスト太郎";
  $email = "test@example.com";
  $iv = "FNjTg2tmhnYjh9u0CimJnw==";
  $password  = "pass0123";

  $sql = "INSERT INTO db_test.testphp(id, nickname, email, iv, password, created_at) VALUES(:id, :nickname, :email, :iv, :password, now())";

  $stmt = $pdo -> prepare($sql);

  $stmt->bindValue(":id", $id, PDO::PARAM_INT);
  $stmt->bindValue(":nickname", $nickname, PDO::PARAM_STR);
  $stmt->bindValue(":email", $email, PDO::PARAM_STR);
  $stmt->bindValue(":iv", $iv, PDO::PARAM_STR);
  $stmt->bindValue(":password", $password, PDO::PARAM_STR);
  $stmt->execute();
?>

これを実行すると

このように時間が入力されたと思います。
これはSQLのnow()関数で現在の時刻を自動的に入力した結果です。

同様にUPDATEを使う時もupdated_atというカラムに日時を入れることで実装できます。
また、deleted_atは、deleted_atカラムの値がNULLならばユーザーはアクティブ、
値があればそのユーザーは削除済み。という扱いの条件分岐に使われたりします。

メール送信処理

PHPでメール送信を行うことができます。

mb_send_mail関数を使いますが、初期設定等が必要なので以下ソースと
参考サイトを見てみてください。

<?php
  mb_language("Japanese"); 
  mb_internal_encoding("UTF-8");
  
  $email = "xxxxxx@example.com";//送信元
  $subject = "テスト"; // 題名 
  $body = "これはテストです。\n"; // 本文
  $to = "xxxxxx@example.com"; // 宛先
  $header = "From: $email\nReply-To: $email\n";
  
  mb_send_mail($to, $subject, $body, $header);
?>

参考一覧
初期設定MAMP
https://iritec.jp/web_service/14794/

初期設定XAMMP
https://my-web-note.com/xampp-mail-send-php/

https://uxmilk.jp/15057
https://www.sejuku.net/blog/24658


これでPHPの説明は以上です。
本教材や検索で探し得たWebサイトを参考に応用課題に取り組んでください。

PHP最終課題

掲示板サイトを作る