画像をディレクトリに保存するタイプ。元ファイル名を記憶するロジックを省いているので画像種別にしたがって拡張子を付与します。

 

<?php

$imgdir = ''upimg/'';
while ((isset($_FILES['img']))&&(is_array($_FILES['img']))) {
    if ($_FILES['img']['error'] !== UPLOAD_ERR_OK) {
        $errmsg = 'Upload Aborted';
        break;
    }
    $data = file_get_contents($_FILES['img']['tmp_name']);
    $info = getimagesizefromstring($data);
    $ext = '';
    switch ($info[2]) {
    case IMAGETYPE_GIF:
        $ext = '.gif';
        break;
    case IMAGETYPE_JPEG:
        $ext = '.jpg';
        break;
    case IMAGETYPE_PNG:
        $ext = '.png';
        break;
    }
    if ($ext === '') {
        $errmsg = 'IMAGE TYPE ERROR';
        break;
    }
    $name = sha1($data) . $ext;
    if (move_uploaded_file($_FILES['img']['tmp_name'], $imgdir . $name)) {
        $msg = 'Save to ' . $name;
    } else {
        $errmsg = 'can NOT save file';
    }

    break;
}
?>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="img" />
<input type="submit" name="submit" value="POST" />
</form>
<?php
if (isset($msg)) { printf('<div>%s</div>', $msg); }
if (isset($errmsg)) { printf('<div style="color:red">%s</div>', $errmsg); }
 

MySQLにデータ挿入・取得するテストスクリプトです。

<?php
header('content-type: text/html; charset=utf-8');
try {
    $pdo = new PDO("mysql:host=localhost;dbname=test; charset=utf8", "root", ""); // 接続情報は適宜書き替えてください
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    print '接続<br>';
    $pdo->query('DROP TABLE IF EXISTS test');
    $pdo->query('CREATE TABLE IF NOT EXISTS test (
        id int(11) NOT NULL AUTO_INCREMENT,
        text varchar(256) DEFAULT NULL,
        PRIMARY KEY (id)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1');
    print '準備完了<br>';
    $stmt = $pdo->prepare('insert into test (text) values (?)');
    for ($i=1; $i < 11; $i++) {
        $stmt->execute(array('PDOで書き込みました(' . $i . '件め)'));
    }
    print 'データ挿入<br>';
    $stmt = $pdo->query('select * from test');
    $ct = 0;
    while ($row = $stmt->fetch()) {
        if ($ct++ === 0) { print '<ul>' . PHP_EOL; }
        printf('<li>%s&nbsp;-&nbsp;$s</li>' . PHP_EOL, $row['id'], $row['text']);

 

    }
    if ($ct > 0) { print '</ul>' . PHP_EOL; }
} catch (PDOException $e) {
    print $e->getMessage();
}

私はロリポBlogのhead要素の</head>の直前に、下記のソースを挿入しています。lightboxの設定などもここです。この開発日誌では無関係ですが(汗

<script src="http://code.shimix.jp/js/scrollsmoothly.js" type="text/javascript"></script>
<link href="http://code.shimix.jp/css/lightbox.css" type="text/css" rel="stylesheet" media="all" />
<script src="http://code.shimix.jp/js/jquery-1.11.0.min.js" type="text/javascript"></script>
<script src="http://code.shimix.jp/js/lightbox-2.6.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$(".entry").find("a").each(function() {
            if( $(this).find('img').length ) {
                $(this).attr( "data-lightbox", "lbox" ); // 画像リンクの場合だけ属性を追加する
            }
});
});
</script>
<!--
</head>
-->

