PHP基本編

ファイル入出力

1. 演習準備

 さあ、いよいよやってきましたファイル操作。ファイルにデータを書き込んだり、ファイルからデータを読み込んだりということです。難しそうですか?いえいえそれほどではありません。いつもパソコンでやってるような「ファイルを開く」とか「ファイルの内容を読む」といったことをPHPでやるだけの話です。これができると、できることの幅がグンと広がります。アクセスされた情報を保存してアクセスカウンターを作ったり、入力されたテキストデータを保存して掲示板のようなものも作れます。というわけでここでは、テキストファイルへの書き込みと読み込みの方法についてマスターしましょう。
 その前にサンプルを動かすためのファイルを準備しておきましょう。これまで通り、[Xamppフォルダ]→[htdocsフォルダ]→[pkpkisoフォルダ]で、ひな形ファイル「hina.html」を[Ctrl]+[c]し、[Ctrl]+[v]を2回すると2つコピーができますので、名前をそれぞれ「kihon08.html」と「kihon08.php」に変更。次のように編集します(ここで時間をかけても仕方ないのでコピペでOK)。

  kihon08.html
  

  kihon08.php
  

 念のため確認です。kihon08.htmlでは<form>タグでkihon08.phpにデータを送る設定をし、そのデータ入力部品として<textarea>と送信ボタン<input type="submit">、リセットボタン<input type="reset">を設置してます。一方、kihon08.phpは、postメソッドでデータを受け取り、変数$messageに代入し改行タグと結合してecho命令で表示しています。

SPONSORED LINK

 作成後、Xamppを起動しlocalhostから表示して下さい。「http://localhost/phpkiso/kihon08.html」です。XamppについてはPHP開発環境準備編・Xamppの起動Xamppの設定をご確認下さい。

  

  

2. PHPでのファイル操作

 準備ができたところで本題に入りましょう。まず、PHPで「ファイル」というものがどのように扱われるか解説します。
 例えば、皆さんが、ワードなどで作成した文書ファイルを編集したい場合、どうするでしょうか。通常、ファイルを開いて、編集して、ファイルを閉じる、ということをすると思います。PHPのプログラムでも同じです。PHPでのファイル操作は、基本的には、ファイルを開く「fopen()」関数から始まって、ファイルを閉じる「fclose()」関数で終わります。ここでは作らなくて良いので例を見てみましょう。

  

 まずfopen()関数があります。抜き出すと次のようになります。

  $fp = fopen ('sample.txt','r');

 ここでは、fopen()関数を用いて「sample.txt」を「r」モード(read読み取りモード)でオープンし、結果を変数「$fp」に代入しています。意味としては、sample.txtというテキストファイルを読み取るだけの(書き込まない)モードで開き、その管理情報を変数$fpに保存している、というようなことです。まぁ「そういうものだ」と覚えておけばOK。プログラム言語なんて所詮はコンピュータに命令するために人間が勝手に作ったルールですから、そもそも書き方に必然性なんてありません。基本的に「そういうものだ」でできています。
 ここでは「sample.txt」を指定してありますが、もちろんこれは読み込みたいファイルです。カンマ区切りの「list.csv」というファイルを読み込みたければそれを指定します。あるいは、読み込みたいファイルがPHPプログラムとは異なるディレクトリにあれば、「files/kakikomi.dat」などとパスを含めて指定する必要があります。
 ここで読み込むファイルは、テキストファイル(=Terapadやメモ帳などテキストエディタで読めるファイル)です。ワードやエクセルのファイルを指定しても読み込めませんのでご注意。PHPでは、ワードやエクセルや画像ファイルも扱えますが、ここで説明するのとは別の方法で処理する必要があります。この超入門資料では取り上げませんので、必要があれば調べて下さい。
 また、ここでは「r」モードが指定されていましたが、これ以外にも「w」モード(上書きwriteモード)や「a」モード(追記addモード)があります。

