PHPプログラミング


Webページを作るためのHTML埋め込み等で利用できる言語。
PHP自体はサーバで処理される言語で、バックエンドのデータベースなどからデータを取得・更新するなどした上で
webブラウザに情報を表示できる。PHPプラグラミング勉強のために情報やコードのsampleをまとめていく。

# 0.HTML基礎

言わずと知れたホームページを書くための言語。
ブラウザアプリからwebページのソースを表示すると下記のようにソースを出力できたりする。

```ruby:sample
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>QA Sheet</title>
</head>
<body>
<h1>Sample</h1>
<h2>Sample</h2>
<p>xxxxxxxxxxxxx</p>

</body>
</html>
```

基本的には開始タグ<タグ名>,終了タグ</タグ名>の組み合わせでHTMLは表現する。
主なタグとしては下記がある。

|タグ名 |用途  |
|------|------|
|h1  |見出し1  |
|h2  |見出し2  |
|h3  |見出し3  |
|p   |段落  |
|ul   |箇条下記  |
|ol   |番号付きリスト  |
|li   |リストの項目  |
|br   |改行  |
|botton   |ボタン  |
|input   |インプット  |
|a   |文書間リンク記述  |
|table   |テーブル  |
|tr   |テーブルの行  |
|td   |テーブルのセル(データ)  |
|th   |テーブルのセル(見出し)  |
|a   |hrefにリダイレクト先アドレスを記載すると定義した文字列クリックによりリダイレクトされる |


これだけだと不明なのでsampleのHTMLコードを示す。

```ruby:sample1(基本)
<!doctype html>
<html>
    <head>
        <title>主な要素</title>
    </head>
    <body>
        <h1>タイトル</h1>
        <h2>副題</h2>

        <p>
            これはパラグラフです。文節を記述するためタグです。
            一部分だけをマーキングする場合は<span>スパン</span>を使用します。
        </p>

        <h3>番号付リストの例</h3>
        <ol>
            <li>野菜を切る</li>
            <li>材料を炒める</li>
            <li>盛り付ける</li>
        </ol>

        <h3>箇条書きの例</h3>
        <ul>
            <li>HTMLの基本</li>
            <li>スタイルの基本</li>
            <li>スクリプトの基本</li>
        </ul>

        <button>OKボタン</button>
        <button>NGボタン</button>
        <input type="text" value="hello" />
        <input type="text" value="world" />
    </body>


</html>
```

![スクリーンショット 2019-06-24 14.42.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245585/2e01cda5-4f1f-0d4a-fc80-a12314db6ae6.png)


```ruby:sample1(テーブル)
<!doctype html>

<html>
<head>
<meta charset="utf-8">
<title>Table Test</title>
</head>
<body>
<table border="2">
<tr>
  <th>Country</th>
  <th>Metropolitan</th>
  <th>number</th>
</tr>
<tr>
  <td>Japan</td>
  <td>Tokyo</td>
  <td>300</td>
</tr>
<tr>
  <td>America</td>
  <td>New York</td>
  <td>1000</td>
</tr>

<tr>
   <td>
   <a href="https://www.yahoo.co.jp/">yahoo.com</a>
   </td>
</tr>
</table>

</body>
</html>
```
![スクリーンショット 2019-06-24 15.02.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245585/ce3bae39-93a4-fb76-7e9b-1b672a3e9371.png)


#1.PHPプログラミング基礎
忘れやすそうな事項をメモがてら記載して行く。（あまりに基本的なことは記載しない)

##タイムゾーン・日付・時刻表示
```ruby:日付フォーマットの仕方
time()はUNIXタイムスタンプなのでそれをyyyy/mm/dd hh:mm:ss形式に変換。2019/6に実行

<?php
date_default_timezone_set('Asia/Tokyo'); //タイムゾーンの設定
echo date("Y/m/d H:i:s") . "\n"; //「現在時刻」
echo date("Y/m/12") . "\n"; //「2019/06/12」
echo date("Y/m/t") . "\n"; //「2019/06/30」
?>
```

##ファイルに対するIO
```ruby:ファイルの読み書き
<html>
<head><title>Access Log</title></head>
<body>
<?php
//デフォルトタイムゾーン定義
date_default_timezone_set('Asia/Tokyo');
print(date("Y/m/d H:i:s")."\n");
print("<p>Access Log</p>\n");
//アクセスログのファイルポインタを定義
$filepointer=fopen("./logs/accesslog_test","a+");
//アクセスログの排他制御を実現するためにファイルをLOCKする。
flock($filepointer,LOCK_EX);
//ファイルに日時 アクセス元IPアドレスの書き込みを実施。
fputs($filepointer,date("Y/m/d H:i:s "). $_SERVER["REMOTE_ADDR"] ."\n");
//ファイルロックを解除
flock($filepointer,LOCK_UN);
//ファイルポインタを先頭に戻す
rewind($filepointer);

//ファイルの読み込み実施・feofはファイルポインタの最後にTRUEを返す関数
while(!feof($filepointer)){　　　　　　　　　　　　 
        $fileline=fgets($filepointer);
        print($fileline."<br />");
}

?>
</body>
</html>
```
##クッキー
クッキーはサーバーにアクセスしてきたブラウザに対して一時的にデータを書き込む仕組みで
ブラウザの訪問時きや、何回訪問したのかという情報を記録しておくことが可能。これによってサーバ側から
ブラウザそれぞれを識別して異なる処理を実行することが可能。

