【DB不要】PHPでToDoアプリを作る（データベースを使わない）

# データベース不要のToDoアプリ
## はじめに
今回、シンプルなToDoアプリ（掲示板）を作りました。
言語はPHPのみで、MySQLなどのデータベース使わずに作りました。**テキストファイルを作成し、JSON形式で保存します。**
[ToDoアプリ](http://mf3px.sakura.ne.jp/ToDoApp/)
## 今回作ったToDoアプリの特徴
- 投稿内容はボタンで削除することができます。

## この記事の対象者
PHPの基礎を勉強している人，PHPやサーバーサイド言語に興味がある人などなど。

## さっそく作きましょう！
わからない部分は一つ一つ調べ、進めていきましょう。


## PHP(32行)，HTML
スクリプトを3分割していますが、実際は全て繋げて一つのファイル(todo.php)のみに記述します。まずはPHP前半です。（主に変数の準備）

```php:todo.php
<?php

//HTMLタグの入力を無効にし、文字コードをutf-8にする
//（PHPのおまじないのようなもの）
function h($v){
    return htmlspecialchars($v, ENT_QUOTES, 'UTF-8');
}

//変数の準備
$FILE = 'todo.txt'; //保存ファイル名

$id = uniqid(); //ユニークなIDを自動生成

//タイムゾーン設定
date_default_timezone_set('Japan');
$date = date('Y年m月d日H時i分'); //日時（年/月/日/ 時:分）

$text = ''; //入力テキスト

$DATA = []; //一回分の投稿の情報を入れる

$BOARD = []; //全ての投稿の情報を入れる

//$FILEというファイルが存在しているとき
if(file_exists($FILE)) {
    //ファイルを読み込む
    $BOARD = json_decode(file_get_contents($FILE));
}
```
### **☞ 今回の変数を保存する配列について**

- `$BOARD[]`　**全体の配列**
- `$DATA[$id, $date, $text]`　**一回分の投稿**（これを`$BOARD[]`へ挿入していく）

結局、下記のような形で保存されます。
`$BOARD[$DATA[省略], $DATA[省略], $DATA[省略],...]`

### **☞ 保存データの読み取り**
詳細は後々説明しますが、今はなんとなくデータを持ってきて、変数に保存したんだなと思っておいてください。（**最初の時点ではファイルもデータもないのでスルーでOK！**）
また、今回は全てのデータをJSON形式（今回はただの配列だと思ってください）で、**todo.txtというファイル**に保存していきます。

- `file_get_contents()`　**ファイルを読み込む**
- `json_decode()`　**JSON形式をPHPで扱える形式に変換する**

ここからのPHP後半が、ファイルを生成し、フォーム内容を保存していく手順になります。

```php:todo.php
//$_SERVERは送信されたサーバーの情報を得る
//REQUEST_METHODはフォームからのリクエストのメソッドがPOSTかGETか判断する
if($_SERVER['REQUEST_METHOD'] === 'POST'){
    //$_POSTはHTTPリクエストで渡された値を取得する
    //リクエストパラメーターが空でなければ
    if(!empty($_POST['txt'])){
        //投稿ボタンが押された場合
        
        //$textに送信されたテキストを代入
        $text = $_POST['txt'];

        //新規データ
        $DATA = [$id, $date, $text];
        //新規データを全体配列に代入する
        $BOARD[] = $DATA;

        //全体配列をファイルに保存する
        file_put_contents($FILE, json_encode($BOARD));
        
    }else if(isset($_POST['del'])){
        //削除ボタンが押された場合
        
        //新しい全体配列を作る
        $NEWBOARD = [];
        
        //削除ボタンが押されるとき、すでに$BOARDは存在している
        foreach($BOARD as $DATA){
            //$_POST['del']には各々のidが入っている
            //保存しようとしている$DATA[0]が送信されてきたidと等しくないときだけ配列に入れる
            if($DATA[0] !== $_POST['del']){
                $NEWBOARD[] = $DATA;
            }
        }
        //全体配列をファイルに保存する
        file_put_contents($FILE, json_encode($NEWBOARD));
    }

    //header()で指定したページにリダイレクト
    //今回は今と同じ場所にリダイレクト（つまりWebページを更新）
    header('Location: '.$_SERVER['SCRIPT_NAME']);
    //プログラム終了
    exit;
}
?>
```
### **☞ 保存場所を作る**

- `json_encode()`　**メッセージの配列をJSON形式に変換する**
- `file_put_contents(a,b)`　**bの内容をファイルaに保存する（もしファイルaが存在しなければ自動で生成）**

### **☞ 保存場所**
今回は、最初にテキストが送信されたとき、投稿した情報である`$DATA`（idと日時、入力文字）を、`file_put_contents()`を用いて自動生成したtodo.txtというファイルに保存します。

ToDoApp
├── todo.php
├── todo.txt（自動で生成される）

ここからがPHPの後に記述していくHTMLです

```php:todo.php
<!DOCTYPE html>
<html lang= "ja">
<head>
    <meta name= "viewport" content= "width=device-width, initial-scale= 1.0">
    <meta http-equiv= "content-type" charset= "utf-8">
    <title>ToDoApp</title>
</head>
<body>
    <h1>ToDoアプリ</h1>
    
    <section class= "main">
        <h2>ToDoAppに投稿する</h2>

        <!--投稿-->
        <form method= "post">
            <input type= "text" name= "txt">
            <input type= "submit" value= "投稿">
        </form>    

        <table style= "border-collapse: collapse">
        <!--tableの中でtr部分をループ-->
        <?php foreach((array)$BOARD as $DATA): ?>
        <tr>
        <form method= "post">
            <td>
                <!--テキスト-->
                <?php echo h($DATA[2]); ?>
            </td>
            <td>
                <!--日時-->
                <?php echo $DATA[1]; ?>
            </td>
            <td>
                <!--削除-->
　　　　　　　　　<!--この時その投稿のidがサーバーに送信される-->
                <input type= "hidden" name= "del" value= "<?php echo $DATA[0]; ?>">
                <input type= "submit" value= "削除">
            </td>
        </form>
        </tr>
        <?php endforeach; ?>
        </table>
    </section>
```

### **☞ 今回のformについて**
今回はフォームから入力した内容をPOST送信でサーバーに送信します。
### **☞ 投稿**
テキストを入力し**投稿ボタンを押したとき、そのテキスト内容がサーバーに送信**されます。**それと同時にPHPで`$id`と`$date`を呼び出し`$text`とともに`$DATA`に格納**します。この`$DATA`を全体配列`$BOARD`挿入し、保存します。
### **☞ 削除**
**削除ボタンを押したとき、その投稿のidがサーバーに**送信されます。**そのidが、すでに保存されている投稿のidと同じであれば保存せず、それ以外を保存**しなおします。

## CSS，JavaScript
CSSやJavaScriptを使うと、よりUIを整えることができます。

## おわりに
今回はデータベースを使わずに、シンプルなToDoリストを作ってみました。もちろんデータが膨大になったり、複雑になったときはMySQLやFirebaseを使うといいでしょう。**データが軽量かつシンプルに完結できる方法**を模索した結果、このようなアプリを作ることができました。
何かアドバイス等あれば教えていただければと思います。
そして、この記事が皆様にお役に立てれば幸いです。

## 参考サイト
https://code-notes.com/lesson/4 ユニークなidを用いてデータを削除
確かな力が身につくPHP「超」入門 p.159 ファイル入出力