http://q.hatena.ne.jp/1202990372
上記の回答者1の方のスクリプトをヒントを元に、
「ファイルが存在しない時には
①新規にファイルを作成
②「test2.php」を呼び出して、①で作成したファイルに書き込み
③作成したファイルをHTTPヘッダを送信する」
というつもりで以下の通りスクリプトを書き直しました。
else{
$fl = fopen($hoge,"a+");
fputs($fl,(include('test2.php')));
fclose($fl);
header("Location: " . $hoge);
}
しかしこれだと下記のようなエラーが出ます。
「Cannot modify header information - headers already sent by (output started at 」
しかも新規に作成されたファイルではなくform.phpが表示されます。
これをのどのように解決すればよいのでしょうか?
なお、質問者はまだPHPの学習を初めて間もない初心者なので、
自分のやりたいことをうまく質問することもままなりません。
情報が不足している場合、または質問が不明瞭な場合はその旨コメントをいただければ幸いです。
以上、よろしくお願いします。
そのエラーメッセージは「既にページ出力が行われているのでヘッダーを追加できません」という意味です。つまりヘッダー出力は echo などでページ出力を行う前に行いましょうということです。
恐らくその header(" Location:...") を実行する前に echo や phpのエラーメッセージ等でなんらかのページ出力が行われていると思います。その部分をコメントアウトするなり適切に修正すればリダイレクトできるようになるはずですよ。
スクリプトを拝見したところ次の箇所が気になります。
fputs($fl,(include('test2.php')));
include('test2.php') だと test2.php に書いてあるPHPスクリプトが
そこで実行されるので、echo とか print で出力を行ったり、PHPの
ブロック() の外に何か書いてあれば、ページ出力が発生
してしまいます。
※出力は一切せず、作成したデータを return で返しているとかなら別なのですが。。。
test2.php は新規に作成するファイルの、ひな型のようなものでしょうか。
test2.php と同じ内容を、新規に作成したファイルに書き込みたいのであれば、
次のようにしてみてください。
fputs($fl,(file_get_contents('test2.php')));
で、もし、test2.php のPHPスクリプトを実行した結果として出力される内容を
保存したいということであれば次のような書き方ができると思います。
// test2.php の出力内容をバッファリングして取得 ob_start(); include('test2.php'); $contents = ob_get_contents(); ob_end_clean(); fputs($fl,$contents);
>test2.php のPHPスクリプトを実行した結果として出力される内容を保存したい
そのとおりです。それがまさにやりたかったことなのです。
私のつたない質問からそこまで推察していただいてありがとうございます。
いただいたスクリプトを元にelse以下を下記のようにしてみました。
else{
$fl = fopen($hoge,"a+");
ob_start();
include('test2.php');
$contents = ob_get_contents();
ob_end_clean();
fputs($fl,$contents);
fclose($fl);
header("Location: " . $hoge);
}
しかしこれだと新規にファイルを作成した時に前と同じエラーが出ます。
また、ファイル自体は思ったとおり作成されるのにそれが表示されません。
これをどのように手直しすればよいのでしょうか?
おそらくとても簡単な間違いをしているのでしょうが、
私は初心者ですのでわかりません。
よろしくご回答くださいませ。
> つまり、スクリプト自体は問題ないと言うことでしょうか?
問題あります。
fputs($fl,(include('test2.php')));
include の使い方が間違っているように思います。
include は、外部ファイルを自スクリプトの一部として読み込む場合に使うお考えになるとよいでしょう。(つまり、複数の異なるスクリプトで共通で使うサブルーチン集とか、状況に合わせた初期値を設定するスクリプトを複数用意しておいて本体からどれかを選んで読み込むとか...)
ご質問のように使うのでしたら、
fputs($fl, file_get_contents('test2.php'));
のような使い方だと予想します。
また、いつも test2.php を読み出して、form で送られたファイル名にするだけでしたらワザワザPHPで読み書きしなくても、copy() というのがあります。
http://jp.php.net/manual/ja/function.copy.php
> また、具体的にはどのようにすればよいのでしょうか?
今質問の回答者1さんが仰るように、変更した else 句以前に、header(), echo, print などを出力しているか、何かのエラーを表示していませんか?
例えば、上述の fputs() の所とか...
でなければ、前質問での回答者1さんのスクリプトの else 以下をご質問のように変更しただけではこのようなエラーは出ないように思います。
公開されていない部分で何かが起きているのでは、今質問の回答者1さんの回答は十分具体的だと思いますよ。
ご回答ありがとうございます。
大変勉強になりました。
今後の参考にさせていただきます。
なお、この質問に関して少し手直しをしていただきたい部分がありますので、
回答者2の方に対するお返事を参照の上、
引き続き皆様からのご回答をお待ちしています。
前の回答者1です。
前回のサンプルは、外部からインクルードして作るようなものにしてませんでした。すみません。
今回のエラーの原因はheaderにあります。
えっと、引用譜面わからないからそのまま↓
覚えておいて頂きたいのは、header() 関数は、 通常の HTML タグまたは PHP からの出力にかかわらず、すべての実際の 出力の前にコールする必要があることです。頻出するエラーとして、include() または require() 関数、他のファイルをアクセスする関数に 空白または空行があり、header() の前に出力が 行われてしまうというものがあります。同じ問題は、単一の PHP/HTML ファイルを使用している場合でも存在します。
http://www.phppro.jp/phpmanual/php/function.header.html
つまり、header命令の前にhtmlの文字や、echoで出力した文字が来るとエラーになります。
解消法はincludeで読み込まず、fopenで読み込んでfgetsで習得してください
else{ $fp = fopen('test2.php','r'); while( $line = fgets($fp,1024) ){ $dat = $line."<br />\n"; } fclose($fp); $fl = fopen($hoge,"a+"); fputs($fl,$dat); fclose($fl); header("Location: " . $hoge); }
http://nyx.pu1.net/practice/file_ope/file_ope4.html
再度のご回答ありがとうございます。本当に助かります。
このスクリプトをそのままコピーして貼り付けて実行したところ、
確かにエラーは消えたのですが、今度は「test2.php」で実行したものが保存されず、
新規に作成されたファイルには「?>」と表示されます。
これはどのように手直しすればよいのでしょうか?
私は初心者ですのでわかりません。
よろしくご回答くださいませ。
> しかしこれだと新規にファイルを作成した時に前と同じエラーが出ます。
それは、else 句内でヘッダを出しているのは変更する前と同じだからです。
else 句以前に、なにか出していませんか?
> また、ファイル自体は思ったとおり作成されるのにそれが表示されません。
header() で、Location: を出すのなら、ローカルのファイル名を出してはダメです。
'Location: http://www.example.com/'.$hoge
のようにしないと。
http://jp.php.net/manual/ja/function.header.php
http://lab.moyo.biz/translations/rfc/rfc2068-ja.xsp#14.30
参考までに、test2.php でやっている処理を少し教えていただけませんか?
再度のご回答ありがとうございます。
>else 句以前に、なにか出していませんか?
ifの所でもlocationを使っていたので、ファイルがある場合の処理を削除して、
下記のようにしたところうまくいきました。
if(file_exists($hoge)==false){
$fl = fopen($hoge,"a+");
ob_start();
include('test2.php');
$contents = ob_get_contents();
ob_end_clean();
fputs($fl,$contents);
fclose($fl);
}
header("Location: " . $hoge);
これで何もかもうまくいきました。
私は初心者ですので、皆さんのおっしゃることが理解できないことも多く、
とんちんかんな発言を繰り返してばかりいます。、
真剣に取り組んでるのでますので、いたらない部分はなにとぞご配慮くださいますようお願いします。
これに懲りず今後もぜひご指導くださいませ。
なお、今回のスクリプトを元にさらに手直しをしたいので、下記で質問しました。
お時間のある時にでもご回答ください。
http://q.hatena.ne.jp/1203395717
皆さん最後までおつきあいいただき本当にありがとうございました。
>>なんらかのページ出力が行われていると思います。
>ご指摘の通りです。
>>適切に修正すれば
>具体的にはどのようにすればよいのでしょうか?
具体的に、とのことですが最初の解答にも書いた通りページ出力をしないようにすればよいです。
Locationジャンプする際にページ出力は不要のはずですよね。
もし出力されているのが故意に行っている echo などではなく phpのエラーメッセージであるならば、そのエラーの原因を解決してエラーやワーニングなどが出ないようにすればよいです。エラーメッセージの内容がwarningやnoticeなどの重要でないエラーメッセージで放置しても大丈夫で、かつそれが出ないように修正するのが大変ということでしたら、以下のコードをphpの先頭に書いておけばエラーメッセージが出なくなります。
<?php // 全てのエラー出力をオフにする error_reporting(0); ?>
再度のご回答ありがとうございます。
質問の項目はこの回答を開く直前にうまく処理することができました。
問題点は回答5の方に対するお返事に書いておきましたので、
スクリプトについてはそれをもってお返事とさせてください。
私は独学で勉強を始めたばかりの初心者なので、
皆さんがおっしゃることが理解できなかったりしています。
Locationの件もやっと先ほど理解できました。
今回のお返事もかなりとんちんかんだったと思います。
私が至らず申し訳ありません。
それでもご回答いただいた皆さんのおかげでまた一歩前進することができました。
一生懸命がんばってる所ですので、なにとぞ寛大にご配慮ください。
「全てのエラー出力をオフにする」コード大変参考になりました。
ありがとうございます。
これに懲りず今後もいろいろ教えてください。
ご回答ありがとうございます。
エラーの理由がやっとわかりました。
>なんらかのページ出力が行われていると思います。
ご指摘の通りです。
>適切に修正すれば
具体的にはどのようにすればよいのでしょうか?
引き続きご回答をお待ちしています。