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

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

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

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

Q&A

解決済

2回答

160閲覧

RDBの運用方法と、サーバーサイドの入力チェックの実務

maguzo

総合スコア57

PHP

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

0グッド

0クリップ

投稿2018/09/19 23:17

編集2018/09/19 23:19

例えばなのですが、現在2つのファイルが存在します。
post.php(質問ページ)
single.php(質問の閲覧ページ)

これをteratailのサービスでいえば、
マークダウンで質問をユーザーが記載し、投稿するまでのページ(post.php)があり、実際に「質問する」のボタンをクリックすると自分が質問した内容の閲覧ページ(single.php)に飛ぶ仕組みになっているかと思います。
*そもそもphpで書かれていないと思うので、例えばということなります。

post.phpで質問した内容をサーバーサイドでチェックする必要があり、これを通過した場合にはRDBへ値が格納されるとともにsingle.phpで質問内容が表示される必要があると思うのですが、このRDBへの格納運用方法とサーバーサイドでのチェック方法について実務的なアドバイスを頂きたく投稿させていただきました。

●RDBへの格納方法
求める仕様によっては一概には言えないと思うのですが、一般的にという点でアドバイスを頂ければと思います。
私の想像では投稿された質問RDBとその後の個別の閲覧ページ内の評価であったり、コメントは別のテーブルに格納されているかと思っております。
少ないテーブルで処理して(いたずらにテーブルを増やさない)運用する方法がある一方、例えば新しい質問が投稿されるたびにその閲覧ページで入力される情報を格納するためのテーブルをcreateしてそれぞれの目的別に数が多くてもテーブルを生み出していくことがどちらが適切であるのか指針はあるのでしょうか?
言い換えるのであれば、テーブルを切り分ける(上記の例でいえば、post.php内で入力される情報とsingle.php内で入力される情報を同じテーブルにするまたは異なるテーブルで処理する)境目はどのような基準で判断するのが一般的なのでしょうか?情報の持つ特性や秩序やクエリのスピード等いろいろな視点があると思うのですが、コメントをいただけると嬉しいです。

●サーバーサイドのチェック方法
例えばこの質問がサーバーサイドチェックを通ればそのまま質問の閲覧ページに飛び、皆様もそれを閲覧できる状態になると思います。この質問ページをpost.phpで皆様も閲覧できるページがsingle.phpであるとしたら、サーバーサイドチェックのコードは一般的にどこに記載されているのでしょうか?
今、私はそれをsingle.phpのトップに記載して、通過しなければもとのpost.phpにリダイレクトし、通過すればRDBにその情報を登録して、single.php上で通過した内容を表示すれば良いと思いコードを書き始めました。
そこでふと、直接single.phpを見に来る閲覧ユーザに対しても、サーバーサイトのチェックからコードが始まるため自分がやろうとしていることに疑問を感じております。single.phpに入力チェックを書くことで以下の矛盾が生じております。

投稿者

1.質問投稿ページ(post.php) → 2.閲覧ページ(single.php)でチェック → 3.閲覧ページ(single.php)で通過していればそのまま表示

閲覧者

2.閲覧ページ(single.php)でチェック → 3.閲覧ページ(single.php)で通過していればそのまま表示
そもそも閲覧者に2.のプロセスは関係がない。。

実務的に
途中でpost.phpから例えばcheck.phpのようなチェック用のファイルを用意して、通過すればsingle.phpにさらにリダイレクトするように何か一つ挟むのでしょうか、または、single.php内で投稿者なのか閲覧者なのかを判断する術があり、閲覧者であれば入力チェックをスキップするような分岐を準備して処理されるのでしょうか、それとも全く別のアプローチなのでしょうか。

基本的な内容であったり、読みづらい文章であれば誠に申し訳ございません。質問内容等不明な点があればご指摘いただければ速やかに補足や修正をさせていただきます。

何卒、よろしくお願い申し上げます。

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

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

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

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

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

m.ts10806

2018/09/19 23:28

補足しますと、teratailはPHPフレームワークCakePHPが基盤なので、基本PHPです。 >*そもそもphpで書かれていない
CHERRY

2018/09/20 00:38 編集

(余談:時々、CakePHP のエラー画面見ますよねぇ...)  データベースに関しては、まずは「データベースの正規化」をある程度理解されるほうが良いと思います。
maguzo

2018/09/20 01:10

mts10806様 コメントありがとうございます。CakePHPで書かれていたのですね!身近でPHPで書かれているウェブサイトはあまりないのかなと思っていたのですが、親近感が湧きました♪
m.ts10806

