質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
XHTML

XHTMLは、eXtensible HyperText Markup Languageの略であり、SGMLベースであるHTMLとは違って、有効なXMLドキュメントにもなるHTMLアプリケーションです。XMLベースのツールを用いて生成されるHTMLページのためによく使われるマークアップ言語です。

PHP

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

サーバ

サーバは、 クライアントサーバモデルにおいてクライアントからの要求に対し 何らかのサービスを提供するプログラムを指す言葉です。 また、サーバーソフトウェアを稼動させているコンピュータ機器そのもののことも、 サーバーと呼ぶ場合もあります。

Q&A

解決済

1回答

1160閲覧

PHPファイルアップローダーでXHTMLを使う理由

nekora

総合スコア501

XHTML

XHTMLは、eXtensible HyperText Markup Languageの略であり、SGMLベースであるHTMLとは違って、有効なXMLドキュメントにもなるHTMLアプリケーションです。XMLベースのツールを用いて生成されるHTMLページのためによく使われるマークアップ言語です。

PHP

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

サーバ

サーバは、 クライアントサーバモデルにおいてクライアントからの要求に対し 何らかのサービスを提供するプログラムを指す言葉です。 また、サーバーソフトウェアを稼動させているコンピュータ機器そのもののことも、 サーバーと呼ぶ場合もあります。

0グッド

1クリップ

投稿2021/05/28 16:58

編集2021/05/28 17:51

やった事

参考リンクのコード例をベースにして、

ドラッグアンドドロップ、INPUTタグでの複数ファイル同時選択、DELETE機能の実装、ページャーの実装、LOADING画面での操作ロック、
DBにファイル本体の登録ではなくURLの登録にして、実ファイルをwordpressのアップローダー準拠で年度、月のフォルダに分けて格納、
BASIC認証、実ファイルフォルダのみ認証なしで外部から参照できるように実装も終えアップローダー自体は完成しました。

お聞きしたい事

しかし、
参考URLのサンプルコードでPHP内のクライアントサイドのコードがHTMLではなくXHTMLになっている理由が分かりません。

グーグル先生に、キーワードを変えて色々聞いてみたのですがHITしませんでした。
たぶんセキュリティ上の問題でXHTMLを使っているのかな?と予測しているのですが、本当のところが分かりません。

実は、当方チームリーダーの立場にあって、新人に完成したコードの説明をしなければならないのですが、
サンプルソースがこうなっていたからでは理由にならず、立つ瀬がありません。

どなたかはっきりとした理由をご存じの方、お手数ですが理由をご享受していただければ幸いです。

参考にしたURL

PHP+MySQLで簡易画像アップローダ

参考サイトのコード、実際にはDELETE機能やページャーなどを組み込み済み

PHP