mode説明
'r'読み込み用に開く。ファイルポインタをファイルの先頭に設定(=先頭から読み込む)。
'w'書き込み用に開く。ファイルポインタをファイルの先頭に設定(=先頭から書き込む=間違って書き込むとファイルが置き換わる)。ファイルが存在しない場合、作成を試みる。
'a'書き込み用に開く。ファイルポインタをファイルの終端に設定(=後ろから追加して書き込む)。ファイルが存在しない場合、作成を試みる。

 またfopen()の結果を、変数$fpに代入する形がとられている点。これはもう少し専門的っぽい言い方をすると、ファイルポインタ(ハンドラ)を「$fp」という名前の変数に格納している、という説明になります。意味は上記の通り、開いたファイルの管理情報を保存しているわけです。
 ですので「$fp」という変数名はfile pointerから来ていますが、これも決まっているわけではなく別の名前でもOKです。ただ実際には、「$fp」や「$handle」が使われるのをよく見かけます。いずれにせよプログラミングする時は、わかりやすい変数名をつけるのがベターということです。
 次に、fclose()関数です。これも拡大すると次の通りです。

  fclose ( $fp );

 我々の普段のパソコン操作でも「編集が終わったら開いたファイルは閉じましょう」ということになりますよね。ということで最後にfclose()関数でファイルを閉じているわけです。この時「$fp」を指定していますが、これはfopen()で開いたファイルの情報を管理する変数でした。つまり開いたファイルをfclose()関数で閉じている、ということになります。

SPONSORED LINK


3. ファイルへの書き込み

 データをファイルに書き込む処理から考えてみましょう。ファイルに書き込むには、fwrite()関数を使います。指定するのは、fopen()関数でファイルを開いた後です。fputs()関数もありますが同じものと思っておけばOK。なのでfwrite()で覚えておいて下さい。もし人が書いたプログラムなどでfputs()が出てきたらfwrite()と読み替えて対応しましょう。

上書きモードでの書き込み
 まずはファイルの先頭から書き込む、つまり上書きモードでのファイル書き込みを確認します。以下のサンプルを確認しましょう。

  kihon08.php(php部分以外は省略)
  

 説明します。2行目まではOKなのでその次から。3行目の「$filename = 'wdata.txt';」。$filenameという変数にファイル名「wdata.txt」を設定しています。これもOKでしょう。
 4行目。出ましたfopen()関数。$filenameに指定されたファイル(wdata.txt)を、上書きwモードで開き、ファイルポインタを$fpに設定しています。上で見た通りです。
 続いて5行目。fwrite()関数。「$fp」つまり、上書きモードですでに開いているwdata.txtに対し、変数$messageの内容を書き込みます。つまり、postメソッドで受け取ったデータをファイルに上書きしているわけです。
 そして6行目では、書き込み完了ということで「fclose ( $fp );」でファイルを閉じ、7行目ではecho命令でファイル名と入力内容を表示して終了、ということになります。
 理解できたらサンプルを実行して試しましょう。「localhost」経由でkihon08.htmlにアクセスしメッセージを送信して下さい。kihon08.phpに飛んで「~に~と書き込みました」と表示されたら、このPHPファイルが保存されたphpkisoフォルダの中を見て「wdata.txt」があるか、そして入力したメッセージが「wdata.txt」に保存されているか確認します。テキストファイルなのでTerapadやメモ帳等のテキストエディタで開けます。

  

  

 できましたか。問題なければ確認を続けます。今開いた「wdata.txt」の内容を確認したテキストエディタを一旦閉じます。その上で、もう一度kihon08.htmlから違うメッセージを入力します。kihon08.phpが表示されたら「wdata.txt」を開いて保存内容を再度確認してください。「wdata.txt」を確認したソフトが開きっぱなしだと内容は変わりませんので必ずいったん閉じて、開きなおして下さいね。保存されたメッセージが更新されていればOKです。

SPONSORED LINK