2018/09/20 01:13

まあフレームワーク使っていればその言語感はでないですしね。私の感覚ではPHPで書かれたサイトの方が多い印象です。企業サイトをWordPressで、とか多いですし。 CHERRYさん 頻発してますよね。あれでcakePHPで作られていることを知ったのは間違いないですが^^;
maguzo

2018/09/20 01:15

CHERRY様 コメント有難うございます。「データベースの正規化」という概念をおはずかしながら初めてしりました。記事もたくさんあり根本的なRDB構築の考え方が載っていました!この機会にたっぷり学んでみます♪
guest

回答2

0

ベストアンサー

確認画面を挟むかどうかで若干作り方が変わってくることもありますが、
多くは入力画面自身にPOSTし入力チェックを行い、OKであれば完了画面(または確認画面)へリダイレクト、
NGであればエラー内容と元の入力内容を初期値として入力画面を再表示だと思います。

ただ、teratailは非同期でコメントの投稿などを行っている部分も多く見られるので、AjaxでサーバーサイドへPOSTし、入力チェックでOKであれば投稿、NGであればエラー内容返却 しているところもありますね。
質問も回答もリアルタイムで入力内容がマークダウン含めて反映されますが、Ajaxで通信して変換したものを表示しているように思います。
非同期通信のリクエスト・レスポンスについてはブラウザ開発ツールの「ネットワーク」の項目である程度追えるので確認してみてください。

直接single.phpを見に来る閲覧ユーザに対しても、サーバーサイトのチェックからコードが始まるため自分がやろうとしていることに疑問を感じております。single.phpに入力チェックを書くことで以下の矛盾が生じております。

上記ですが、$_SERVER ['REQUEST_METHOD']でPOST判定を入れておけば閲覧者にはそのチェック処理を通ることはないので問題ないかと思います。
SUBMITボタンがコメント・回答・回答へのコメントなどいろいろありますが、ボタンのnameによって処理を分岐させておけば同じ処理を通らないようにはできます。
ただ、質問明細ページでは先に書きました非同期通信による入力チェック、投稿処理をしている箇所も多いので、押したボタンのイベントをそれぞれ振り分けておけば重複しないような作りにはできますね。

また、質問テーブルに投稿者IDを保存しておくようにしておけば、投稿者とそれ以外を振り分けることができますので、例えば投稿者のみに編集ボタン・ベストアンサーボタンなどを表示させたりとか、そういったことをやっているのではないでしょうか。

まあ、ミニマムを追い求めるとteratailも掲示板投稿の仕組みになるので、その掲示板投稿の仕組みの最小構成を基盤として設計を考えていくとイメージしやすくなるかもしれません。
マークダウンや非同期通信での投稿や新着通知などもあくまでやり方・見せ方の1つにすぎません。

投稿2018/09/19 23:42

m.ts10806

総合スコア80850

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

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

maguzo

2018/09/20 01:33 編集

mts10806様 詳細にご丁寧なコメントを頂き有難うございます。 ・サーバーサイドのチェックにつきまして > 閲覧側のページでチェックコードを設置する場合 $_SERVER[`REQUEST_METHOD`]でpost判定ができることを初めて知りました!大変勉強になりました。ケースによっては活用していきいたいと思います。 >投稿ページ側でチェックコードを設置する場合 "多くは入力画面自身にPOSTし入力チェックを行い、OKであれば完了画面(または確認画面)へリダイレクト、NGであればエラー内容と元の入力内容を初期値として入力画面を再表示だと思います。" とコメントいただきましたが、少しぴんと来なかった部分がございます。 掲げた例で申し上げれば、post.phpのなかにチェックコードを入れることになると思うのですが、html側のform action="XX"でリダイレクトが指定されてしまっていると思います。 1) これを無効化(JQueryでpreventDefault()等でできるのか現在調べております)してphp側に値を渡して判定した上、PHP側にリダイレクトも委ねるイメージでしょうか? 2) 仮にサーバー側で一部の値にNGが出た場合、 NGではない値は保存して、post.phpに改めてリダイレクトした上で、保存しておいたNGではない値については、サーバー側から改めて出力するというアプローチは不自然でしょうか?NGがあってリダイレクトすると全て入力された値が破棄されてしまうので、sessionやサーバーから再出力等で一部の内容の保存が一般的課と思いますが、そのアプローチも皆様がどのようにされているのか是非お伺いしたくコメントさせていただきました。 重ねてで失礼いたします。
m.ts10806

