[PHP-users 34642] Re: phpから別のphpを実行するには?
Ryo Hayashi
ryo @ spais.jp
2009年 7月 2日 (木) 18:10:22 JST
林と申します。
> 1、掲示板の投稿を受け付けるプログラム、
> 2、投稿をデータベースに登録するプログラム、
> 3、データベースから新規10件を読み込んで表示するプログラム、
> 1,2,3と順番に実行する必要があるとします。
> このような場合、みなさんはどのようにされてますでしょうか。
> 私は、http_redirectを使っています。
2から3だけではなく、1から2へについてもリダイレクトされているのだとす
ると余り意味のない処理であると思います。
2から3に関しては認証処理などでよく使われる方法であり、リロードで重複し
た書き込みがなされてしまう事を簡単に防げるのでメリットは大きいですが、1
から2にリダイレクトをかますのはリクエストパラメータを引き回さなければな
らない分デメリットが大きいです。
2に対してのリクエストをローカルホストだけに限定するというような処理を加
えないと2に直接 POST リクエストしてしまえばいいだけになってしまいます
し、そもそも1で投稿を受け付ける意味も薄くなってしまいます(リクエストパ
ラメータの評価という意味で)
一般論と言っていいかどうかわかりませんが、glowlymoon さんの仰られる方法
に近いアプローチだと以下のようなものが挙げられます。
1.GET メソッドならばフォームを表示する
2.POST メソッドならば投稿処理を行い元のページに 302 リダイレクト
つまり1ファイルで問題ありません。
ウェブアプリケーションのほぼ全てが GET か POST メソッドでリクエストされ
ていますし、掲示板程度のアプリケーションでしたらリクエストメソッドに基づ
いて処理を行う事は不自然ではありません。
例えば CSRF を考慮してワンタイムチケットを発行し、そのトークンを hidden
要素でフォームに配置するような場合、ワンタイムチケットの評価メソッドを作
ることでも投稿処理のフックとして扱えます。
それを踏まえた上でシンプルな構成を考えると以下のような構造が考えられます。
<?php
if( ticket::valid() ){ //ワンタイムチケットの評価
if( form::valid() ){ // 入力内容の評価
model::set(); // データベースに登録
header( 'Location: http://example.com' ); // リダイレクト
}
}
// ワンタイムチケットの評価が false = 投稿ではない、もしくは不正な投稿
form::display(); // 表示するプログラム
class ticket {
function valid(){
// セッションなどに保存しておいたワンタイムチケットと、
// POST パラメータに含まれているトークンを評価して真偽値を返す
}
function issue(){
// ワンタイムチケットの発行
}
}
class form {
private
$err = array(); // エラーメッセージを貯めておく
function valid(){
// POST パラメータの入力内容評価
// 入力内容に不備があるようなら form::display() で表示するフォームに
// 表示するエラーメッセージを追加するなどの処理も行う
}
function display(){
// form::$err などを考慮して掲示板の HTML を生成する
// ここで model::get() を呼び出して繰り返し処理で
// 投稿データを表示する
}
}
class model {
function get( $page = 1, $perPage = 10 ){
// データベースから投稿データを取得する
}
function set( array $data ){
// データベースに投稿データを登録する
}
}
?>
何を以って手間とするかは人それぞれだと思いますが、少なくとも僕はプログラ
ムを書く手間よりも管理コストを優先しますので、上記のような構成になりました。
投稿データに検索機能や編集機能、削除機能などを追加したい、などといった場
合にも上記アプローチならば割りと簡単に追加実装できます。
合理的理由が無い限り「別のファイルにする」だとか「リダイレクトする」と
いったアプローチは避けた方が無難です。PHP での処理だけならばプログラムを
修正すればほとんどは対応可能ですが、ファイル構成や画面遷移は設計レベルの
話なので修正すると他に影響しやすいです。
設計レベルではなるべくシンプルにした方が、長期的に見て「プログラムを書く
手間」よりも手間がかからなくなると思います。
参考になるかどうかはわかりませんが、僕はこのようなスタイルで設計しています。
PHP-users メーリングリストの案内