追記モードでの書き込み
 上記サンプルでは上書きwモードで書き込みましたので、処理を実行するたびにファイルの内容が置き換わってました。でも上書きして古いデータを消してしまうのではなく、書き込んだことがどんどんたまっていくようにしたいこともあります。そんな時に使うのが追記のaモードです。サンプルで確かめましょう。

  kihon08.php(php部分以外は省略)
  

 修正は3か所だけ。1つ目。3行目のファイル名。違いが確かめられるよう別のファイルに指定しなおしました。wdata.txtを「adata.txt」としています。ファイル名は何でも良いのですが、追記aモードのaなのでわかりやすいかなと。
 2つ目。4行目のfopen()関数のモード指定を「'w'」から「'a'」に変更しました。これで書き込みするとファイルにデータが下から追加されていくはずです。
 3つ目。5行目のfwrite()関数の中。書き込む内容を「fwrite ( $fp, $message."¥n" );」と変更しました。つまり、入力データである$messageに「.」(ピリオド)で結合して「"¥n"」を入力しています。これまでにも出てきましたが、¥nは、Terapadやメモ帳等テキストエディタでの「改行」を表す記号です。ブラウザでの改行は<br>ですが、テキストエディタでは<br>では改行されません。テキストファイル内で改行させるためには¥nとする必要があります。そしてPHPで「¥n=改行記号」と認識させるためには「"」(ダブルコーテーション)で囲むんでしたね。「'」(シングルコーテーション)で囲むと「¥n=¥nという文字列」と認識されてしまいます。PHP基本編・配列で文字列を特定の区切り文字で分割して配列に格納するexplode()関数の説明のところでも出てきました。
 ところでここでなぜ書き込む内容に「¥n」(改行記号)を結合したかというと、追記モードでデータが追加されていく際に区切りがないと、元々あったデータと追加されたデータの境界がわからなくなるためです。「カレー」「うどん」「焼きそば」「パン」と区切られていれば、それぞれ別々に入力されたことがわかりますが、「カレーうどん焼きそばパン」だと「カレーうどん」かもしれないし「焼きそばパン」の可能性もあって場合によっては困るわけです。
 ですので逆に「追加されたデータなんて区別できなくていい!」という場合は不要ですし、あるいは「別の区切り記号を使いたい!」という場合は別の記号でも構いません。でも「1回の入力=1レコード=1行」となっているとわかりやすいので「¥n」(改行記号)はよく使います。
 ということで実際に動かしてみましょう。「localhost」経由でkihon08.htmlにアクセスしメッセージを送信。kihon08.phpが正常に表示されたら、もう一度ブラウザの戻るボタンでkihon08.htmlに戻って別のデータを入力します。数回繰り返しても良いです。できたら「adata.txt」を開いて確認して下さい。書き込んだメッセージが改行されて下へ下へと追加されていたらOKです。うまくいかないときはよく見直しましょう。

  

  

SPONSORED LINK


4. ファイルからの読み込み

 サーバーに保存されたテキストファイルを読み込む方法はいくつかありますが、ここでは取り扱いが簡単なfile()関数を紹介します。簡単ですし、これでほぼ十分でもあります。
 file()関数は「テキストファイルの内容を全て読み込み、1行ずつ配列に格納してくれる関数」です。配列に格納されれば、編集したり、計算したり、表示したりすることが容易にできます。
 「1行ずつ」という事は、一連のデータの「改行」がある所までが「1行」として扱われるという事です。この場合の「改行」はHTMLの改行タグ<br>ではなく、Terapadやメモ帳等テキストエディタで行が変わる「改行」です。Terapadなら「改行」の表示設定がしてあれば、各文末に「↓」(下矢印)の改行マークが表示されますが、これのことです。上でも見たように、PHP的には「¥n」ですね。つまり、テキストファイルに書かれた1行1行には、その最後に目には見えない「¥nという記号で表される改行」が付いているということです。例えば、テキストファイルに・・・

当店では
大盛りサービスは
やってません

・・と3行書いてある場合、実際には・・・

