すごくわかりやすい家計簿アプリ作成を通して学ぶPHP+MySQL

フロントエンドの学習から入って、いまいちバックエンドの感覚が分からなくて困っていた時にこの動画を発見して大変勉強になりましたので、備忘録的にまとめてみました。

勉強させていただいた動画：[よねのYouTube大学プログラミング学科「【PHP+MySQL】簡単な家計簿システムを作成しよう」](https://youtube.com/playlist?list=PLey1r5U24UpGQ9_Zu2RLpvIBot0ANnUQ4)

### 1.環境

MAMP

### 2.データベースの作成と呼び出し
データはMySQLにphpMyAdminで作成

```PHP:dbconnect.php
<?php

try {

  $pdo = new PDO(
    // 'mysql:dbname=YOUR_DB_NAME;host=localhost;charset=utf8mb4',
    'mysql:dbname=simple-kakeibo;host=localhost;charset=utf8mb4',
    'root',
    'root',
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ]
  );

} catch (PDOException $e) {

    header('Content-Type: text/plain; charset=UTF-8', true, 500);
    exit($e->getMessage());

}
```
データベースの現時点での内容を`$pdo`に入れ、他のファイルで呼び出して使う。
### 3.データ入力用のファイルを作成
phpファイルに通常のhtmlで書いた`form`から送信

```php:createForm.php
    <form class="m-5" action="./create.php" method="POST">
      <p class="alert alert-primary" role="alert">新規追加フォーム</p>
      <div class="form-group">
        <label for="date">日付</label>
        <input type="date" class="form-control" id="date" name="date">
      </div>
   //省略
    </form>
```
`form` タグのaction属性に遷移するテンプレートのurlを記述し、method属性にPOSTを指定することで入力された値を取得して送れる。
値のkeyは`input`タグのname属性に記述する。

### 4.値を受けとってデータベースに送る。
値は複数あるが`date`に絞ってみていくとわかりやすいので🌟をつけておきました。

```php:create.php
<?php

// dbconnect.phpを読み込む ➞ DBに接続
include_once('./dbconnect.php');

// 新しいレコードを追加するための処理
// 【処理の流れ】
// 最終のゴール：新しい家計簿が追加されて、TOPに戻る

// 1. 画面で入力された値の取得
// 2. PHPからMySQLへ接続
// 3. SQL文を作成して、画面で入力された値をrecordsテーブルに追加
// 4. index.phpに画面遷移する

$date = $_POST['date'];//🌟
$title = $_POST['title'];
$amount = $_POST['amount'];
$type = $_POST['type'];

// INSERT文の作成
$sql = "INSERT INTO records(title, type, amount, date, created_at, updated_at) VALUES(:title, :type, :amount, :date, now(), now())";

// 先程作成したSQLを実行できるよう準備
$stmt = $pdo->prepare($sql);

// 値の設定
$stmt->bindParam(':title', $title, PDO::PARAM_STR);
$stmt->bindParam(':type', $type, PDO::PARAM_INT);
$stmt->bindParam(':amount', $amount, PDO::PARAM_INT);
$stmt->bindParam(':date', $date, PDO::PARAM_STR);//🌟

// SQLを実行
$stmt->execute();

// index.phpに移動
header('Location: ./index.php');
exit;
```

### 5.最初のページに現在のデータを取得して表示する。

```php:index.php
<?php

// DBへの接続
include_once('./dbconnect.php');

// functions.phpを読み込む
include_once('./functions.php');

// 処理の流れ
// 1. DBへの接続
// 2. recordsテーブルのデータを全件取得
// 3. 全データを画面に表示


// SQL文を作成
$sql = "SELECT * FROM records";

// SQLの実行準備
$stmt = $pdo->prepare($sql);

// SQLの実行
$stmt->execute();

// 全データを変数に入れる
$records = $stmt->fetchAll();

?>
<!DOCTYPE html>
//html部分から$recordsのデータをfoueachで抜き出して`table`に埋め込んでいく部分を抜粋
//Bootstrapのクラスは見にくいので割愛
   <?php foreach($records as $record): ?>

     <tr>
　　　//ここで使われている関数h()については`functions.php`で記述されている
        <td class=""><?php echo h($record['date']); ?></td>
        <td class=""><?php echo h($record['title']); ?></td>
        <td class=""><?php echo h($record['type']) == 0 ? h($record['amount']) : '' ?></td>
        <td class=""><?php echo h($record['type']) == 1 ? h($record['amount']) : '' ?></td>
        <td class="">
         <a href="./editForm.php?id=<?php echo h($record['id']); ?>" class="">編集</a>
         <a href="./delete.php?id=<?php echo h($record['id']); ?>" class="">削除</a>
        </td>
    </tr>

   <?php endforeach; ?>
```

```phpl:functions.php
<?php
//このようにして万が一意味のあるコードなどを書かれてもただの文字列に加工する
function h($value) {
  return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
```

### 6.入力されたレコードを編集する。

`index.php`の各レコードの右にある「編集」「削除」ボタンにそのidを渡しhref属性に埋め込む事でどのレコードを選んでいるのか決定する。

まずは`editForm.php`に記述する。
GET送信で送られたidを変数に入れる。
それを使ってデータベースにsqlを投げる。

```PHP:editForm.php
$id = $_GET['id'];//ここに全ての値が入っている。

// SQL作成
$sql = "SELECT * FROM records WHERE id = :id";

// SQL実行準備
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);//ここでGET送信で送られてきたidをsql文に連結させる。

// SQLの実行
$stmt->execute();

// 実行結果の取得
$record = $stmt->fetch();//一件だけなのでfetchAll()ではなくfetch()を使う。
```
各項目に取得した値をセットする。
一番上の日付の部分と、三項演算子を使う収入・支出で説明。
'input`タグの中でcheckedの文字を出力してそれを属性としている。
htmlspscialchars()を使った関数h()を使うために`include_once('./functions.php');`でfunctions.phpを読み込んでおく。

```PHP:editForm.php
<form class="" action="./update.php" method="POST">
  <input type="hidden" name="id" value="<?= $id; ?>">
  <p class="" role="">編集フォーム</p>
  <div class="">
    <label for="date">日付</label>
    <input type="date" class="" id="date" name="date" value="<?= h($record['date']); ?>">
   </div>
      <div class="">
        <div class="">
          <input class="" type="radio" name="type" id="income" value="0"
            <?= h($record['type']) == 0 ? 'checked' : '';  ?>
          >
          <label class="" for="income">収入</label>
        </div>
        <div class="">
          <input class="" type="radio" name="type" id="spending" value="1"
            <?= h($record['type']) == 1 ? 'checked' : '';  ?>
          >
          <label class="" for="spending">支出</label>
        </div>
      </div>
      <div class="form-group">
</form>
```
`<?php echo`は`<?=`と書いても構わない。

### 7.編集されたレコードで上書きする。

editForm.phpからPOSTで送られてくるデータを`$_POST`で受け取って変数に取り出す。
新規作成とほぼ同じだが、既に存在するレコードを上書きするのでidの値も取り出す。
ただし、`index.php ==> editForm.php`へはaタグのリンクでidの値が渡されているがこれはGET送信になるのでeditForm.phoでは`$_GET`で値を取り出せるが、リクエストスコープの寿命の関係でその先のupdate.phpでは参照できない。
なので、editForm.phpで値を隠して渡す。

```PHP:editForm.php
<form class="" action="./update.php" method="POST">
  <input type="hidden" name="id" value="<?= $id; ?>">
  <p class="" role="">編集フォーム</p>
//省略
</form>
```

`input`タグのtype属性にhiddenを設定すると表示されない。これに`value='<?= $id; ?>'`として値を渡せる。
それをupdate.phpで取り出すときはPOST送信なので他の値同様に$_POSTで取り出せる。
update.phpは上書きとindex.phpへの遷移だけで表示するものはないので通過していく感じ。

### 8.レコードの削除

index.phpからGETで渡されてきたid使ってレコード指定してまるまる削除してindex.phpへ遷移させる。