初心者がphp,sqlで簡単ブログ作成(備忘録)

phpとsqlを勉強を始めた初心者です。
今回はhttp://ponk.jp/php/basic/blog　さん
の簡単んブログの作成と簡単な解説をして行きたいと思います。
あくまで、phpとsqlにおける解説なので、html,cssの説明は省きます。
下準備として、お使いのサーバーにblogとうフォルダを作成してください。
それから、blog.cssというものを作成しておいておきます。

```blog.css
body {
  background-color:#f77;
  font-size: 14px;
  font-family: Helvetica,Arial,sans-serif;
}
a:link, a:visited {color: #a00;}
a:hover {color: #fca;}
p {
  margin: 0;
  padding: 0;
}
h1 {
  margin: 10px 0;
  padding: 0;
  color: white;
  font-size: 32px;
  text-align: center;
}
h2 {
  margin: 0 -20px 10px -20px;
  padding: 5px 10px;
  background-color: #379;
  color: white;
  font-size: 18px;
}
h3 {
  margin: 0 -15px 10px -15px;
  padding: 5px 10px;
  background-color: #a55;
  color: white;
  font-size: 14px;
}
.post {
  width: 500px; 
  margin: 0 auto 15px auto;
  padding: 0 20px 20px 20px; 
  background-color: #fb0; 
}
.comment {
  margin: 10px 0;
  padding: 0 15px 15px 15px; 
  background-color: #da7; 
}
.commment_link {
  text-align: right;
}
```

sqlをやっている方には以下のようなsql文を作成してください。

```sql
CREATE DATABASE blog;
```

```sql

CREATE TABLE post (
  no SERIAL,
  title TEXT,
  content TEXT,
  time TIMESTAMP
);

CREATE TABLE comment (
  no SERIAL,
  post_no INT,
  name TEXT,
  content TEXT,
  time TIMESTAMP
);

INSERT INTO post(no,title,content) VALUES(1,'記事１タイトル','記事１の内容です。');
INSERT INTO post(no,title,content) VALUES(2,'記事２タイトル','記事２の内容です。');
INSERT INTO comment(no,post_no,name,content) VALUES(1,1,'たろう','記事１へのコメントです。');
INSERT INTO comment(no,post_no,name,content) VALUES(2,1,'はなこ','記事１へのコメントです。');
```


はじめにデータベースのblogを作成しています。それから二つのテーブルを作成しています。一つ目はブログ情報を集めたテーブル、二つ目はブログのコメントを集めたテーブルとなっています。

次に、ブログの表示画面を作ります。

```index.php

$pdo = new PDO("mysql:dbname=blog", "root","");
  $st = $pdo->query("SELECT * FROM post ORDER BY no DESC");
  $posts = $st->fetchAll();
  for ($i = 0; $i < count($posts); $i++) {
    $st = $pdo->query("SELECT * FROM comment WHERE post_no={$posts[$i]['no']} ORDER BY no DESC");
    $posts[$i]['comments'] = $st->fetchAll();
  }
  require 't_index.php';
```
はじめのブログラムでは、phpでデータベースを参照するためのPDOクラスのインスタンス作成します。
それが~new PDO~というところです。ここの部分ではデータベースとphpをつなげています。
PDOの中身でははじめにデータベースの名前を入力して、次の項目ではユーザー名とパスワードを入力します。
今回の場合、データベース名をblog,ユーザー名をroot,パスワードを無しにしています

```
 $st = $pdo->query("SELECT * FROM post ORDER BY no DESC");
```
の部分では、pdoインスタンスから->query()メソッドを呼び出してデータベースに指令を送っています。
そして、$stにはメソッドの戻り値が入ります。
命令内容はpostテーブルにあるすべてのフィールドを
noにおいて大きい順に返すように指示しています。
つまり、新しい順という意味ですね。

```
$posts = $st->fetchAll();
```

fetchAllメソッドはすべてのレコードを配列として返します。この場合だとposts[0]は最新の記事の内容となっております。

```
for ($i = 0; $i < count($posts); $i++) {
    $st = $pdo->query("SELECT * FROM comment WHERE post_no={$posts[$i]['no']} ORDER BY no DESC");
    $posts[$i]['comments'] = $st->fetchAll();
  }
```

上記の部分では、まずcounts($posts)でposts配列はどれくらいの数があるのか、調べています。それからその数分blogデータベースからcommentのフィールドすべてをnoの逆順にして返すようにしています。
つまりですね。それぞれのブログには対応したコメントが存在するため、それらをforで個別に呼び出してpost部分と対応付け用としています。

次に最初のプログラムが終わったらrequireで飛びます。

```t_index.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Special Blog</title>
<link rel="stylesheet" href="blog.css">
</head>
<body>
<h1>Special Blog</h1>
<?php foreach ($posts as $post) { ?>
  <div class="post">
    <h2><?php echo $post['title'] ?></h2>
    <p><?php echo nl2br($post['content']) ?></p>
    <?php foreach ($post['comments'] as $comment) { ?>
      <div class="comment">
        <h3><?php echo $comment['name'] ?></h3>
        <p><?php echo nl2br($comment['content']) ?></p>
      </div>
    <?php } ?>
    <p class="commment_link">
      投稿日：<?php echo $post['time'] ?>　
      <a href="comment.php?no=<?php echo $post['no'] ?>">コメント</a>
    </p>
  </div>
<?php } ?>
</body>
</html>
```

