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

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

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

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

HttpWebRequest

HttpWebRequestとは.NETにおけるクラスであり、WebRequestクラスをHTTPに導入するものです。

HTTPヘッダー

Hypertext Transfer Protocol(HTTP)の中のHTTPヘッダフィールドはHTTPの要求やレスポンスの機能しているパラメーターが含まれます。その要求もしくはレスポンスライン(メッセージの最初の一行)でメッセージヘッダを作ります。

PHP

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

HTML

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

Q&A

解決済

1回答

1644閲覧

【php】なぜかプログラムが上から順番に処理されない

WeilSpinor

総合スコア170

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

HttpWebRequest

HttpWebRequestとは.NETにおけるクラスであり、WebRequestクラスをHTTPに導入するものです。

HTTPヘッダー

Hypertext Transfer Protocol(HTTP)の中のHTTPヘッダフィールドはHTTPの要求やレスポンスの機能しているパラメーターが含まれます。その要求もしくはレスポンスライン(メッセージの最初の一行)でメッセージヘッダを作ります。

PHP

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

HTML

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

0グッド

1クリップ

投稿2019/04/26 09:16

編集2019/04/27 12:45

phpで、header関数を使って別ページに飛ぶ処理をしたいのですが、うまくいきません。

より詳しくは、
header(Location:url)を複数用意し、if文を使って飛び先のページを制御しようとすると、なぜか下にあるheader(Location:url)が先に処理されてしまう
というものです。

以下のstaff_branch.phpが問題のソースコードです。
さらに下のコードstaff_list.phpは、staff_branch.phpに飛ぶ前の(情報を渡す)ページです。
(データベースへの接続コードは、個人情報記載のため省略します)

ソース内のコメントに問題点を書いたので、どこが悪いのかご回答宜しくお願いします。

環境は、Windows10/Chrome/PHP7 です。

問題のソースコード(staff_branch.php):

php