何故コメントアウトした</head>があるかというと、ロリポBlog独自のスクリプトが</head>の直前に埋め込まれるからです。その</head>がコメントアウトされているかどうかはノーチェックなので、コメントアウトの開始と</head>の間に埋め込まれます。つまり全部コメントアウトされてしまう(=強制的に無効になる)わけですね(苦笑


自分で使うというよりは他人に「この時点でのデータ内容をチェックしろ」って教えるときに、ブラウザ上での「見た目」じゃなくてバイナリとして比較させるのにしばしば提示する関数です。

function hexdump($arg) {
    $ret = [];
    if (strlen($arg) > 0) {
        for ($i=0; $i < strlen($arg); $i++) {
            $ret[] = sprintf('%02x', ord(substr($arg, $i, 1)));
        }
    }
    return implode('-', $ret);
}

対象データが大きくなると予想されるときは、16バイトごとに改行したりとかもするといいんだろうなぁ(汗

ローカルPCのphpからメール送信をテストしたいケースはよくありますが、実運用ならまだしもわざわざテストのためだけにSMTPサーバをインストールするのは敷居が高いです。

現行のxampp1.8.1のphp.iniでは
sendmail_path = "C:¥xampp¥mailtodisk¥mailtodisk.exe"

が有効になっていて、説明だとC:¥xampp¥mailoutputフィルダに書き込まれるとなっていますが、どうやっても確認出来ませんでした(汗


ということで、xampp標準装備のsendmail.exeを使うように変更してみます。sendmail.exeのコメントアウトを取り除き、mailtodisk.exeをコメントアウトします。
; XAMPP: Comment out this if you want to work with fakemail for forwarding to your mailbox (sendmail.exe in the sendmail folder)
sendmail_path = "¥"C:¥xampp¥sendmail¥sendmail.exe¥" -t"

; XAMPP: Comment out this if you want to work with mailToDisk, It writes all mails in the C:¥xampp¥mailoutput folder
;sendmail_path = "C:¥xampp¥mailtodisk¥mailtodisk.exe"

あとは、C:¥xampp¥sendmail¥sendmail.iniを編集して送信設定を行います。GMailのアカウントを利用するならこんな感じで(書き替える部分だけ抜粋)。
smtp_server=smtp.googlemail.com

smtp_port=465

auth_username=(GMailのアカウント)
auth_password=(GMailのパスワード)

hostname=(送信元として名乗るホスト名:指定しないとPC名になる)
元々はComma-Separated Valuesの名のとおりカンマで区切られたフィールドを扱うフォーマットです。カンマ以外のデリミタ(区切り文字)のもの(タブ区切りのTSVや半角スペース区切りのSSVなど)も含めてCharacter-Separated Values(CSV)とかDelimiter-Separated Valuesと呼ばれることもあります。

データ交換用のフォーマットととして長く使われていますので、現在ではRFC4180で仕様が成文化されています。

http://www.ietf.org/rfc/rfc4180.txt
http://www.kasai.fm/wiki/rfc4180jp

phpスクリプトでCSVデータを扱うときの最善手はfgetcsv/fputcsvを使うことです。fgetcsv/fputcsvであれば、文字列データ中に改行コードが含まれているようなケースでも問題なく扱えます。現在のphpスクリプトでは、これ以外の選択肢は考えられません。

SplFileObjectを使うときは同様にfgetcsvメソッドがあります。



ということで以下は蛇足です(汗

fgetcsvがなかった頃の力技だと、作成時にはimplode、取り出し時にはexplodeを使うのが基本でした。現在でも、たまに自前で implode/explodeを使って処理しようとしているケースがあります。習作としてデータの扱いに慣れるための頭の体操としては意味があるのですが、カンマ(区切り文字)の取り扱いや二重引用符の取り扱いすら考慮してないケースがほとんどです。そういうスクリプトはデータの内容次第で簡単に破綻してしまいます。

  • データとして「改行」が存在すると扱いにくいので、作成時にはnl2brしたあとで、"¥r"と"¥n"を(個別に)削除する。読み込んでhtmlとして表示するときは「そのまま」。改行コードに戻したいときはを改行コードに置換する。もちろんなどの存在を認めるようなケースだと(いわゆるBBコード的な)別の文字列に置換することになります。

  • カンマは文字列データに存在する可能が高いのでデリミタをタブ("¥t")とする。文字列データ内に存在するタブコードは適当な文字列で置換する(ほとんど出現しないハズの文字コードだがコピペなどで混入する可能性がまったくゼロではないので)。

  • 文字列中に二重引用符があったら二重引用でエスケープ( " → "" で置換)し、文字列(フィールド)全体を二重引用符で括る。取り出し時には先頭+末尾が二重引用符だったら取り除き、"" を " で置換する。


phpの標準関数であるmb_send_mail()を使う場合の注意点です。標準で実装されていることから初心者が最初に作るメールフォームではmb_send_mailが多用されるようです。

#本来はPHPMailerなどのライブラリを使う方がベター

大事なのは、mb_languagemb_internal_encodingをキッチリ(正しく)書くこと

mb_languageとmb_internal_encodingさえちゃんと指定していれば、あとはほとんどの部分を自動的にやってくれます。自前で余計なことをしないように要注意です。

mb_languageが"ja"の場合はISO-2022-JP、"uni"の場合はUTF-8のメールが作成されます。

普段はほとんど意識しない(意識しなくても問題がない)mb_internal_encodingですが、mb_send_mailを使うときだけはちゃんと指定します。mb_internal_encodingで指定された文字セットからメールの文字セット(前述のとおりmb_languageの値に従ってISO-2022-JPもしくはUTF-8)に変換されます。

変換対象は第一引数から第三引数まで。つまり件名や本文は何も考えなくていいわけです。逆に言えば第四引数で自分でメールヘッダに何か指定するときには日本語の扱いには注意しないといけません。Fromヘッダにメールアドレスだけでなく自分の名前を入れたいという場合にはmb_encode_mimeheaderする必要があります。

なおmb_encode_mimeheaderも第二引数を省略した場合にはmb_languageの値を参照しますし、mb_internal_encodingからの変換も自動的にやってくれます(これも自前で変換したりするとおかしなことになります)。

開発途中での調べ物の結果とかちょこっと書いたソースとかを置いとくのにBlog追加しました。要するに備忘録です。

#今さら感満載なんですが(汗

多分メインはphpに関する話題になると思います。

1