質問編集履歴

4

mumumoon

mumumoon score 4

2018/08/07 18:04  投稿

続き:PHP、MySQL、HTMLを使って、画像、テキストを同時にDB保存とトップページで表示できるブログ風のようなものを作りたい。
### 前回(先週)PHP MySQL HTML を使ってブログ風のものを作っています。の続きです。
マニュアルを見ながらやっていますが、理解が中々難しくまた、躓いているので質問させていただきます。
質問の答えから教えていただいた
[[PHP]ファイルアップロードサンプル(PHP → DB → HTML)
](https://qiita.com/ShibuyaKosuke/items/dbe45cbf43bd819bf6cc)
をもとに考えながら行っていましたが、画像をDBに保存できることもあったのに、急にできなくなったり
指摘を受けたコメントを表示させる部分でforループの中でSQLを実行するのはNGということなので、JOINを使って繋いでみましたが、
表示の部分でDBから引っ張ってきて表示をするのに配列を組むべきなんだろうということはなんとなくわかったのですが、まだうまく書けずです。
画像も同じように記事に紐付けでをSQL文で、繋げて表示をするということをするべきということはなんとなくわかりましたが、コメントを表示させるのができないので、わかっていません。
### **知りたいこと**
~~・なぜ画像がDBに保存できなきなくなるのか。~~
- DBの紐付けた部分をどのように表示をすれば良いのか。コードも含め。
- 1つの記事に複数のコメント、1つの画像の付け方
初心者で勉強不足なのはわかっており、今は今までのコピペ文を読み解くようなことをしています。
何卒ご質問をお答えいただけると幸いです。
```php
<記事投稿PHP>
<?php
//DB接続  
try{  
function connect_db()  
{  
   $dsn = 'mysql:host=localhost;dbname=blog;charset=utf8';  
   $username = 'root';  
   $password = '...';  
   $options = [  
       PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION  
       , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC  
   ];  
   return new PDO($dsn, $username, $password, $options);  
}  
 
/**  
* insert  
* @param string $sql  
* @param array $arr  
* @return int lastInsertId  
*/  
function insert($sql, $arr = [])  
{  
   $pdo = connect_db();  
   $stmt = $pdo->prepare($sql);  
   $stmt->execute($arr);  
   return $pdo->lastInsertId();  
}  
 
/**  
* select  
* @param string $sql  
* @param array $arr  
* @return array $rows  
*/  
function select($sql, $arr = [])  
{  
   $pdo = connect_db();  
   $stmt = $pdo->prepare($sql);  
   $stmt->execute($arr);  
   return $stmt->fetchAll();  
}  
 
/**  
* htmlspecialchars  
* @param string $string  
* @return $string  
*/  
function h($string)  
{  
   return htmlspecialchars($string, ENT_QUOTES, 'utf-8');  
}  
 
 
//ファイルのアップロード部分
   function file_upload()
   {
   // POSTではないとき何もしない
   if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') !== 'POST') {
       return;
   }
   // アップロードファイル
   $upfile = $_FILES['upfile'];
   if (!$upfile['error'] > 0) {
       throw new Exception('ファイルアップロードに失敗しました。');
   }else{
   
   $tmp_name = $upfile['tmp_name'];
   //$tmp_name = $_FILES['upfile']['tmp_name'];
   // ファイルタイプチェック
   $finfo = finfo_open(FILEINFO_MIME_TYPE);
   $mimetype = finfo_file($finfo, $tmp_name);
   // 許可するMIMETYPE
   $allowed_types = [
       'jpg' => 'image/jpeg'
       , 'png' => 'image/png'
       , 'gif' => 'image/gif'
   ];
   if (!in_array($mimetype, $allowed_types)) {
       throw new Exception('許可されていないファイルタイプです。');
   }
   // ファイル名(ハッシュ値でファイル名を決定するため、同一ファイルは同盟で上書きされる)
   $filename = sha1_file($tmp_name);
   // 拡張子
   $ext = array_search($mimetype, $allowed_types);
   //画像の新しい名前 テキストに入力する部分
    $new_name = $_FILES['upfile']['name'];
   // 保存作ファイルパス 移動先 今回は絶対パス
   // 保存作ファイルパス 
    $destination = sprintf('/%s/%s'
       , "Users/・・・/Blog/upfiles"
       , $new_name
   );
   
   // アップロードディレクトリに移動
   if (!move_uploaded_file($tmp_name, $destination)) {
       throw new Exception('ファイルの保存に失敗しました。');
}
   // Exif 情報の削除
   $imagick = new Imagick($destination);
   $imagick->stripimage();
   $imagick->writeimage($destination);
   // データベースに登録
   $sql = 'INSERT INTO `images` (`id`, `path`) VALUES (NULL, :path) ';
   $arr = [];
   $arr[':path'] = $destination;
   $lastInsertId = insert($sql, $arr);
   
   // 成功時にページを移動する
   header(sprintf('Location: User_TopPage.php', $lastInsertId));
   
   }
   // ファイルアップロード
   file_upload();
}
} catch (Exception $e) {
   $error = $e->getMessage();
}
//タイトルと本文部分
if(isset($_POST['submit'])){
   echo '';
     $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: User_TopPage.php');
     exit();
       }
 }
?>
<!DOCTYPE html>
<html lang="ja">
   <head>
       <meta charset="utf-8">
       <title>記事投稿</title>
       <link rel="stylesheet" href="blog.css">
   </head>
<body>
   <form method="post" action=""enctype="multipart/form-data">
       <div class="posting">
           <h2>記事投稿</h2>
           <p>題名</p>
           <p><input name="title" type="text" size="40"></p>
           <p>本文</p>
           <p><textarea name="content" rows="8" cols="40"></textarea></p>
           <p><label for="upfile">画像ファイル</label>
           <input type="file" name="upfile" id="upfile" /></p>
           <input name="submit" type="submit" value="投稿">
   </form>
           <p><input type="button" onclick="window.history.back('http://localhost/Blog/User_TopPage.php');" value="戻る"></p>
           <p><?php echo $error ?></p>
       </div>
</body>
</html>
```
```PHP
<User_TopPage>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>TEST Blog</title>
<link rel="stylesheet" type="text/css" href="blog.css">
</head>
<body>
   <a href="User_TopPage.php"><label class="toptest"><h1>TEST Blog</h1></label></a>
<a href="t_post.php"><label class="contentTop"><h4>記事作成</h4></label></a>
<a href="Logout.php"><label class="Logout"><h5>ログアウト</h5></label></a>
</body>
</html>
<?php
 $pdo = new PDO("mysql:dbname=blog", "root","...",[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
 
 //tableの全部(*)を記事番号の大きい順、すなわち新しい記事から順番に並び替えられる
 //fetchAllメソッドは、全てのレコードを配列として返します。$posts[0]に最も新しい記事、$posts[1]に次の記事…と順番に入ります
 $stmt = $pdo->prepare("SELECT * FROM post ORDER BY no DESC");
 $stmt->execute();
 $posts = $stmt->fetchAll();
$sql =
"CREATE VIEW
 blogview
 ( 
   no,
   title,
   content,
   time,
   path,
   name,
   comment 
   
 )
AS
 SELECT
   post.no,
   post.title,
   post.content,
   post.time,
   images.path,
   comment.name,
   comment.comment
 FROM
   post AS post
   LEFT JOIN
   comment AS comment
   ON
   post.no = comment.post_no
   LEFT JOIN
   images AS images
   ON
   post.time = images.time"
   ;
 $blogview['comments'] = $stmt->fetchAll();
 $stmt->execute();
$sql = 'SELECT `no`, `path` FROM `blogview`ORDER BY no DESC';
$result = $pdo->query($sql);
//for ループの中でSQLを実行するのはNGです。JOINを使ってテーブルを連結し、SQLの発行回数を一回で住むようにしよう (質問部分)
 // 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
<表示部分>
<?php
$pdo = new PDO("mysql:dbname=blog", "root","…",[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>TEST Blog</title>
<link rel="stylesheet" href="blog.css">
</head>
<body>
<?php foreach ($posts as $post) { ?>
 <div class="post">
   <h2><?php echo $post['title'] ?></h2> 
   <p><?php echo nl2br($post['content']) ?></p>
   
<!-- image -->
<?php foreach ($result as $row) { ?>
     <div class="iamges">
     <?php echo '<img src="'.$row['path'];?>
     </div>
   <?php } ?>
<!-- コメント部分 -->
   <?php foreach ($blogviews['comments'] as $blogview) { ?>
     <div class="comment">
       <h3><?php echo $blogview['name'] ?></h3>
       <p><?php echo nl2br($blogview['comment']) ?></p>
       <!-- <p>>?php echo ($) -->
     </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>
```
### 変更点
imagesのテーブル構造です。
![](f5d0a1e1bbb3a4cdbb6b60011a3d898e.png)
・なぜ画像がDBに保存できなきなくなるのか。 はもう一度書き直したところ、Permissionエラーが出たので、ファイルの権限を変えたらDB内に保存できるようになりました。
また、今回は練習も含めなので絶対パスにしたところもあります。
- なぜ画像がDBに保存できなきなくなるのか。 はもう一度書き直したところ、Permissionエラーが出たので、ファイルの権限を変えたらDB内に保存できるようになりました。
###変更点2
CREATE viewで作成したものです。
これを使ってコメントと画像を上手くtitle,conetnt を使って表示させようとしているところです。
![](66b11231070066acf736c466463f9637.png)
---
User_TopPageの部分に
```PHP
$blogview['comments'] = $stmt->fetchAll();
 $stmt->execute();
$sql = 'SELECT `no`, `path` FROM `blogview`ORDER BY no DESC';
$result = $pdo->query($sql);
```
表示部分のところにimgタグを入れました。
```PHP
<?php foreach ($result as $row) { ?>
     <div class="iamges">
     <?php echo '<img src="'.$row['path'];?>
     </div>
   <?php } ?>
 
```
この2つを追加したところ
![](dd1e883d367f94ce7033a6cf59a985e6.png)
このような地獄絵図になりました。
このような地獄絵図になりました。
---
```
- path部分は(pathについて理解はあまりできていません)
   ```php
//画像の新しい名前 テキストに入力する部分
    $new_name = $_FILES['upfile']['name'];
   // 保存作ファイルパス 
    $destination = sprintf('/%s/%s'
       , "Users/・・・/Blog/upfiles"
       , $new_name
   );
```
  • PHP

    23999 questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • HTML

    11459 questions

    HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

  • phpMyAdmin

    805 questions

    phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

3 変更点記載しました。

mumumoon

mumumoon score 4

2018/07/31 20:19  投稿

続き:PHP、MySQL、HTMLを使って、画像、テキストを同時にDB保存とトップページで表示できるブログ風のようなものを作りたい。
### 前回(先週)PHP MySQL HTML を使ってブログ風のものを作っています。の続きです。
マニュアルを見ながらやっていますが、理解が中々難しくまた、躓いているので質問させていただきます。
質問の答えから教えていただいた
[[PHP]ファイルアップロードサンプル(PHP → DB → HTML)
](https://qiita.com/ShibuyaKosuke/items/dbe45cbf43bd819bf6cc)
をもとに考えながら行っていましたが、画像をDBに保存できることもあったのに、急にできなくなったり
指摘を受けたコメントを表示させる部分でforループの中でSQLを実行するのはNGということなので、JOINを使って繋いでみましたが、
表示の部分でDBから引っ張ってきて表示をするのに配列を組むべきなんだろうということはなんとなくわかったのですが、まだうまく書けずです。
画像も同じように記事に紐付けでをSQL文で、繋げて表示をするということをするべきということはなんとなくわかりましたが、コメントを表示させるのができないので、わかっていません。
**知りたいこと**
### **知りたいこと**
~~・なぜ画像がDBに保存できなきなくなるのか。~~
・DBの紐付けた部分をどのように表示をすれば良いのか。コードも含め。
- DBの紐付けた部分をどのように表示をすれば良いのか。コードも含め。
- 1つの記事に複数のコメント、1つの画像の付け方
初心者で勉強不足なのはわかっており、今は今までのコピペ文を読み解くようなことをしています。
何卒ご質問をお答えいただけると幸いです。
```php
<記事投稿PHP>
<?php
//DB接続
try{
function connect_db()
{
   $dsn = 'mysql:host=localhost;dbname=blog;charset=utf8';
   $username = 'root';
   $password = '...';
   $options = [
       PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
       , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
   ];
   return new PDO($dsn, $username, $password, $options);
}
/**
* insert
* @param string $sql
* @param array $arr
* @return int lastInsertId
*/
function insert($sql, $arr = [])
{
   $pdo = connect_db();
   $stmt = $pdo->prepare($sql);
   $stmt->execute($arr);
   return $pdo->lastInsertId();
}
/**
* select
* @param string $sql
* @param array $arr
* @return array $rows
*/
function select($sql, $arr = [])
{
   $pdo = connect_db();
   $stmt = $pdo->prepare($sql);
   $stmt->execute($arr);
   return $stmt->fetchAll();
}
/**
* htmlspecialchars
* @param string $string
* @return $string
*/
function h($string)
{
   return htmlspecialchars($string, ENT_QUOTES, 'utf-8');
}
//ファイルのアップロード部分
   function file_upload()
   {
   // POSTではないとき何もしない
   if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') !== 'POST') {
       return;
   }
   // アップロードファイル
   $upfile = $_FILES['upfile'];
   if (!$upfile['error'] > 0) {
       throw new Exception('ファイルアップロードに失敗しました。');
   }else{
   
   $tmp_name = $upfile['tmp_name'];
   //$tmp_name = $_FILES['upfile']['tmp_name'];
   // ファイルタイプチェック
   $finfo = finfo_open(FILEINFO_MIME_TYPE);
   $mimetype = finfo_file($finfo, $tmp_name);
   // 許可するMIMETYPE
   $allowed_types = [
       'jpg' => 'image/jpeg'
       , 'png' => 'image/png'
       , 'gif' => 'image/gif'
   ];
   if (!in_array($mimetype, $allowed_types)) {
       throw new Exception('許可されていないファイルタイプです。');
   }
   // ファイル名(ハッシュ値でファイル名を決定するため、同一ファイルは同盟で上書きされる)
   $filename = sha1_file($tmp_name);
   // 拡張子
   $ext = array_search($mimetype, $allowed_types);
   //画像の新しい名前 テキストに入力する部分
    $new_name = $_FILES['upfile']['name'];
   // 保存作ファイルパス 移動先
    $destination = sprintf('./%s.%s'
       , 'upfiles'
       , $new_name
       
   // 保存作ファイルパス 移動先 今回は絶対パス
    $destination = sprintf('/%s/%s'
       , "Users/・・・/Blog/upfiles"
       , $new_name
   );
   //上手くいかない。画像ファイルはなぜかBlogの中に保存される。権限も_wwwにしないとだめ  
   
   // アップロードディレクトリに移動
   if (!move_uploaded_file($tmp_name, $destination)) {
       throw new Exception('ファイルの保存に失敗しました。');
}
   // Exif 情報の削除
   $imagick = new Imagick($destination);
   $imagick->stripimage();
   $imagick->writeimage($destination);
   // データベースに登録
   $sql = 'INSERT INTO `images` (`id`, `path`) VALUES (NULL, :path) ';
   $arr = [];
   $arr[':path'] = $destination;
   $lastInsertId = insert($sql, $arr);
   
   // 成功時にページを移動する
   header(sprintf('Location: User_TopPage.php', $lastInsertId));
   
   }
   // ファイルアップロード
   file_upload();
}
} catch (Exception $e) {
   $error = $e->getMessage();
}
//タイトルと本文部分
if(isset($_POST['submit'])){
   echo '';
     $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: User_TopPage.php');
     exit();
       }
 }