1<?php 2 3/* HTML特殊文字をエスケープする関数 */ 4function h($str) { 5 return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); 6} 7 8// XHTMLとしてブラウザに認識させる 9// (IE8以下はサポート対象外w) 10header('Content-Type: application/xhtml+xml; charset=utf-8'); 11 12try { 13 14 // データベースに接続 15 $pdo = new PDO( 16 'mysql:host=localhost;dbname=imagedb;charset=utf8', 17 'root', 18 '', 19 [ 20 PDO::ATTR_EMULATE_PREPARES => false, 21 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, 22 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, 23 ] 24 ); 25 26 /* アップロードがあったとき */ 27 if (isset($_FILES['upfile']['error']) && is_int($_FILES['upfile']['error'])) { 28 29 // バッファリングを開始 30 ob_start(); 31 32 try { 33 34 // $_FILES['upfile']['error'] の値を確認 35 switch ($_FILES['upfile']['error']) { 36 case UPLOAD_ERR_OK: // OK 37 break; 38 case UPLOAD_ERR_NO_FILE: // ファイル未選択 39 throw new RuntimeException('ファイルが選択されていません', 400); 40 case UPLOAD_ERR_INI_SIZE: // php.ini定義の最大サイズ超過 41 case UPLOAD_ERR_FORM_SIZE: // フォーム定義の最大サイズ超過 42 throw new RuntimeException('ファイルサイズが大きすぎます', 400); 43 default: 44 throw new RuntimeException('その他のエラーが発生しました', 500); 45 } 46 47 // $_FILES['upfile']['mime']の値はブラウザ側で偽装可能なので 48 // MIMEタイプを自前でチェックする 49 if (!$info = @getimagesize($_FILES['upfile']['tmp_name'])) { 50 throw new RuntimeException('有効な画像ファイルを指定してください', 400); 51 } 52 if (!in_array($info[2], [IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG], true)) { 53 throw new RuntimeException('未対応の画像形式です', 400); 54 } 55 56 // サムネイルをバッファに出力 57 $create = str_replace('/', 'createfrom', $info['mime']); 58 $output = str_replace('/', '', $info['mime']); 59 if ($info[0] >= $info[1]) { 60 $dst_w = 120; 61 $dst_h = ceil(120 * $info[1] / max($info[0], 1)); 62 } else { 63 $dst_w = ceil(120 * $info[0] / max($info[1], 1)); 64 $dst_h = 120; 65 } 66 if (!$src = @$create($_FILES['upfile']['tmp_name'])) { 67 throw new RuntimeException('画像リソースの生成に失敗しました', 500); 68 } 69 $dst = imagecreatetruecolor($dst_w, $dst_h); 70 imagecopyresampled($dst, $src, 0, 0, 0, 0, $dst_w, $dst_h, $info[0], $info[1]); 71 $output($dst); 72 imagedestroy($src); 73 imagedestroy($dst); 74 75 // INSERT処理 76 $stmt = $pdo->prepare('INSERT INTO image(name,type,raw_data,thumb_data,date) VALUES(?,?,?,?,?)'); 77 $stmt->execute([ 78 $_FILES['upfile']['name'], 79 $info[2], 80 file_get_contents($_FILES['upfile']['tmp_name']), 81 ob_get_clean(), // バッファからデータを取得してクリア 82 (new DateTime('now', new DateTimeZone('Asia/Tokyo')))->format('Y-m-d H:i:s'), 83 ]); 84 85 $msgs[] = ['green', 'ファイルは正常にアップロードされました']; 86 87 } catch (RuntimeException $e) { 88 89 while (ob_get_level()) { 90 ob_end_clean(); // バッファをクリア 91 } 92 http_response_code($e instanceof PDOException ? 500 : $e->getCode()); 93 $msgs[] = ['red', $e->getMessage()]; 94 95 } 96 97 /* ID指定があったとき */ 98 } elseif (isset($_GET['id'])) { 99 100 try { 101 102 $stmt = $pdo->prepare('SELECT type, raw_data FROM image WHERE id = ? LIMIT 1'); 103 $stmt->bindValue(1, $_GET['id'], PDO::PARAM_INT); 104 $stmt->execute(); 105 if (!$row = $stmt->fetch()) { 106 throw new RuntimeException('該当する画像は存在しません', 404); 107 } 108 header('X-Content-Type-Options: nosniff'); 109 header('Content-Type: ' . image_type_to_mime_type($row['type'])); 110 echo $row['raw_data']; 111 exit; 112 113 } catch (RuntimeException $e) { 114 115 http_response_code($e instanceof PDOException ? 500 : $e->getCode()); 116 $msgs[] = ['red', $e->getMessage()]; 117 118 } 119 120 } 121 122 // サムネイル一覧取得 123 $rows = $pdo->query('SELECT id,name,type,thumb_data,date FROM image ORDER BY date DESC')->fetchAll(); 124 125} catch (PDOException $e) { 126 127 http_response_code(500); 128 $msgs[] = ['red', $e->getMessage()]; 129 130} 131 132?> 133<!DOCTYPE html> 134<html xmlns="http://www.w3.org/1999/xhtml"> 135<head> 136 <title>画像アップロード</title> 137 <style><![CDATA[ 138 fieldset { margin: 10px; } 139 legend { font-size: 12pt; } 140 img { 141 border: none; 142 float: left; 143 } 144 ]]></style> 145</head> 146<body> 147 <form enctype="multipart/form-data" method="post" action=""> 148 <fieldset> 149 <legend>画像ファイルを選択(GIF, JPEG, PNGのみ対応)</legend> 150 <input type="file" name="upfile" /><br /> 151 <input type="submit" value="送信" /> 152 </fieldset> 153 </form> 154<?php if (!empty($msgs)): ?> 155 <fieldset> 156 <legend>メッセージ</legend> 157<?php foreach ($msgs as $msg): ?> 158 <ul> 159 <li style="color:<?=h($msg[0])?>;"><?=h($msg[1])?></li> 160 </ul> 161<?php endforeach; ?> 162 </fieldset> 163<?php endif; ?> 164<?php if (!empty($rows)): ?> 165 <fieldset> 166 <legend>サムネイル一覧(クリックすると原寸大表示)</legend> 167<?php foreach ($rows as $i => $row): ?> 168<?php if ($i): ?> 169 <hr /> 170<?php endif; ?> 171 <p> 172 <?=sprintf( 173 '<a href="?id=%d"><img src="data:%s;base64,%s" alt="%s" /></a>', 174 $row['id'], 175 image_type_to_mime_type($row['type']), 176 base64_encode($row['thumb_data']), 177 h($row['name']) 178 )?><br /> 179 ファイル名: <?=h($row['name'])?><br /> 180 日付: <?=h($row['date'])?><br clear="all" /> 181 </p> 182<?php endforeach; ?> 183 </fieldset> 184<?php endif; ?> 185</body> 186</html>

