LoglessLove

愛は常に上書き保存 新ブログ→ http://www.loglesslove.net/blog

全体表示

[ リスト | 詳細 ]

記事検索
検索

全2ページ

[1] [2]

[ 次のページ ]

PHPで日本語メールを送る際には、mb_send_mail() では送信者を、PEAR::Mail を使う場合はそれに加えSubjectを mb_encode_mimeheader() でエンコードする。
その場合、件名や送信者名が長いとヘッダと本文の壊れたメールになることがある。

下記は mb_encode_mimeheader() の仕様だ。
string mb_encode_mimeheader ( string $str [, string $charset [, string $transfer_encoding [, string $linefeed [, int $indent ]]]] )
・・・
linefeed
linefeed は EOL (行末) のマーカで、 mb_encode_mimeheader() が行を折りたたむ (» RFC 用語で、 ある一定より長い行を複数行に分割することを言います。 分割する長さは、現在 74 文字に固定されています) 際に利用します。 デフォルトは "\r\n" (CRLF) です。

http://php.net/manual/ja/function.mb-encode-mimeheader.php

上記のように第4引数の $linefeed がデフォルトで "\r\n" となっている。これで件名や送信者名を分割していくわけだが、メーラーによってはCRLFでヘッダを切ってしまう。
その結果ヘッダと本文が壊れる。
#大手のフリーメールだったら大丈夫。

この場合は $linefeed に"\n"を設定してやるとうまくいく。

ただ単純に mb_encode_mimeheader() を使ってメールを送信することは可能だが、実はもっときめ細やかな設定ができるし、した方がいいよ、という話。

この記事に

開く コメント(0)

文字化けが発生した場合や、正規表現で特定の全角文字を捕まえなければならないときに、よく文字コード表を見るのだけど、文字を探してコードを見て、という作業がいいかげん面倒になってきたので、任意の文字列を SJIS, EUC, UTF-8 のコードで表現するロジックを作った。

    $str = isset($_POST['str']) ? $_POST['str'] : null;
    $encoding = isset($_POST['encoding']) ? $_POST['encoding'] : '1';
    $regexp = isset($_POST['regexp']) ? $_POST['regexp'] : null;

    $dstEncoding = null;
    $srcEncoding = 'UTF-8';
    $strEncoded = null;
    $code = null;
    
    switch ($encoding) {
        case '1':
            $dstEncoding = 'SJIS-win';
            break;
        case '2':
            $dstEncoding = 'EUCJP-win';
            break;
        case '3':
            $dstEncoding = 'UTF-8';
            break;
        default:
            $dstEncoding = $srcEncoding;
            break;
    }
    if (strlen($str) > 0) {
        $strEncoded = mb_convert_encoding($str, $dstEncoding, $srcEncoding);

        $prefix = ' ';
        if ($regexp == '1') {
            $prefix = '\x';
        }
        
        for ($i = 0; $i < strlen($strEncoded); $i++) {
            $code .= $prefix . dechex(ord(substr($strEncoded, $i, 1)));
        }
    }
    echo $code;

こいつに値をPOSTする入力フォームをつけて終了。

2010-01-03 追記
一部間違いがあったので修正。
ついでに実装例。
http://www.loglesslove.net/encode.php

この記事に

開く コメント(0)

SELECT CONCAT('a', NULL);

の結果は NULL になる。
CONCAT するカラムに NULL が入るかどうかをちゃんとチェックしないといけないねえ。

この記事に

開く コメント(0)

エンバケッソ

カタカナの「ソ」が化けてトラブルが発生するのをたまに聞く。
「ソ」のコードを見てみると、SJIS で 0x83 0x5c。
ところで、「\」の文字コードは 0x5c。
たとえば SJIS の文書で「\」をデリミタにして単語を分ける、なんてことをしてみる。

ミライ\ニ\バケル\シンソザイ

これを PHP の explode() で切り分けて配列にする。

$aru = "ミライ\ニ\バケル\シンソザイ";
$paka = explode("\\", $aru);
print_r($paka);

そうすると、

Array ( [0] => ミライ [1] => ニ [2] => バケル [3] => シン・ [4] => ザイ )

のような感じになって、意図した分け方をしてくれない。
「ソ」の後ろ 2 バイトを「\」と解釈してしまうので、このような現象が起きる。
5C問題とか呼ばれているらしい。