クッキーはphpではsetcookieで付与する。
setcookie(クッキー名[,クッキーの値 [,有効期限 [,パス [,ドメイン [, セキュア]]]]])
※セキュアはクッキーをSSL通信時のみ付与するかどうかをTRUE/FALSEで制御
※ここで付与されたクッキーは次回からブラウザからのリクエストヘッダに付与される。

```ruby:cookieのsample
<?php
$time=$_COOKIE["count"];
if(!isset($time)){
	$time=0;
}else{
	$time++;
}
setcookie("count",$time,time()+600);  //Cookie名,Value,Expire Time
?>
<html>
<head>
<title>Cookie Test</title>
</head>
<body>
<?php
if($time == 0){
	print("Nice to meet you!");
}elseif($time ==1){
	print("Second Time!");
}elseif($time ==2){
	print("Third Time!");
}else{
	print("Other!");
}	
?>
</body>
</html>
```

<?php
    session_start();
?>


##セッション
session_start()を記述すると、セッションが開始されます。
セッションとh始まり～終わりまでの一連の処理の中でいつ何時でもクライアントを識別するための仕組みである。
同じクライアント（ブラウザ）のアクセスの途中経過についてはサーバ側に安全に保管される。

クッキーだとクライアント側に大事なデータを保管してしまう可能性があり。
セッションの場合はクライアントにクライアントを識別するための一意のID（セッションID)を渡して各クライアントを
サーバ側で判別する。

```ruby:sessionのsample
<html>
<head><title>PHP TEST</title></head>
<meta charset="utf-8">
<body>

<?php
    //デフォルトタイムゾーン定義
    date_default_timezone_set('Asia/Tokyo');

    if (!isset($_SESSION["visited"])){
        print('初回の訪問です。セッションを開始します。');

        $_SESSION["visited"] = 1;
        $_SESSION["date"] = date("Y/m/d H:i:s");;
    }else{
        $visited = $_SESSION["visited"];
        $visited++;

        print('訪問回数は'.$visited.'です。<br>');

        $_SESSION["visited"] = $visited;

        if (isset($_SESSION["date"])){
            print('前回の訪問日時は'.$_SESSION["date"].'です。<br>');
        }

        SESSION["date"] = date("Y/m/d H:i:s");
    }

?>

</body>
</html>
```

##HTMLフォーム処理
HTMLフォームを入力して、それを画面出力する例

テキストボックス、ラジオボタン、チェックボックス、プルダウン、テキストエリアを実装。
POSTメソッドでsample.phpで処理させる

```ruby:sample.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>QA Sheet</title>
</head>
<body>
<h1>QA Sheet!!!</h1>
<form method="post" action="sample.php">
 <p>
 Name：<input type="text" name="name" />
 </p>

 <p>
 Sexuality：
 <input type="radio" name="Sexuality" value="Man" /> Man　
 <input type="radio" name="Sexuality" value="Women" /> Women
 </p>

 <p>
 Product：
 <input type="checkbox" name="properties[]" value="CellPhone" /> CellPhone
 <input type="checkbox" name="properties[]" value="Car" /> Car
 <input type="checkbox" name="properties[]" value="Cottage" /> Cottage　
 </p>

 <p>
 Favorite Fruit：
 <select name="Fruit">
   <option>Apple</option>
   <option>Orange</option>
   <option>Banana</option>
 </select>
 </p>

 <p>
 <textarea name="freeanswer" rows="4" cols="40">Free Comment</textarea>
 </p>
 
 <p>
 <input type="submit" value="Submit" />　
 <input type="reset" value="Cancel" />
 </p>

</form>

</body>
</html>
```

![スクリーンショット 2019-06-26 15.29.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245585/aa18af5f-3863-f278-4494-b99629b69a47.png)

上記の回答結果

```ruby:sample.php
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Answer Sheet</title>
</head>
<body>
<?php
$name = $_POST['name'];
$sexuality = $_POST['Sexuality'];
$properties = implode(", ",$_POST["properties"]);
$fruit = $_POST['Fruit'];
$freeanswer = $_POST['freeanswer'];
?>

次のデータを受け取りました
<br />
<table border="1">
<tr>
  <th>Name</th>
  <td><?php echo $name ?></td>
</tr>
<tr>
  <th>Sexuality</th>
  <td><?php echo $sexuality ?></td>
</tr>
<tr>
  <th>Product</th>
  <td><?php echo $properties ?></td>
</tr>
<tr>
  <th>Fruit</th>
  <td><?php echo $fruit ?></td>
</tr>
<tr>
  <th>Free Answer</th>
  <td><?php echo $freeanswer ?></td>
</tr>

</table>
</body>
</html>
```

![スクリーンショット 2019-06-26 15.31.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245585/35ffec30-c2ee-eb0b-ed62-fb8108e3894c.png)