次の部分は表示部分です。
html部分の説明を省きますと。

```
<?php foreach ($posts as $post) {?>
```
では投稿されたブログをすべて表示するために、foreachでpostsの中身を一回ごとにpostに移しています。そして、$postsの数に応じて次のプログラムを行います。

```
<div class="post">
    <h2><?php echo $post['title'] ?></h2>
    <p><?php echo nl2br($post['content']) ?></p>
    <?php foreach ($post['comments'] as $comment) { ?>
      <div class="comment">
        <h3><?php echo $comment['name'] ?></h3>
        <p><?php echo nl2br($comment['content']) ?></p>
      </div>
    <?php } ?>
    <p class="commment_link">
      投稿日：<?php echo $post['time'] ?>　
      <a href="comment.php?no=<?php echo $post['no'] ?>">コメント</a>
    </p>
  </div>
```

```
<?php echo nl2br($post['content']) ?>
```
では、nl2brはcontent中に存在するテキストの改行\nを自動的に<br />に変換します。

あとの部分では、htmlに<? echo post[x]>などの表記をしてphpの変数をいいかんじにhtmlに表示していますね。
実行画面はを以下のようになります
![myhtml.png](https://qiita-image-store.s3.amazonaws.com/0/189997/4f927c69-18a9-79c8-6a56-bffa43fc76d7.png)


次はブログの投稿画面に映ります。

```post.php
<?php
  $error = $title = $content = '';
  if (@$_POST['submit']) {
    $title = $_POST['title'];
    $content = $_POST['content'];
    if (!$title) $error .= 'タイトルがありません。<br>';
    if (mb_strlen($title) > 80) $error .= 'タイトルが長すぎます。<br>';
    if (!$content) $error .= '本文がありません。<br>';
    if (!$error) {
      $pdo = new PDO("mysql:dbname=blog", "root");
      $st = $pdo->query("INSERT INTO post(title,content) VALUES('$title','$content')");
      header('Location: index.php');
      exit();
    }
  }
  require 't_post.php';
?>
```
内容としては、はじめのほうはt_post.phpがすでに実行されたのかを調べています。実行された場合、if (_POST['submit'])がtrueとなり次の処理へと移ります。
それぞれ、title,contentを$_POST配列から読み出します。それから、それらのパラメータに以上がないかifで確認しています。
そして、最後にerrorがない場合、

```
$pdo = new PDO("mysql:dbname=blog", "root");
$st = $pdo->query("INSERT INTO post(title,content) VALUES('$title','$content')");
header('Location: index.php');
exit();
```
データベースにsql文で入力されたtitleとcontentを出力せよというプログラムを出力しています。

```t_post.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>記事投稿 | Special Blog</title>
<link rel="stylesheet" href="blog.css">
</head>
<body>
<form method="post" action="post.php">
  <div class="post">
    <h2>記事投稿</h2>
    <p>題名</p>
    <p><input type="text" name="title" size="40" value="<?php echo $title ?>"></p>
    <p>本文</p>
    <p><textarea name="content" rows="8" cols="40"><?php echo $content ?></textarea></p>
    <p><input name="submit" type="submit" value="投稿"></p>
    <p><?php echo $error ?></p>
  </div>
</form>
</body>
</html>
```
こちらのほうが、formを作成して、それらの内容をpost.phpに送るためのプログラムです。


次はコメント差し込むphpプログラムです。同じくblogフォルダ内に作成しましょう。

```comment.php
<?php
  $post_no = $error = $name = $content = '';
  if (@$_POST['submit']) {
    $post_no = strip_tags($_POST['post_no']);
    $name = strip_tags($_POST['name']);
    $content = strip_tags($_POST['content']);
    if (!$name) $error .= '名前がありません。<br>';
    if (!$content) $error .= 'コメントがありません。<br>';
    if (!$error) {
      $pdo = new PDO("mysql:dbname=blog", "root");
      $st = $pdo->prepare("INSERT INTO comment(post_no,name,content) VALUES(?,?,?)");
      $st->execute(array($post_no, $name, $content));
      header('Location: index.php');
      exit();
    }
  } else {
    $post_no = strip_tags($_GET['no']);
  }
  require 't_comment.php';
?>
```

```t_comment.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>コメント投稿 | Special Blog</title>
<link rel="stylesheet" href="blog.css">
</head>
<body>
<form method="post" action="comment.php">
  <div class="post">
    <h2>コメント投稿</h2>
    <p>お名前</p>
    <p><input type="text" name="name" size="40" value="<?php echo $name ?>"></p>
    <p>コメント</p>
    <p><textarea name="content" rows="8" cols="40"><?php echo $content ?></textarea></p>
    <p>
      <input type="hidden" name="post_no" value="<?php echo $post_no ?>">
      <input name="submit" type="submit" value="投稿">
    </p>
    <p><?php echo $error ?></p>
  </div>
</form>
</body>
</html>
```

やっていることはpost.phpと同様に
ボタンおされた後？ならエラーはないかい？それならデータベースに挿入しなくちゃ！みたいなかんじだと思います笑