dポイントプレゼントキャンペーン実施中!

お世話になっております。

http://oshiete1.goo.ne.jp/qa4005498.html
http://oshiete1.goo.ne.jp/qa4047511.html

これまで上記ページにてDBを使わずにテキストファイルにてデータ管理するアドバイスをいただき、テキストエリアに入力したものをテキストファイルに登録することが出来ました。

こんな感じ。

01<>プログラム
01_01<>PHP
01_02<>javascript

と入力したものを、テキストファイルに

01  プログラム
01_01 PHP
01_02 javascript

に登録(半角数値と文字の間はスペース)。

そこで、テキストファイルに登録されたデータを修正・削除する管理画面を作っているのですが、テキストファイルからデータを呼び出し、file()を用いてデータを配列にし、for文で各データをテキストフォームに表示させるところまで出来ましたが、以下の点についてが分からず、アドバイスを頂ければと投函させていただきます。

1.修正する場合、テキストファイルのデータを配列にして各データをテキストフォームにて表示させているが、修正する場合、どのような流れになるのか?(テキストファイルのデータは改行にて登録されていますが、テキストファイルから読み込んだとき配列にしているので、適正な流れが分かりません)

2.テキストファイルのデータを配列にし、各テキストフォームに表示させた際、削除するための機能と考え、各データ毎にチェックボックスを設けていますが、配列データの任意の場所を削除したとき、再度テキストファイルに改行を含んだデータとして登録するには、どういった流れ(プログラム?関数?)になるのか?

以上、皆さんお忙しいとは思いますが、お知恵を頂戴出来れば幸いです。宜しくお願い致します!

A 回答 (5件)

<?php


// データの読み込み
$myData = unserialize(file('category.txt'));
// 様々な処理

$fp = fopen('category.txt', 'w');
fputs(serialize($myData));
fclose($fp);
?>

ですね。
出力時にserializeかけるの忘れてました。
    • good
    • 0
この回答へのお礼

masa6272さんへ

こんばんは。お世話になっております!
ご丁寧に補足まで頂きありがとう御座います。
ご挨拶が遅れてしまいましたが、(自信はないものの)とりあえず動くまで設定することが出来ました!
不慣れなため、以降、似たようなことで質問することもあるかと思いますが、今後とも宜しくお願い致します。
有難う御座いました!

お礼日時:2008/06/02 21:50

serializeとオブジェクトは直接関係は無いです。


下のような感じです。
$myDataに必要なものを全部入れておきます。
例えば、
$myData['member'] = $members; // メンバーの配列
$myData['city'] = $cities; // 市の配列
$myData['prefecture'] = $prefectures; // 県の配列
のようにです。

で、入出力はまとめてですね。

<?php
// データの読み込み
$myData = unsirialize(file('category.txt'));
// 様々な処理

$fp = fopen('category.txt', 'w');
fputs($myData);
fclose($fp);
?>

オブジェクト指向ですが、PHP5からかなり使えるものになっていますので、使わないのはもったいないかも。もちろん無理に使うこともありませんが。
    • good
    • 0

テキストファイルでの保存の話はもう済んでいるかも知れませんが・・・



テキストファイルの書式を気にせずに、serialize,unserializeを使ったらどうでしょう?
serializeは、配列だろうがオブジェクトだろうが、構造や内容を保ったまま、文字列に変換します。
そして、それをそのまま、まとめてファイルに書き出します。
使うときは、一度に文字列として読み込んで、unserializeを使えば、元のデータ構造、内容が復元されます。
改行が、どうのといったことは考える必要もありません。

考えるのは、配列を使ったプログラミングだけです。
後、最初の住所録のようなものでしたら、
Prefecture、City、Memberのクラスを作って、MemberオブジェクトのプロパティにCityオブジェクトを持ち、Cityオブジェクトのプロパティとして、Prefectureオブジェクトを持つようにします。
そして、Memberオブジェクトの配列を丸のまま、serailize、unserializeでいいと思います。
    • good
    • 0
この回答へのお礼

masa6272さんへ

はじめまして、こんばんは!
ご親切なアドバイスをありがとう御座います!