##ファイルアップロード

PHPでWebブラウザ経由のファイルアップロードについてはスーパーグローバル変数\$_FILESを活用する。
\$_FILESは2次元連想配列として付与されて下記の情報を入手可能である。
upfileはアップロード時に、\<input type="file>で指定したnameの値である。


|要素|意味|
|:---------------------------------|:--------------------------------------|
|$_FILES['upfile']['name']  |元ファイル名  |
|$_FILES['upfile']['type']  |ブラウザによって得られるMIME型  |
|$_FILES['upfile']['size']  |アップロードされたファイルサイズ(byte)  |
|$_FILES['upfile']['tmp_name']  |サーバ上にアップロードされたファイルに<br>与えられる一時的な名前（フルパス）  |
|$_FILES['upfile']['error']  |エラーコード |

実際にアップロードされたファイルを得るには\$_FILESから得られたファイルに対して、
名前と保管場所を与える必要がある。

move_uploaded_file(移動前パス,移動後ファイルパス)


```ruby:uploader.html
<html>
<head><title>upload test</title></head>
<meta charset="utf-8">
<body>
----------------------Upload Testing------------------------------------
<form method="post" enctype="multipart/form-data" action="uploader.php">
<input type="file" name="upfile">
<input type="submit" value="UPLOAD">
</form>
</body>
</html>
```
```ruby:uploader.php
<html>
<head><title>PHP TEST</title></head>
<meta charset="utf-8">
<body>
<p> file uploader </p>
<?php

$updir="./upload/";
$filename=$_FILES['upfile']['name'];

if (move_uploaded_file($_FILES['upfile']['tmp_name'],$updir.$filename) == FALSE){
        print("Upload failed...");
        print($_FILES['upfile']['error']);
}else{
        print("<b>".$filename."</b> uploaded");
}
?>
</body>
</html>
```

##PDOによるデータベース接続処理[PHP Data Objects]
PHPでデータベースを接続を実施する場合はPDOでオブジェクト作成、その後PDOオブジェクトのメソッドを利用してデータベースを操作する。

1)SQL実行方法

```ruby:queryメソッドによる単純即時実行(MySQL)
//接続定義
$dsn = 'mysql:host=db1;port=3307;dbname=testdb';
$user='admin';
$password='P#ssw0rd';
$dbh = new PDO($dsn, $user, $password);

//SQL実行部分
$dbh->query('select * from item where id=100);
```
```ruby:queryメソッドによる単純即時実行(PostgreSQL)
//接続定義
$dsn = 'postgresql:host=XXX;port=5432;dbname=testdb';
$user='pguser01';
$password='P#ssw0rd';
$dbh = new PDO($dsn, $user, $password);

//SQL実行部分
$dbh->query('select * from item where id=100);
```

```ruby:prepateメソッド,executeメソッドによるパラメータに変数を使って実行
//接続定義
$dsn = 'mysql:host=db1;port=3307;dbname=testdb';
$user='admin';
$password='P#ssw0rd';
$dbh = new PDO($dsn, $user, $password);

//SQL実行部分
$smt=$dbh->prepare("UPDATE item SET price = :price WHERE id = :id");
$smt->execute(array(':price'=>500, ':id'=>2));
```


2)SQL出力方法
1)の方法ではSQLの実行結果が戻り値として返されるだけでデータの値としては使えない。
fetchメソッドでデータの値として使う。

```ruby:fetchメソッドによる値取得
//接続定義
$dsn = 'mysql:host=db1;port=3307;dbname=testdb';
$user='admin';
$password='P#ssw0rd';
$dbh = new PDO($dsn, $user, $password);

//1レコードあたり1次元配列として取得。複数行の場合は2次元配列になる
$sql = "SELECT * FROM item";
$rows = $dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);
var_dump($rows);

//select指定した1カラムを1次元配列として取得。
$sql = "SELECT name FROM item";
$rows = $dbh->query($sql)->fetchAll(PDO::FETCH_COLUMN);
var_dump($rows);

```

```ruby:fetchしなくても・・・こっちの方が単純？
//接続定義
$dsn = 'mysql:host=db1;port=3307;dbname=testdb';
$user='admin';
$password='P#ssw0rd';
$dbh = new PDO($dsn, $user, $password);
$sth = $dbh->query('select * from item limit 100');
foreach($sth as $row){
        print($row['id'].",".$row['name'].",".$row['description']."\n");
}
```

- DB 接続定義用の関数を別ファイルで保有する。 

```ruby:DB.php
<?php
function db_connect(){
    $db_user = "root";          // ユーザー名
    $db_pass = "P#ssw0rd";      // パスワード
    $db_host = "mysql1";        // ホスト名
    $db_name = "db01";          // データベース名
    $db_type = "mysql";         // データベースの種類

    $dsn = "$db_type:host=$db_host;dbname=$db_name;charset=utf8";

    try {
      $pdo = new PDO($dsn, $db_user,$db_pass);
      $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    } catch(PDOException $Exception) {
      die('エラー :' . $Exception->getMessage());
    }
    return $pdo;
}
?>
```


`参考`
https://blog.webico.work/php-login