2018/09/20 02:49

>form action="XX"で 私の回答ではactionの指定先を自身に指定することをさします。つまりpost.phpというものが不要となります。 ただ自身を指定する場合は直にファイル名を書くのではなく、$_SERVERの中に自身を指定できる指定があるのでそれを使うのが望ましいです。 まあaction=""とすれば自身になるのであえて書く必要はないといえばないですが。 >1) これを無効化(JQueryでpreventDefault()等でできるのか現在調べております)してphp側に値を渡して判定した上、PHP側にリダイレクトも委ねるイメージでしょうか? 意図が汲み取れてないかもしれませんがOKだった場合のリダイレクトはphp側で良いです。 作り方次第ですが、リダイレクトをしたくなければ確認画面や完了画面にpostしてURLは確認画面や完了画面でも出ているhtmlは入力画面と同じフォームという作りもありです。 それについてはフレームワークでよく採用される"MVC"の考え方を学んでみてくださください。 ちなみにpreventDefaultはイベントを無効にするだけで、例えばsubmitを止めるとかに使いますが、それではサーバー側に送信されないので、おそらくやりたいことにはつながらないかと。 >2) あまり「保存して」というのが適切ではないとは思います。 確かに「戻る」を実装するためにセッションに保管して利用することは在りますが、あくまで一時的なものですしね。 一部でもNGということはDBへの保存処理にはいかないので、postした情報をOK、NG関わらずそのまま表示すればいいですね。 自身にpostした場合、NGがあればそもそもリダイレクトしないのでpostした情報は消えることはありません。 文でやりとりしていても実感できないと思うので、ミニマムコードで試してみては? いきなり大きなことをやろうとしても路頭に迷うだけなので、私が回答の最後の段に書いたように最小構成で掲示板システムを作って、先にコメントがあるようにDB正規化も含めて拡張していくと良いです。
maguzo

2018/09/20 03:42

コメントをいただき、ありがとうございます。 おっしゃる通り、風呂敷を広げずにシンプルな形から進めてみようと思います。 リダイレクトだけで一点だけ最後にお問い合わせさせてください。 teratailの質問投稿ページをみると「action="/questions/input"」と確かにおっしゃる通り自分自身になっております、ただ問題なく成功すると「/questions/147531」と個別のページに飛ぶ仕組みになっていると思います。この個別ページにリダイレクトさせているのはhtmlのformのアクションではないとすれば、どこで処理(サーバーサイド?)されているものと推察されるのでしょうか? ご迷惑をおかけし、申し訳ございません。
m.ts10806

2018/09/20 05:21

質問投稿したことはないのですがPHPでリダイレクトではないかと。 自身へ送信→入力チェック→OKならDBに登録し質問IDを取得→その質問IDのページへリダイレクト。 ※teratailはURLにルールがあるので質問IDさえ取得できれば非同期でPHPに渡して入力チェックから質問ID取得まで行い、その質問IDを返してJavaScriptでリダイレクトもありますけど。 ちなみにformのactionがしているのはあくまで指定先へのform情報の送信でありリダイレクトとは違います。
maguzo

2018/09/20 07:02

有難うございます。 申し訳ございません、action=redirectと思い込んでおりました。 度々お付き合いを頂き申し訳ございませんでした。 具体的な道筋をたてることができました! 改めて、御礼を申し上げます。
m.ts10806

2018/09/20 07:29

解決に向かいそうで何よりです
guest

0

●RDBへの格納方法

通常、「いたずらにテーブルを増やさない」形で運用します。データに応じて動的にテーブルを増やすのは、よほど特殊な場合(たとえば、インデックスのないBigQueryを使う場合など)に限られます。

投稿2018/09/20 00:17

maisumakun

総合スコア145183

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

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

maguzo

2018/09/20 01:17

maisumakun様 コメントありがとうございます。同じテーブル化で検索処理等をする場合、レコードが増えるほど、パフォーマンスが落ちていくものと思っていたので、出来るだけ切り分けていくべきかとも思っていましたが、なるほどです。 一つの指針として、念頭において取り組んで参ろうとおもいます。
maisumakun

2018/09/20 01:43

> レコードが増えるほど、パフォーマンスが落ちていくもの インデックスを適切に付ければ、ほぼ問題になりません(全文検索などをする場合は、それ用に構築する必要もあるかもしれませんが)。
maguzo

2018/09/20 03:44

コメントありがとうございます。インデックスを適切に付すという点を次のステップで勉強してみようと思います。お力添えに感謝いたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問