たぶんこうすればいい。

$paka = explode("\\", mb_convert_encoding($aru, "UTF-8", "SJIS"));
$src = array_fill(0, count($paka), "SJIS");
$tmp = array_fill(0, count($paka), "UTF-8");
$paka = array_map("mb_convert_encoding", $paka, $src, $tmp);
print_r($paka);

一旦 SJIS から他の文字コードに変換して、分割して、元の文字コードに戻す。

Array ( [0] => ミライ [1] => ニ [2] => バケル [3] => シンソザイ ) 

円マークに化けずに新素材が無事未来に化けてくれたよ\(^o^)/

この記事に

開く コメント(0)

上策 アップロードファイルを一旦サーバに置き、バックグラウンドで登録/変更/削除
中策 アップロードファイルから直ちに登録/変更/削除
下策 アップロードファイルから一旦配列を作ってから、登録/変更/削除

WEBページで商品CSVをアップロードしてDBに対して登録/変更/削除を行うページの開発を最近よくやるようになった。普段ブラウザから画像をアップするような感覚で行う、アレ。

やることリストは以下。
1. CSVからデータを取る。
2. 取ったデータをDBのテーブルレイアウトに合うように変更する。
3. DBに放り込む。

何も考えず、わかりやすいのがいいだろうと思って「下策」を採っていた。
混沌とした商品CSVから1行を取り出し、テーブルレイアウトに合致するように値を設定し、配列に1行追加する、ということを件数分行う。
やることリストでいうと1と2を完了させてから、3を行う形だ。

ところが、商品件数が数万件になってくるとメモリ不足で怒られて処理ができなくなることがある。特にレンタルサーバーは怒りっぽい。
数万件の商品データ全部を格納した配列を一度つくるから、無駄にメモリを食ってしまう。

ということで、「中策」を採ることにした。全体の配列を一度作るということをせずに、CSVから1行取り出してテーブルレイアウトに合わせ、その1行をDBに放り込む。
やることリスト1〜3までを件数分繰り返す。
これで無駄にメモリを食うことはなくなった。
今はリソースが潤沢にあるとはいえ、どんな無駄も許されるというわけじゃない。
日常生活にたとえてみると、年収2000万円だけど家賃月600万円の高級マンションに住むようなもので、そりゃアンタ金持ってますが限度があるでしょう、といったところだ。

こうしてメモリの問題は解決した。ところが、数万件もあると処理完了までに数十分かかることがあり、CSVをアップロードすると完了までそのままブラウザが固まってしまう。
いくら待っても画面が真っ白、まだ処理が続いているのかな、と調べてみるととっくに完了しているといったようなことが、よくある。
日常生活にたとえてみると、5分だけ首絞めるから我慢してね、と5分間首を絞めていたら、本当にあの世に行ってましたという感じ。
では5分間首を絞めるとあの世に行くので、首を絞めるのは30秒ずつにしてくださいねとか、そんな注意をユーザーに求めることは難しい。操作としてできることはついやってしまうからだ。
帰るときは戸締りをしてくださいといわれても、戸締りをしないで帰ることができるから、戸締りを忘れてしまう。それと同じ。

さあどうしたものかと悩むふりをしていたある日、他のサービスのCSVからの商品登録を見て「(・∀・)ソウダッタノカ!!」と納得した。それはたぶんこうだろうということで「上策」を採用する。
CSVファイルをアップロードしたところで、そのファイルをサーバー上の適当な場所に放置する。
それでPHPのsystem()関数で別のプログラムを実行する。このプログラムはやることリスト1〜3をバックグラウンドでやってくれる働き者だ。
そうやって働き者に仕事を丸投げしたところで、このアップロード用プログラムの仕事は完了する。
数十分後には商品登録処理も完了しているだろう、果報は寝て待て、という想定。

ここで働き者のバックグラウンド商品登録さんが、さらに進捗状況をファイルかDBに書き出してくれていると、アップロード後丸投げさんのところのHTMLでjavascriptが動いて進捗状況をブラウザに表示する、ということもできる。

あとは商品登録処理の中止(system()でkillする)があると、いいかもしれない。登録処理中にもう一度アップロードされることなどを考えると。「何か食べる前には嘔吐して胃と腸を空にしておきましょうね」設計。

この記事に

開く コメント(0)

全2ページ

[1] [2]

[ 次のページ ]


.


みんなの更新記事