#1-2様からのアドバイスを無駄にしたくなく、また理解を深めたいと思っておりますが、具体的な設置例なども含め、このserialize,unserializeをもう少しお教え頂けないでしょうか?

アドバイスからして効率よく?(簡単?)に出来そうなイメージはあるものの、本を読んでもいまいちピンと来ないのが本音です。

これまでクラスやオブジェクトなどは、あまり取り入れずに来たもので、(ゆくゆくは学びたいとは思うものの)今回は無視して進めたいと思っているのですが、このserialize,unserializeを利用するに当たり、クラスやオブジェクトを取り入れることは不可欠なのでしょうか?
もう少し具体例をアドバイスいただけると嬉しいです。
宜しくお願い致します!

お礼日時:2008/05/28 23:43

ANo.1です



まず・・file()でデータファイルを配列に読み込んだときには、各配列の文字列の最後には改行コードが付いたままなのは過去のやりとりで理解されていますね?また、ファイルへ書き込むときには、最後にPHP_EOLを付加して書き込むことは前回のやりとり(私ではなかったですが)で既知だと思います。

で、ご質問の件(配列データの取扱い)ですが、配列データと行単位で修正・POSTされた内容を書き込む場合には

  $ct = 0;
  $no = 0;
  foreach ($array as $line) {
    $ct++;
    if ($ct == $_POST['no']) {
      $no++;
      puts($fh, $no . "\t" . $_POST[item1] . "\t" . $_POST['item2'] . PHP_EOL)
      }
    else {
      list($wno, $body) = explode("\t", trim($line));
      $no++;
      puts($fh, $no . "\t" . $body . PHP_EOL);
      }
    }

のような感じでいいのでは?$no++を2箇所に書いているのは、削除用に流用するときのためです(苦笑)。noを書き替えなくていいような場合(もしくはnoに該当するようなものがない場合)には不要ですね。削除のときはputsで修正された(POSTされた)データを書き込む代わりにcontinueで書込みをskipすればいいと思います。

  $ct = 0;
  $no = 0;
  foreach ($array as $line) {
    $ct++;
    if ($ct == $_POST['no']) { continue; }
    list($wno, $body) = explode("\t", trim($line));
    $no++;
    puts($fh, $no . "\t" . $body . PHP_EOL);
    }


全部一括で書き替えるような場合には、そもそもフォームに全内容をセットするときに配列になるようにnameを工夫しますから、POSTされた内容をforeachで回せばいいと思います。

#上記では手抜きしてますが、POSTされた値の正当性やmagic_quotes_gpc関係の処理はこれより前の段階で終わっているという前提で(汗

この回答への補足

shimixさんへ

こんばんは。お世話になっております。
ご説明の中にある「puts」とは、「fputs」のことで宜しいでしょうか?
今回出てくる関数は、殆どと言っていいほど初めて試すものばかりで、アドバイスを頂戴してから時既に7-8時間を費やしています。。

本を片手に関数を調べながら進めているのですが、申し上げたように初めて試すものが多く、以下のように苦し紛れで動作確認をしながら進めているのが現状です。。
お恥ずかしいこととは思いますが、以下にそのソースを記載いたしますので、引続きご指導いただければ有難いです。
教えて教えて!と言うつもりじゃないのですが・・・

<?php

$file_name = 'category.txt';

if(file_exists($file_name)){
$file=fopen("$file_name", "r") or die("OPENエラー $file_name");
fclose($file);
$string = file($file_name);

$count = count($string);//データ数

$string = file($file_name);//配列に格納

}

//修正or削除
if(isset($_POST["edit-category"])){
/********
if(isset($_POST["c1"])){
$line = $_POST["c1"];
print_r($line);
}

$categoryname = $_POST["category_name"];
print_r($categoryname);//POSTされた配列データ

$ct = 0;
$no = 0;
foreach($categoryname as $line){
$ct++;
if ($ct == $_POST['c1']) {
$no++;
fputs($file_name, $no . "\t" . $_POST[category_name] . PHP_EOL);
}
else {
list($wno, $body) = explode("\t", trim($line));
$no++;
fputs($file_name, $no . "\t" . $_POST[category_name] . PHP_EOL);
}
}


//削除
$ct = 0;
$no = 0;
foreach($categoryname as $line){
$ct++;
if ($ct == $_POST['c1']){continue;}
list($wno, $body) = explode("\t", trim($line));
$no++;
puts($$file_name, $no . "\t" . $_POST[category_name] . PHP_EOL);
}
******/
}

