ブログ

  • 【PHP】fopen関数とfputs関数の不具合

    アクセスカウンターを作成していて、fopenとfputsで、ハマったので覚書しておきます。

    (タイトルを正確に言うと、不具合ではなくて、仕様の理解不足です。)

    まず、fopen関数のモードについて。

    r+ は上書き。
    w は書き出しです。

    この2つのモードでのfputsの挙動を記しておきます。

    元のファイルが一行で以下の場合。

    1234567890

    これにwモードで、「abcde」と書き込むと以下の結果になります。

    abcde

    1234567890は消え去り、書き込まれたabcdeに置き換わっています。当たり前といえば当たり前です。

    次に、同じ「1234567890」にr+モードで「abcde」を書き込んでみます。

    元は、

    1234567890

    r+モードで「abcde」を書きこみします。

    abcde67890

    すると、結果がおかしなことになっています。というか、これが正常な結果のようです。

    どういうことかというと、abcdeを書き込んだのに、元からあった文字の重ならない部分が、そのまま残ってしまっているのです。(赤字部分)

    abcde67890

    wモードだと、一度、ファイルを空にしてから書き込むので、元の文字列のくずは残りません。

    これに対して、r+モードだと、元の文字列の上に上書きするので、元の文字列のくずが残ってしまいます。

    これは、r+モードの良さでも有り、悪さでもあります。

    例えば、アクセスカウンターを扱う場合に、r+モードだと、内容がゼロになる瞬間は(多分)ないのでファイルが壊れる可能性は低くなります。これが良い点。

    しかし、元の文字列と桁数が異なるような場合には、元の文字列のクズが残るので、不具合の原因になります。これが悪い点です。

    最後に蛇足です。

    file_put_contents関数は、fopenのwモードで動く(と思われる)ので、アクセスカウンターには向きません。wモード同様にファイルがゼロになる瞬間があるのでファイルの内容が消えてしまうことがあります。

    アクセスカウンターを作るなら、r+モードで桁数に注意して作成することをお勧めします。

  • 【google maps api】infowindowの中で改行させる処理【PHP】

    google maps api を利用していて、吹き出しであるinfowindowの中で改行させる方法です。

    通常の場合、<br>または</br>タグを記述すれば、改行されます。

    しかし、PHP+DBで連携させていて、データをDBから取得して処理する場合、改行処理の関数であるnl2br関数を当てて処理しても、上手く改行表示されません。

    そこで、改行文字をスクリプトを使って<br>に変更します。

    参考までに、スクリプトは以下の通りです。

    $needles = array("\r\n", "\r", "\n",);
    $string = str_replace($needles, '<br>', $string);

    文字列$stringに入っている改行文字をstr_replace関数で<br>に戻してやります。

    ちなみに、CORESERVERでは、\r\nを変換するだけで上手くいきましたが、念のため、\rおよび\nも変換対象にしています。

    以上です。

  • 【CORESERVER】PHPのエラーログを記録する方法【XREA】

    PHPのエラーログを記録する方法は3つあります。

    一つは、php.iniで設定する方法。

    一つは、.htaccessで設定する方法。

    一つは、個別ファイルでini_set()関数で記録する方法。

    この3つの方法のうち、レンタルサーバーであるXREA、CORESERVERでは、php.iniの編集はできないので、後の2つの方法でログを記録することになります。

    ただ、本来、.htaccessでエラーログを記録できるはずなのですが、
    php_value error_log ‘任意のファイル’
    を設定しても機能せず、ログが取得できない場合があります。
    症状 http://sb.xrea.com/showthread.php?t=12556

    そこで、.htaccessには、

    php_flag display_errors off
    php_flag log_errors on

    この2つのみを記述して、php_value error_logは個別スクリプトでini_set()関数で実行する方法を採用します。

    つまり、ログを記録したいファイルのページの先頭で、ini_set()関数を実行する共通ファイルを読み込ませてログを記録するわけです。

    参考までに共通ファイルでのスクリプトを紹介します。

    <?php
    /**** エラーログを記録 ****/
    $logdate = date('Ymd') ;
    $logpath = realpath(dirname((__FILE__ ))).'/../../../errorlog' ;
    $logfile = "$logpath/$logdate.log" ;
    ini_set('error_log', $logfile) ;

    上記スクリプトをcommon.phpなどの名前で保存して、個別ファイルの先頭に読み込ませるとログを記録します。

    この際、ログの記録先として、errorlogディレクトリをルートディレクトリにパーミッション707で作成しておきます。すると、このerrorlogディレクトリに日別にエラーログが作成されていきます。

    この方法だと、一つのログファイルが膨大になることを防ぐことができるので、.htaccessで記録するよりもログファイルを扱いやすくなる利点が有ります。

    なお、スクリプトのご利用は自己責任でお願いします。

    関連記事
    http://webmaster.chielog.com/php/120.html

  • 【書評】プロのWebクリエイターになるための教科書

    プロのWebクリエイターになるための教科書
    千貫りこ(著)の書評です。

    マイコミの、○○の教科書シリーズの一冊です。

    良い点

    • フルカラーで綺麗で見やすい
    • 文章が丁寧で読みやすい
    • Web製作の請負を時系列で丁寧に解説
    • ディレクター・デザイナー・コーダー3者について著者の経験とノウハウを公開
    • 著者の熱意

    悪い点

    • 特になし。あえて言うなら、技術の解説が中途半端。

    総評

    Webクリエイターになるための教科書というタイトルのこの本ですが、内容的には、小中規模のソフトハウスやSOHOとして、どのようにしてホームページ製作を請負い仕事をするかという点に重点が置かれています。

    読者対象として、これから、Web系のSOHOをしたい人にお勧めできる本です。

    Web製作の過程を、準備、企画設計、デザイン製作、納品公開の4ステップで時系列に解説していて分かりやすいです。クライアントである顧客との折衝方法も参考になります。

    また、それぞれの製作過程をディレクター、デザイナー、コーダーという3者の立場に割り当てているので、3者の役割がどのようなものか分かりやすいです。

    WebのHTMLやCSSなどの技術書は巷に溢れていますが、本書のようなプロのWeb製作を請け負うための書籍はあまりないので、この方面の仕事につきたい人にはお勧めの一冊。ただし、技術主体の本ではないのでこの点は注意が必要です。

    プロのWebクリエイターになるための教科書

  • PHPで作るアクセスカウンター【昨日・今日・合計】

    PHPでアクセスカウンターを作ってみました。

    いわゆる昨日・今日・合計形式のテキストカウンターです。

    【追記】このスクリプトの改訂版を掲載しました。(2014/01/29)
    http://webmaster.chielog.com/php/182.html

    作ったといっても一から作るのではなく、レッツPHP!さんの昨日・今日カウンターをカスタマイズしてみました。

    カスタマイズといっても大分変更してシンプルにしてあります。

    <?php
    //ログファイルcount.logの形式は1行のみで以下の通り。
    //今日の日付け|昨日のカウント|今日のカウント|合計カウント
    //例:20120101|07777|05555|09999999
    $now_date = date('Ymd') ; // 今日の日付
    $yes_date = date('Ymd', strtotime('-1 day')) ; // 昨日の日付
    // カウンタ記録ファイル
    $count_log = 'count.log' ;
    $dat = file($count_log) ; //ログを配列に読み込む
    if (!empty($dat)) {
        //変数を展開(比較用日付、昨日、今日、総合)
        list($key, $yes, $tod, $all) = explode("|", $dat[0]) ;
        if ($key === $now_date) { //ログの日付が今日ならカウントアップ
            $tod++ ;
        } elseif ($key === $yes_date) { //日付がかわったら昨日に今日を、今日に1を入れる。
            $yes = $tod ;
            $tod = 1 ;
        }
        $all++ ; //合計カウントアップ
    
        //桁数整形
        $yes = sprintf("%05d", $yes) ;
        $tod = sprintf("%05d", $tod) ;
        $all = sprintf("%08d", $all) ;
        //ファイル更新
        $new = implode("|", array($now_date,$yes,$tod,$all)) ;
        $fp = fopen($count_log, "r+") ;
        flock($fp, LOCK_EX) ;
        fputs($fp, $new) ;
        fclose($fp) ;
    }
    echo $all.'|' ;
    echo $tod.'|' ;
    echo $yes     ;
    //end

    こんな感じです。

    レッツPHPさんとの違いは、

    1. 画像を無くし、テキストオンリーにしたこと
    2. fopen関数をwモードではなくr+モードにしたこと
    3. 桁数を整形してからファイルに書き出ししていること
    4. 日付変更時のロジックを簡略化

    などなどです。

    カスタマイズの理由は、

    1. テキストのみの方が軽い
    2. fopenをwモードで処理するとファイルが壊れる(ファイルが空になる瞬間あるため)
    3. 先に桁数を整形した方が、日付変更時に桁数違いのバグが出ない
    4. 三項演算子の処理が不要だったので簡略化

    というわけです。

    アクセスカウンターを作成している人の参考までに。

    なお、スクリプトのご利用は自己責任でお願いします。

    fopen関数とfputs関数の仕様についての関連記事
    http://webmaster.chielog.com/php/125.html