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

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

ただいまの
回答率

88.10%

PHPのファイルロック:配列によるオープンと更新

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 632

score 36

こんにちは。
PHPで、既に存在しているファイル「aaa.cgi」に対し、
「排他ロック+何かしら処理+ファイル更新」という処理をしようと思っています。

<aaa.cgi の中身>

あああああ
いいいいい
ううううう

<やろうとしている処理>
排他ロックを使用して、aaa.cgi の先頭や真ん中に文字を追加したり書き換えたりする。
イメージとしては次のような感じです。読み込みには配列(file関数)を利用したいと思います。

$filename="aaa.cgi";
$fp=fopen("$filename", "r+");
if(flock($fp, LOCK_EX))
{
  $hairetsu=file("$file");

  # 何かしら処理
//  array_unshift($hairetsu, "なにこれ\n");  // 例えば先頭に追加
//  array_splice($hairetsu, 2, 0, "なにこれ\n");  // 例えば3行目に挿入

// ??????  // 【※書き換えの処理※】
  flock($fp, LOCK_UN);
}
fclose($fp);

現在、この【※書き換えの処理※】で何かしらうまいコードを差し込んで、
実現できないかを検討しているのですが、いかがでしょうか…
fwrite() ではstring型限定、file_put_contentsでは読み込みからの排他ロック実装が
問題としてあって解決法を探っています。

<別の解決策>

$filename="aaa.cgi";
file_put_contents("$filename", "なにこれ", FILE_APPEND | LOCK_EX);

追記モードを使ってこのようにすると、aaa.cgi に排他ロックで追記できるのですが、
この場合末尾に追記されるので、上記のようにファイル先頭に追記したり、
ファイル中央付近に追記するような操作があれば…

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

array_unshiftやarray_spliceで任意の場所に差し込みができているのであれば、
配列を改行コードでimplodeしたものをファイルに書き込めば良いだけだと思います。
改行コードで連結するので差し込むときに後ろにつけている改行コードは不要ですね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/30 18:08 編集

    ありがとうございます。
    implode() を使うのは盲点でした。面白いですねぇ…
    確かにこれでstringにしてfwrite() 使って書き込むことができますね。

    ただ、今回やろうとしてることは現存するファイルを読み込んで、
    そのファイルの中身に対して、array_unshift() や array_splice() で追記しようとしているので、
    【読み~書き までの間で排他ロックする】必要があります。
    ただ、排他ロックの関係で file() のアクセスができないので、
    読みの段階で共有ロックをして、書きの段階で排他ロックを掛けるしか方法はないでしょうか。
    アクセスの多いコンテンツのログであるため、この方法だとログが飛ぶケースが何度かあり、改善の余地があります…。

    キャンセル

  • 2018/09/30 19:34

    今一つやりたいことがわかりませんけど、同じファイルを参照する以上は更新中は後からのアクセスには待ってもらう必要があります。
    DBも同じですね。
    ロック中かどうかを取得してロック中の場合は一定時間スリープして自身がロック取得できるまで再起処理するしかないのではないでしょうか。

    というか、質問内容に現れていない大事な前提をさらっとコメントで書かれると回答が無駄になることがあります。
    要件として質問に追記してください。

    キャンセル

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

  • ただいまの回答率 88.10%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る