当店では¥n
大盛りサービスは¥n
やってません¥n

 と書いてあることになります。
 というわけで、file()関数でテキストファイルの内容が1行ずつ配列に格納される、というのはまさにこの「当店では」「大盛りサービスは」「やってません」が、それぞれ配列の要素として設定されることを意味します。この場合は、テキストファイルが3行から成るので、配列の要素は3つになります。以下のサンプルを見て下さい。

  kihon08.php(php部分以外は省略)
  

 解説します。一つ前のサンプルの最後のecho文を削除して、7行目から新たに書き加えています。
 7行目ではさっそく「file()」関数が使われています。ここでは「$contents = file($filename);」ということで、$filenameに指定されたファイル「adata.txt」の内容を読み込み、変数$contentsに設定しています。このとき、ファイルの各行は分割されて配列の各要素に割り当てられますので、$contentsは配列になります。
 そして次からのforeachループ。配列専用の繰り返し処理命令でした。前の資料PHP基本編・配列にありましたね。指定された配列のすべての要素について1件ずつ取り出し処理していきます。配列$contentsのすべての要素、つまり、ファイル「adata.txt」のすべての行を1行ずつ取り出して処理します。続く{ }内にecho命令が指定されていますので、ファイルのすべての行が改行タグ<br>とともに出力されることになります。
 できたところで、実際に動作させて確認してみましょう。先と同様kihon08.htmlに「localhost」経由でアクセスしメッセージを送ります。kihon08.phpが表示されメッセージの一覧が表示されたらOK。何度か繰り返してみて下さい。どんどん一覧のリストが追加されてけば完璧です。

  

  

 file()関数の他にも、先に示したfopen()とfclose()関数と一緒に使うfgets()関数や、fopen()とfclose()が不要でテキストファイル全部をまとめて読み込むfile_get_contents()関数、同じくfopen()とfclose()が不要でテキストファイル全部をまとめて読み込んで表示するreadfile()関数などもあります。ただ、file()関数さえ知っていればほぼ事足ります。ここでは紹介しませんが必要があれば調べてみて下さい。

SPONSORED LINK

(参考) ファイルのパーミッションについて

 ファイルの書き込みに関して一点覚えておいて欲しい注意点があります。
 この資料では、Xamppを使ってローカルのパソコン内で開発することを想定しています。ですが、これをレンタルサーバなどにUPして実行しようとした場合に、書き込まれるファイルの「パーミッション」(=permission、許可)が問題になることがあります。いわゆる「アクセス権限」ですね。権限がないとうまく書き込めなかったりエラーが出たりするわけです。
 なぜこのようなことが起きるかというと、サーバー上のファイルには「読み」「書き」「実行」という3つの属性が設定され、これらによって「閲覧可能か」「書き込み可能か」「実行ファイルかどうか」が制御されているからです。
 普段パソコン使ってると、テキストファイルならどれもメモ帳やTerapad等のテキストエディタで閲覧も書き込みもできますし、実行ファイルかどうかはファイル名拡張子が「~.exe」となっているかどうかで決まりますので、ピンとこないかも知れません。でもサーバーは違います。サーバーはそもそも複数あるいは多数のユーザーが共用することを想定していますので、誰もが勝手にいろいろアクセスできては困ります。ですのでファイルやフォルダーについて、誰がアクセスできるのか、誰なら閲覧できるのか、誰が実行してよいのかなど「パーミッション」を指定してやる必要があるわけです。
 ということで、この資料に基づいてXamppでサンプルを試すときは問題になりませんが、サーバーを借りてやる場合に、もし「書き込み権限がありません!」といったエラーになったときは、パーミッションを変更して、「書き込み」を許可すれば書き込めるようになります。やり方にまでは踏み込みませんが、そういうのがあるということだけ覚えておきましょう。

SPONSORED LINK


練習問題

 このページで用いたファイルkihon08.htmlとkihon08.phpを使い、以下の課題に取り組みましょう。
  1. kihon08.htmlの「メッセージ」の上に「お名前」を入力する<input type="text" name="onamae" size="20">タグを設定し、kihon08.phpにはそのデータとメッセージのデータを受け取り、2つのデータを結合して「名前:メッセージ(改行)」という形式で、ファイル「message.txt」に追記モードで保存する処理を作成しなさい。
  2. kihon08.phpを編集し、作成された「message.txt」の一覧が表示されるようにしなさい。データが追加されるたびに1行ずつ増えていくようにすること。
練習問題の出力例

ページのトップへ戻る
SPONSORED LINK