1 2<?php 3 4if(isset($_POST['edit']) === true){//editは、buttonエレメントのname 5 if(isset($_POST['staffcode']) === false){//ラジオstaffcodeが何も選択されていなければ、staff_ng.phpに飛ぶ 6 header('Location:staff_ng.php'); 7 } 8/*ラジオstaffcodeが何かしら選択されていれば、URLパラメータにstaffcodeの値を載せて、staff_edit.phpへ飛ぶ。*/ 9 10/*ラジオstaffcodeが未選択(空っぽ)なのに、なぜか、上のif文内のheaderではなく、以下のheaderが実行されてしまう*/ 11/*以下のheaderを削除すれば、上のheaderは実行される*/ 12 $staff_code=$_POST['staffcode']; 13 header('Location: staff_edit.php?staffcode='.$staff_code); 14} 15 16if(isset($_POST['delete']) === true){//deleteはボタンエレメントのname 17 if(isset($_POST['staffcode']) === false){//ラジオstaffcodeが何も選択されていなければ、staff_ng.phpに飛ぶ 18 header('Location:staff_ng.php'); 19 } 20/*ラジオstaffcodeが何かしら選択されていれば、URLパラメータにstaffcodeの値を載せて、staff_edit.phpへ飛ぶ。*/ 21/*ラジオstaffcodeが未選択(空っぽ)なのに、なぜか、上のif文内のheaderではなく、以下のheaderが実行されてしまう*/ 22/*以下のheaderを削除すれば、上のheaderは実行される*/ 23 $staff_code=$_POST['staffcode']; 24 header('Location: staff_delete.php?staffcode='.$staff_code); 25} 26?> 27

staffcode選択画面(staff_list.php)

php

1 2データベースへの接続(個人情報が記載されているので省略) 3 4<body> 5<?php 6 print('スタッフ一覧<br><br>'); 7 8 print '<form action="staff_branch.php" method="post">'; 9 while(true){ 10 $rec = $stmt -> fetch(PDO::FETCH_ASSOC);//$stmtにはデータベースのデータが格納 11 if($rec == false){ 12 break; 13 } 14 15 print '<input type="radio" name="staffcode" value="'.$rec['code'].'">'; 16 print $rec['name']; 17 print '<br>'; 18 } 19 print '<button type="submit" name="edit">修正</button>'; 20 print '<button type="submit" name="delete">削除</button>'; 21 print '</form>'; 22 }catch(Exception $e){ 23 print('ただいまサーバーに障害が発生しております。ご迷惑おかけしております。'); 24 } 25 ?> 26<\body>

###試したこと

このコードは、2013年に書かれたあるphpの本のコードをそのまま写経したものですが、
「もしかして、この本が書かれた後にPHPやHTTPの仕様に変更があったのではないか?」
と思い、マニュアルを見てみました。

すると、2006年発表のPHP5.1.2の改訂内容に「header関数」がありました。内容は以下のとおりです:

header この関数は一度に複数のヘッダを送信できないようになりました。 これは、ヘッダインジェクション攻撃への対策です。

仮にこれの意味するところが「一つのphpプログラム内で一つのheader関数しか使えない」という意味ならば、本に書かれたコードはそれに反していることになりますが、上記以上の詳細は書いておらず、こまりました 。
今回起きた「期待と異なる挙動」と照らし合わせると、おそらく、正確には以下のような内容と思われます:

「もし一つのphpプログラムに2つ以上のheader関数が書かれた場合、最後のheader関数のみが実行され、ほかのheader関数は無視される」

しかし、
・実行後になんのnoticeもエラーメッセージを出さないのは不自然。
・仕様書にちゃんとした断りが書いていない。
・7年も前の仕様変更を見落として本を書くのはさすがに著者がうかつすぎる。

といった理由から、その線は薄いと思われます。

謎です。

###追記
解答者様のご指摘により解決しました。
header関数実行後にすぐにプログラムの処理を終了してページをジャンプするには、終了したい地点にexit()の記述が必要だったようです。

写経した書籍の公式サイト調べたら、正誤表があって、
「exitが抜けていた」
とおっしゃっていました。
環境によっては期待した挙動を示すこともあるようですが、私の環境の場合は駄目だったようです。

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

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

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

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

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

guest

回答1

0

ベストアンサー

header() で値を返した後はexitをするなどして、その後のヘッダーを出力しないようにしないと、

Location: http://〜最初〜
Location: http://〜2番め〜
Location: http://〜3番め〜

がブラウザに渡されてしまいます。結果、3番目のものが処理されているのだと思います。

投稿2019/04/26 09:20

tetsunosuke

総合スコア1292

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

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

WeilSpinor

2019/04/26 09:44

ご回答ありがとうございます。 exitを追加したら期待通りに動きました。 写経した本のコードにはexitが書いてありませんでした。 著者が書き忘れたか、著者が仕様変更を知らなかったんでしょうね。 (やはり、追記で書いた2006年の5.1.2の改訂でしょうか…) 時間がかかってしまいましたが、何はともあれ解決してよかったです。
WeilSpinor

2019/04/26 10:03 編集

今いろんな技術ブログで調べてみましたが、どうやらheader関数は、読み込むとそこで処理を終了してくれるわけではなく、exitを書かない限り下に書かれた処理を続けて、完了してからジャンプするらしいですね。 そして、今回のケースは、きちんとexitを書かないと誤動作を招くケースだった、ということですね。 だとしたら、この本の作者は大変なミスを犯していますね…。今度本屋で最新版で訂正されてるかチェックしてみようと思います。 でも、今回のこのミニマルな状況で学べてよかった本当によかったです。 (今回学べなかったら、いつか大きな痛手を負っていた気がします…)
m.ts10806

2019/04/26 10:12

わざわざexitを書かなければならない実装の方がまずいかと。 書籍を責めるのはお門違いです。
young

2019/04/26 10:41

あんま読んでないけど、書籍のコードをそのまま写経したわけだから、書籍を責めてるんじゃないの?
WeilSpinor

2019/04/26 11:11

>書籍のコードをそのまま写経したわけだから そのとおりです。 今書籍の公式サイト調べたら、正誤表があって、やはりexitが抜けていたところが訂正されていました。 でもミスは付き物ですし、それが気にならないほど大変素晴らしい書籍なので、責めてはいません。 http://www.ric.co.jp/book/error/error926.html
tetsunosuke

2019/04/26 11:49

ちなみにheader関数は、Locationヘッダー以外を返したいときにも使うので、複数回呼び出しはありえるわけです。 Locationヘッダーに関する知識が十分でなかったことも今回問題になってしまった要因かもですね 実装の話で言えば、 リダイレクトはフレームワークではたいてい標準機能であるので、いつもexitするわけではないことを理解しておくのも大事かなと
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問