//新規登録
if(isset($_POST["new-category"])){

$new = $_POST["new"];

$pattern = "<>";
$replacement ="\t";//に置換
$contents1 = ereg_replace($pattern, $replacement,$new);
$pattern = "<>";
$replacement ="\t";
$new = ereg_replace($pattern, $replacement,$contents1);

//$new = mb_convert_encoding($new, "SJIS","SJIS,EUC-JP,UTF-8");//Linuxサーバーの場合はSJISをEUC-JPに

$file=fopen("./data/"."category.txt","w");
flock($file,LOCK_EX);
fputs($file, "$new" . PHP_EOL);
flock($file,LOCK_UN);
fclose($file);

}

echo <<<EOD
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">
<title></title>
</head>
<body>

<form method="post" action="./">
EOD;
for($i=0; $i<$count; $i++){

$category_data = $string[$i];
$category_data = explode('',$category_data);
echo "<input type=\"checkbox\" name=\"c1[]\" value=\"".$category_data[0]."".$category_data[1]."\"><input type=\"hidden\" value=\"".$i."\" name=\"id\">";
echo $category_data[0];
echo "<input type=\"text\" name=\"category_name[]\" size=\"30\" value=\"".$category_data[1]."\">\n";
echo "<br>\n";
}

echo <<<EOD
<input type="submit" name="edit-category" value="修正">
<hr>


<textarea cols="50" rows="10" name="new"></textarea>
<br>
<input type="submit" name="new-category" value="登録">

</form>
</body>
</html>
EOD;
?>

補足日時:2008/05/28 23:19
    • good
    • 0
この回答へのお礼

shimixさんへ

おはよう御座います!お世話になっております!
早々のお返事、かつ夜遅くの対応をありがとう御座います!!

今、お教えいただいた内容を試す状況ではないので(プログラムを触れる状況じゃないので)、改めアドバイスして下さった内容を元に、試してみたいと思います!取り急ぎお礼まで・・。

ありがとう御座いました!
今日も一日頑張って下さい^^

お礼日時:2008/05/28 08:24

修正は行ごとですか?全行一括ですか?どちらにするかで処理が変わってきますが・・



・行ごと(行番号とその行の内容を受け取る)であれば
   全行を配列の読み込む。
   変更のあった行を置換する
   全行を再度上書きする
・全行一括であれば
   受け取ったデータで全部上書きする

行削除は、上記の「行ごと」と同様で
   全行の配列を読み込む
   削除行番号以外のデータをデータファイルに上書きする

といったパターンではないでしょうか?

(蛇足)
行内のセパレータは「空白」ということですが、入力内容に空白が含まれないことは保証(空白を含んでいたら再入力にするなど)されてますか?個人的にはセパレータは"\t"(タブ)が使いやすいのですが・・
    • good
    • 0
この回答へのお礼

shimixさんへ

こんばんは!お世話になっております!
行ごとのケースと、全行のケース、どちらの方が良いのでしょうか?
色々なお考えがあるでしょうが、ご意見いただけると嬉しいです。

それと、今回アドバイスいただいた件ですが、ご説明から察すると配列を操作する内容かと思いますが、テキストファイルに上書きする際、配列から配列でないデータ(改行を含んだデータと言ったら宜しいのでしょうか・・適切な言葉が出てきません・・)にするには、どのような関数?を利用するのでしょうか?今一度アドバイス頂戴出来たら嬉しいです。


>個人的にはセパレータは"\t"(タブ)が使いやすいのですが・・

すみません。。説明が不適切だったかも知れません。。行内は以前アドバイスして下さったように、"\t"で行っています・・。

お礼日時:2008/05/27 22:29

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!