?>
<!DOCTYPE html>
<html lang="ja">
   <head>
       <meta charset="utf-8">
       <title>記事投稿</title>
       <link rel="stylesheet" href="blog.css">
   </head>
<body>
   <form method="post" action=""enctype="multipart/form-data">
       <div class="posting">
           <h2>記事投稿</h2>
           <p>題名</p>
           <p><input name="title" type="text" size="40"></p>
           <p>本文</p>
           <p><textarea name="content" rows="8" cols="40"></textarea></p>
           <p><label for="upfile">画像ファイル</label>
           <input type="file" name="upfile" id="upfile" /></p>
           <input name="submit" type="submit" value="投稿">
   </form>
           <p><input type="button" onclick="window.history.back('http://localhost/Blog/User_TopPage.php');" value="戻る"></p>
           <p><?php echo $error ?></p>
       </div>
</body>
</html>
```
```PHP
<User_TopPage>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>TEST Blog</title>
<link rel="stylesheet" type="text/css" href="blog.css">
</head>
<body>
   <a href="User_TopPage.php"><label class="toptest"><h1>TEST Blog</h1></label></a>
<a href="t_post.php"><label class="contentTop"><h4>記事作成</h4></label></a>
<a href="Logout.php"><label class="Logout"><h5>ログアウト</h5></label></a>
</body>
</html>
<?php
 $pdo = new PDO("mysql:dbname=blog", "root","...",[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
 
 //tableの全部(*)を記事番号の大きい順、すなわち新しい記事から順番に並び替えられる
 //fetchAllメソッドは、全てのレコードを配列として返します。$posts[0]に最も新しい記事、$posts[1]に次の記事…と順番に入ります
 $stmt = $pdo->prepare("SELECT * FROM post ORDER BY no DESC");
 $stmt->execute();
 $posts = $stmt->fetchAll();
$sql =
"CREATE VIEW
 blogview
 ( 
   no,
   title,
   content,
   time,
   path,
   name,
   comment 
   
 )
AS
 SELECT
   post.no,
   post.title,
   post.content,
   post.time,
   images.path,
   comment.name,
   comment.comment
 FROM
   post AS post
   LEFT JOIN
   comment AS comment
   ON
   post.no = comment.post_no
   LEFT JOIN
   images AS images
   ON
   post.time = images.time"
   ;
 $stmt = $pdo->prepare("SELECT post.no, comment.post_no FROM post LEFT OUTER JOIN comment ON post.no = comment.post_no");
 $blogview['comments'] = $stmt->fetchAll();
 $stmt->execute();
$sql = 'SELECT `no`, `path` FROM `blogview`ORDER BY no DESC';  
$result = $pdo->query($sql);  
//for ループの中でSQLを実行するのはNGです。JOINを使ってテーブルを連結し、SQLの発行回数を一回で住むようにしよう (質問部分)
 // 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
<表示部分>
<?php
$pdo = new PDO("mysql:dbname=blog", "root","…",[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>TEST Blog</title>
<link rel="stylesheet" href="blog.css">
</head>
<body>
<?php foreach ($posts as $post) { ?>
 <div class="post">
   <h2><?php echo $post['title'] ?></h2> 
   <p><?php echo nl2br($post['content']) ?></p>
   
<!-- image -->  
<?php foreach ($result as $row) { ?>  
     <div class="iamges">  
     <?php echo '<img src="'.$row['path'];?>  
     </div>  
   <?php } ?>  
<!-- コメント部分 -->
   <?php foreach ($blogview['comments'] as $blogview) { ?>
   <?php foreach ($blogviews['comments'] as $blogview) { ?>
     <div class="comment">
       <h3><?php echo $blogview['name'] ?></h3>
       <p><?php echo nl2br($blogview['comment']) ?></p>
       <!-- <p>>?php echo ($) -->
     </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>
```
### 変更点
imagesのテーブル構造です。
![](f5d0a1e1bbb3a4cdbb6b60011a3d898e.png)
・なぜ画像がDBに保存できなきなくなるのか。 はもう一度書き直したところ、Permissionエラーが出たので、ファイルの権限を変えたらDB内に保存できるようになりました。
・なぜ画像がDBに保存できなきなくなるのか。 はもう一度書き直したところ、Permissionエラーが出たので、ファイルの権限を変えたらDB内に保存できるようになりました。
また、今回は練習も含めなので絶対パスにしたところもあります。
###変更点2
CREATE viewで作成したものです。
これを使ってコメントと画像を上手くtitle,conetnt を使って表示させようとしているところです。
![](66b11231070066acf736c466463f9637.png)
---
User_TopPageの部分に
```PHP
$blogview['comments'] = $stmt->fetchAll();
 $stmt->execute();
$sql = 'SELECT `no`, `path` FROM `blogview`ORDER BY no DESC';
$result = $pdo->query($sql);
```
表示部分のところにimgタグを入れました。
```PHP
<?php foreach ($result as $row) { ?>
     <div class="iamges">
     <?php echo '<img src="'.$row['path'];?>
     </div>
   <?php } ?>
```
この2つを追加したところ
![](dd1e883d367f94ce7033a6cf59a985e6.png)
このような地獄絵図になりました。
  • PHP

    23999 questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • HTML

    11459 questions

    HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

  • phpMyAdmin

    805 questions

    phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

2 変更点を追記させていただきました。

mumumoon

mumumoon score 4

2018/07/31 10:53  投稿

続き:PHP、MySQL、HTMLを使って、画像、テキストを同時にDB保存とトップページで表示できるブログ風のようなものを作りたい。
### 前回(先週)PHP MySQL HTML を使ってブログ風のものを作っています。の続きです。
マニュアルを見ながらやっていますが、理解が中々難しくまた、躓いているので質問させていただきます。
質問の答えから教えていただいた
[[PHP]ファイルアップロードサンプル(PHP → DB → HTML)
](https://qiita.com/ShibuyaKosuke/items/dbe45cbf43bd819bf6cc)
をもとに考えながら行っていましたが、画像をDBに保存できることもあったのに、急にできなくなったり
指摘を受けたコメントを表示させる部分でforループの中でSQLを実行するのはNGということなので、JOINを使って繋いでみましたが、
表示の部分でDBから引っ張ってきて表示をするのに配列を組むべきなんだろうということはなんとなくわかったのですが、まだうまく書けずです。
画像も同じように記事に紐付けでをSQL文で、繋げて表示をするということをするべきということはなんとなくわかりましたが、コメントを表示させるのができないので、わかっていません。
**知りたいこと**
・なぜ画像がDBに保存できなきなくなるのか。
~~・なぜ画像がDBに保存できなきなくなるのか。~~
・DBの紐付けた部分をどのように表示をすれば良いのか。コードも含め。
初心者で勉強不足なのはわかっており、今は今までのコピペ文を読み解くようなことをしています。
何卒ご質問をお答えいただけると幸いです。
```php
<記事投稿PHP>
<?php
//DB接続
try{
function connect_db()
{
   $dsn = 'mysql:host=localhost;dbname=blog;charset=utf8';
   $username = 'root';
   $password = '...';
   $options = [
       PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
       , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
   ];
   return new PDO($dsn, $username, $password, $options);
}
/**
* insert
* @param string $sql
* @param array $arr
* @return int lastInsertId
*/
function insert($sql, $arr = [])
{
   $pdo = connect_db();
   $stmt = $pdo->prepare($sql);
   $stmt->execute($arr);
   return $pdo->lastInsertId();
}
/**
* select
* @param string $sql
* @param array $arr
* @return array $rows
*/
function select($sql, $arr = [])
{
   $pdo = connect_db();
   $stmt = $pdo->prepare($sql);
   $stmt->execute($arr);
   return $stmt->fetchAll();
}
/**
* htmlspecialchars
* @param string $string
* @return $string
*/
function h($string)
{
   return htmlspecialchars($string, ENT_QUOTES, 'utf-8');
}
//ファイルのアップロード部分
   function file_upload()
   {
   // POSTではないとき何もしない
   if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') !== 'POST') {
       return;
   }
   // アップロードファイル
   $upfile = $_FILES['upfile'];
   if (!$upfile['error'] > 0) {
       throw new Exception('ファイルアップロードに失敗しました。');
   }else{
   
   $tmp_name = $upfile['tmp_name'];
   //$tmp_name = $_FILES['upfile']['tmp_name'];
   // ファイルタイプチェック
   $finfo = finfo_open(FILEINFO_MIME_TYPE);
   $mimetype = finfo_file($finfo, $tmp_name);
   // 許可するMIMETYPE
   $allowed_types = [
       'jpg' => 'image/jpeg'
       , 'png' => 'image/png'
       , 'gif' => 'image/gif'
   ];
   if (!in_array($mimetype, $allowed_types)) {
       throw new Exception('許可されていないファイルタイプです。');
   }
   // ファイル名(ハッシュ値でファイル名を決定するため、同一ファイルは同盟で上書きされる)
   $filename = sha1_file($tmp_name);
   // 拡張子
   $ext = array_search($mimetype, $allowed_types);
   //画像の新しい名前 テキストに入力する部分
    $new_name = $_FILES['upfile']['name'];
   // 保存作ファイルパス 移動先
    $destination = sprintf('./%s.%s'
       , 'upfiles'
       , $new_name
       
   );
   //上手くいかない。画像ファイルはなぜかBlogの中に保存される。権限も_wwwにしないとだめ
   
   // アップロードディレクトリに移動
   if (!move_uploaded_file($tmp_name, $destination)) {
       throw new Exception('ファイルの保存に失敗しました。');
}
   // Exif 情報の削除
   $imagick = new Imagick($destination);
   $imagick->stripimage();
   $imagick->writeimage($destination);
   // データベースに登録
   $sql = 'INSERT INTO `images` (`id`, `path`) VALUES (NULL, :path) ';
   $arr = [];
   $arr[':path'] = $destination;
   $lastInsertId = insert($sql, $arr);
   
   // 成功時にページを移動する
   header(sprintf('Location: User_TopPage.php', $lastInsertId));
   
   }
   // ファイルアップロード
   file_upload();
}
} catch (Exception $e) {
   $error = $e->getMessage();
}
//タイトルと本文部分
if(isset($_POST['submit'])){
   echo '';
     $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: User_TopPage.php');
     exit();
       }
 }
?>
<!DOCTYPE html>
<html lang="ja">
   <head>
       <meta charset="utf-8">
       <title>記事投稿</title>
       <link rel="stylesheet" href="blog.css">
   </head>
<body>
   <form method="post" action=""enctype="multipart/form-data">
       <div class="posting">
           <h2>記事投稿</h2>
           <p>題名</p>
           <p><input name="title" type="text" size="40"></p>
           <p>本文</p>
           <p><textarea name="content" rows="8" cols="40"></textarea></p>
           <p><label for="upfile">画像ファイル</label>
           <input type="file" name="upfile" id="upfile" /></p>
           <input name="submit" type="submit" value="投稿">
   </form>
           <p><input type="button" onclick="window.history.back('http://localhost/Blog/User_TopPage.php');" value="戻る"></p>
           <p><?php echo $error ?></p>
       </div>
</body>
</html>
```
```PHP
<User_TopPage>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>TEST Blog</title>
<link rel="stylesheet" type="text/css" href="blog.css">
</head>
<body>
   <a href="User_TopPage.php"><label class="toptest"><h1>TEST Blog</h1></label></a>
<a href="t_post.php"><label class="contentTop"><h4>記事作成</h4></label></a>
<a href="Logout.php"><label class="Logout"><h5>ログアウト</h5></label></a>
</body>
</html>
<?php
 $pdo = new PDO("mysql:dbname=blog", "root","...",[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
 
 //tableの全部(*)を記事番号の大きい順、すなわち新しい記事から順番に並び替えられる
 //fetchAllメソッドは、全てのレコードを配列として返します。$posts[0]に最も新しい記事、$posts[1]に次の記事…と順番に入ります
 $stmt = $pdo->prepare("SELECT * FROM post ORDER BY no DESC");
 $stmt->execute();
 $posts = $stmt->fetchAll();
$sql =
"CREATE VIEW
 blogview
 ( 
   no,
   title,
   content,
   time,
   path,
   name,
   comment 
   
 )
AS
 SELECT
   post.no,
   post.title,
   post.content,
   post.time,
   images.path,
   comment.name,
   comment.comment
 FROM
   post AS post
   LEFT JOIN
   comment AS comment
   ON
   post.no = comment.post_no
   LEFT JOIN
   images AS images
   ON
   post.time = images.time"
   ;
 $stmt = $pdo->prepare("SELECT post.no, comment.post_no FROM post LEFT OUTER JOIN comment ON post.no = comment.post_no");
 $blogview['comments'] = $stmt->fetchAll();
 $stmt->execute();
//for ループの中でSQLを実行するのはNGです。JOINを使ってテーブルを連結し、SQLの発行回数を一回で住むようにしよう (質問部分)
 // 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
<表示部分>
<?php
$pdo = new PDO("mysql:dbname=blog", "root","…",[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>TEST Blog</title>
<link rel="stylesheet" href="blog.css">
</head>
<body>
<?php foreach ($posts as $post) { ?>
 <div class="post">
   <h2><?php echo $post['title'] ?></h2> 
   <p><?php echo nl2br($post['content']) ?></p>
   
<!-- コメント部分 -->
   <?php foreach ($blogview['comments'] as $blogview) { ?>
     <div class="comment">
       <h3><?php echo $blogview['name'] ?></h3>
       <p><?php echo nl2br($blogview['comment']) ?></p>
       <!-- <p>>?php echo ($) -->
     </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>
```
### 変更点  
 
imagesのテーブル構造です。
![](f5d0a1e1bbb3a4cdbb6b60011a3d898e.png)
![](f5d0a1e1bbb3a4cdbb6b60011a3d898e.png)
・なぜ画像がDBに保存できなきなくなるのか。 はもう一度書き直したところ、Permissionエラーが出たので、ファイルの権限を変えたらDB内に保存できるようになりました。
  • PHP

    23999 questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • HTML

    11459 questions

    HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

  • phpMyAdmin

    805 questions

    phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

1 User_TopPageの中に追加したSQL文、その下のPDO->prepare文と表示部分のコメント部分を修正しました。がコメントの表示と画像の表示、保存は現在解決は未解決なので試行錯誤中です。

mumumoon

mumumoon score 4

2018/07/30 17:03  投稿

### 前回(先週)PHP MySQL HTML を使ってブログ風のものを作っています。の続きです。
マニュアルを見ながらやっていますが、理解が中々難しくまた、躓いているので質問させていただきます。
質問の答えから教えていただいた
[[PHP]ファイルアップロードサンプル(PHP → DB → HTML)
](https://qiita.com/ShibuyaKosuke/items/dbe45cbf43bd819bf6cc)
をもとに考えながら行っていましたが、画像をDBに保存できることもあったのに、急にできなくなったり
指摘を受けたコメントを表示させる部分でforループの中でSQLを実行するのはNGということなので、JOINを使って繋いでみましたが、
表示の部分でDBから引っ張ってきて表示をするのに配列を組むべきなんだろうということはなんとなくわかったのですが、まだうまく書けずです。
画像も同じように記事に紐付けでをSQL文で、繋げて表示をするということをするべきということはなんとなくわかりましたが、コメントを表示させるのができないので、わかっていません。
**知りたいこと**
・なぜ画像がDBに保存できなきなくなるのか。
・DBの紐付けた部分をどのように表示をすれば良いのか。コードも含め。
初心者で勉強不足なのはわかっており、今は今までのコピペ文を読み解くようなことをしています。
何卒ご質問をお答えいただけると幸いです。
```php
<記事投稿PHP>
<?php
//DB接続
try{
function connect_db()
{
   $dsn = 'mysql:host=localhost;dbname=blog;charset=utf8';
   $username = 'root';
   $password = '...';
   $options = [
       PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
       , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
   ];
   return new PDO($dsn, $username, $password, $options);
}
/**
* insert
* @param string $sql
* @param array $arr
* @return int lastInsertId
*/
function insert($sql, $arr = [])
{
   $pdo = connect_db();
   $stmt = $pdo->prepare($sql);
   $stmt->execute($arr);
   return $pdo->lastInsertId();
}
/**
* select
* @param string $sql
* @param array $arr
* @return array $rows
*/
function select($sql, $arr = [])
{
   $pdo = connect_db();
   $stmt = $pdo->prepare($sql);
   $stmt->execute($arr);
   return $stmt->fetchAll();
}
/**
* htmlspecialchars
* @param string $string
* @return $string
*/
function h($string)
{
   return htmlspecialchars($string, ENT_QUOTES, 'utf-8');
}
//ファイルのアップロード部分
   function file_upload()
   {
   // POSTではないとき何もしない
   if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') !== 'POST') {
       return;
   }
   // アップロードファイル
   $upfile = $_FILES['upfile'];
   if (!$upfile['error'] > 0) {
       throw new Exception('ファイルアップロードに失敗しました。');
   }else{
   
   $tmp_name = $upfile['tmp_name'];
   //$tmp_name = $_FILES['upfile']['tmp_name'];
   // ファイルタイプチェック
   $finfo = finfo_open(FILEINFO_MIME_TYPE);
   $mimetype = finfo_file($finfo, $tmp_name);
   // 許可するMIMETYPE
   $allowed_types = [
       'jpg' => 'image/jpeg'
       , 'png' => 'image/png'
       , 'gif' => 'image/gif'
   ];
   if (!in_array($mimetype, $allowed_types)) {
       throw new Exception('許可されていないファイルタイプです。');
   }
   // ファイル名(ハッシュ値でファイル名を決定するため、同一ファイルは同盟で上書きされる)
   $filename = sha1_file($tmp_name);
   // 拡張子
   $ext = array_search($mimetype, $allowed_types);
   //画像の新しい名前 テキストに入力する部分
    $new_name = $_FILES['upfile']['name'];
   // 保存作ファイルパス 移動先
    $destination = sprintf('./%s.%s'
       , 'upfiles'
       , $new_name
       
   );
   //上手くいかない。画像ファイルはなぜかBlogの中に保存される。権限も_wwwにしないとだめ
   
   // アップロードディレクトリに移動
   if (!move_uploaded_file($tmp_name, $destination)) {
       throw new Exception('ファイルの保存に失敗しました。');
}
   // Exif 情報の削除
   $imagick = new Imagick($destination);
   $imagick->stripimage();
   $imagick->writeimage($destination);
   // データベースに登録
   $sql = 'INSERT INTO `images` (`id`, `path`) VALUES (NULL, :path) ';
   $arr = [];
   $arr[':path'] = $destination;
   $lastInsertId = insert($sql, $arr);
   
   // 成功時にページを移動する
   header(sprintf('Location: User_TopPage.php', $lastInsertId));
   
   }
   // ファイルアップロード
   file_upload();
}
} catch (Exception $e) {
   $error = $e->getMessage();
}
//タイトルと本文部分
if(isset($_POST['submit'])){
   echo '';
     $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: User_TopPage.php');
     exit();
       }
 }
?>
<!DOCTYPE html>
<html lang="ja">
   <head>
       <meta charset="utf-8">
       <title>記事投稿</title>
       <link rel="stylesheet" href="blog.css">
   </head>
<body>
   <form method="post" action=""enctype="multipart/form-data">
       <div class="posting">
           <h2>記事投稿</h2>
           <p>題名</p>
           <p><input name="title" type="text" size="40"></p>
           <p>本文</p>
           <p><textarea name="content" rows="8" cols="40"></textarea></p>
           <p><label for="upfile">画像ファイル</label>
           <input type="file" name="upfile" id="upfile" /></p>
           <input name="submit" type="submit" value="投稿">
   </form>
           <p><input type="button" onclick="window.history.back('http://localhost/Blog/User_TopPage.php');" value="戻る"></p>
           <p><?php echo $error ?></p>
       </div>
</body>
</html>
```
```PHP
<User_TopPage>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>TEST Blog</title>
<link rel="stylesheet" type="text/css" href="blog.css">
</head>
<body>
   <a href="User_TopPage.php"><label class="toptest"><h1>TEST Blog</h1></label></a>
<a href="t_post.php"><label class="contentTop"><h4>記事作成</h4></label></a>
<a href="Logout.php"><label class="Logout"><h5>ログアウト</h5></label></a>
</body>
</html>
<?php
 $pdo = new PDO("mysql:dbname=blog", "root","...",[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
 
 //tableの全部(*)を記事番号の大きい順、すなわち新しい記事から順番に並び替えられる
 //fetchAllメソッドは、全てのレコードを配列として返します。$posts[0]に最も新しい記事、$posts[1]に次の記事…と順番に入ります
 $stmt = $pdo->prepare("SELECT * FROM post ORDER BY no DESC");
 $stmt->execute();
 $posts = $stmt->fetchAll();
 $stmt = $pdo->prepare("SELECT post.no, comment.post_no FROM post RIGHT OUTER JOIN comment ON post.no = comment.post_no");
 $posts['comments'] = $stmt->fetchAll();
$sql =
"CREATE VIEW
 blogview
 ( 
   no,
   title,
   content,
   time,
   path,
   name,
   comment 
   
 )
AS
 SELECT
   post.no,
   post.title,
   post.content,
   post.time,
   images.path,
   comment.name,
   comment.comment
 FROM
   post AS post
   LEFT JOIN
   comment AS comment
   ON
   post.no = comment.post_no
   LEFT JOIN
   images AS images
   ON
   post.time = images.time"
   ;
 $stmt = $pdo->prepare("SELECT post.no, comment.post_no FROM post LEFT OUTER JOIN comment ON post.no = comment.post_no");
 $blogview['comments'] = $stmt->fetchAll();
 $stmt->execute();
//for ループの中でSQLを実行するのはNGです。JOINを使ってテーブルを連結し、SQLの発行回数を一回で住むようにしよう (質問部分)
 // 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
<表示部分>
 
<?php
$pdo = new PDO("mysql:dbname=blog", "root","…",[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>TEST Blog</title>
<link rel="stylesheet" href="blog.css">
</head>
<body>
<?php foreach ($posts as $post) { ?>
 <div class="post">
   <h2><?php echo $post['title'] ?></h2> 
   <p><?php echo nl2br($post['content']) ?></p>
   
   <!--<?php //foreach ?>
    <div class="image">
     <a></a> 画像挿入場所-->
   <!-- コメント部分 -->
   <?php foreach ($post['comments'] as $comment) { ?>
<!-- コメント部分 -->
   <?php foreach ($blogview['comments'] as $blogview) { ?>
     <div class="comment">
       <h3><?php echo $comment['name'] ?></h3>
       <p><?php echo nl2br($comment['content']) ?></p>
       <h3><?php echo $blogview['name'] ?></h3>
       <p><?php echo nl2br($blogview['comment']) ?></p>
       <!-- <p>>?php echo ($) -->
     </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>
```
```
imagesのテーブル構造です。
![](f5d0a1e1bbb3a4cdbb6b60011a3d898e.png)
  • PHP

    23999 questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • HTML

    11459 questions

    HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

  • phpMyAdmin

    805 questions

    phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る