参考サイトのSQL

SQL

1CREATE TABLE image( 2 `id` int UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'ID', 3 `name` varchar(255) NOT NULL COMMENT 'ファイル名', 4 `type` tinyint(2) NOT NULL COMMENT 'IMAGETYPE定数', 5 `raw_data` mediumblob NOT NULL COMMENT '原寸大データ', 6 `thumb_data` blob NOT NULL COMMENT 'サムネイルデータ', 7 `date` datetime NOT NULL COMMENT '日付' 8) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dameo

2021/05/30 05:38

xhtmlを使った理由は、記事を書いた人に聞くべきだと思います。記事のコメントを読む限りでは、本人も2016年時点ではhtmlを使ってるようですね。 個人的にxhtmlを使うメリットは、厳密なエラー判定を行える点だと思います。例えば、閉じるべきタグが閉じられてないとxhtmlではエラーになりますが、htmlではエラーになりません。例えばDOMをXPathで走査するような処理がある場合は、メリットと言えるかもしれません。 ただし、他の回答や https://ja.wikipedia.org/wiki/Extensible_HyperText_Markup_Language にあるとおり、xhtmlの開発は2009年に終わっていますので、使い続ける人はなかなかいないかもしれません。 結論としては、新人さんには不要なウンチクだと思うので、説明が面倒という話なら私であれば作り直します。その時間が惜しければ「サンプルソースがこうなっていたから」で十分だと思います。事実ですしね。
nekora

2021/05/30 05:42

アドバイス、ありがとうございます。 作り直すか、記事を書いた方に質問するか、工数の兼ね合いもあるので、明日出社したら 上司と相談の上対応したいと思います。 アドバイスありがとうございました、重ねてお礼申し上げます。
nekora

2021/05/31 22:40

返信遅くなりました、昨日掛け合って工数をもらって、HTML5で作り直して正常に動作することを確認しました。 回答の評価を+1したいので何でもいいので回答つけてくだされば、+1します。
dameo

2021/05/31 22:57

良かったですね。お気になさらず。
guest

回答1

0

ベストアンサー

2014年10月28日に HTML5 が勧告され[1]、2016年11月1日に HTML 5.1 が勧告され[2]、2017年12月14日に HTML 5.2 が勧告された[3]。

https://ja.wikipedia.org/wiki/HTML5

リンク先の記事が書かれた年月日 > 2014年10月31日に更新

参考URLのサンプルコードでPHP内のクライアントサイドのコードがHTMLではなくXHTMLになっている理由が分かりません。

記事が古いから

投稿2021/05/28 18:09

phper.k

総合スコア3923

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nekora

2021/05/28 18:21 編集

ご回答ありがとうございます。 では今のHTML5.2準拠ではXHTMLにしないでHTML5.2の記述でも問題ないということでしょうか?
phper.k

2021/05/28 18:23 編集

問題ないけど、試してみるのが一番だと思いますよ。 それに HTMLで書かれた参考サイトは全く見つかりませんか?
nekora

2021/05/28 18:27 編集

ありがとうございます。では来週出社したら試してみようと思います。 PHP ファイルアップローダーで検索するとどれもクライアントサイドはXHTMLでした。 (当方の検索の仕方に問題があったのかもしれませんが・・・) もろもろ含めて、来週試してみようと思います。
nekora

2021/05/31 22:40

返信遅くなりました、昨日掛け合って工数をもらって、HTML5で作り直して正常に動作することを確認しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問