ランダムで取得してページング

2008/07/20 | MySQL

データをランダムな順番で取得するには以下のorder句をつければいいということは前に書いた。

order by rand()

これで確かにランダムな順番でデータを吐き出してくれるのだが、SQL実行毎に順番が変わってしまう(当たり前)。ページング処理を実行したい場合は、1ページ目と2ページ目を表示する際に、順番に(例えば)10件ずつデータを取ってくるわけだが、そもそも順番がめちゃくちゃなので、1ページ目のデータが2ページ目でまた出現してしまう、といったことが起きてしまう。どうすればよいか。解決策がコレ。

order by rand(n)
nは適当な数値

詳しくは調べていないがnは乱数を発生させる際のseed値のようなもの。このseed値が同じであれば、並び順は常に同じになるのだ。なのでデータ取得の一番最初のときにこのseed値を初期化して、以降のページングの際はこのseed値を持ちまわってSQL文に仕込んでやればよいということになる。

fsockopenでマルチバイトなメール送信

2008/07/08 | PHPの基本

基本的にメール送信はmb_send_mailを使っているが、いろんな事情でfsockopenによるメール送信を実現しなければならないときがある。それでも、マルチバイトなメール送信でない場合は、何も気にしなくてもスムーズにいくが、マルチバイトなメール送信となると、文字化け問題が常につきまとう。
今回fsockopenでマルチバイトなメール送信プログラムを書いたときに、文字化けせずに送信できたので、その例をメモしておく。

■タイトル
$subj=mb_convert_encoding($subj,’JIS’,’(元のエンコーディング)’);
$subj=mb_encode_mimeheader($subj,’JIS’,’B’);

■本文
$body=mb_convert_encoding($body,’JIS’,’(元のエンコーディング)’);

よく調べてないけれど、タイトルはいったんJISに変換してからmb_encode_mimeheader。本文はJISに変換するだけでいい。

結果オーライということで。

特定の動作時のみプログラムが動かない

2008/07/01 | PHPの基本

つい先日、クライアントさんに納品した案件で不具合があった。本番環境にて稼働させたところ問題が発生したとのことだった。まぁ、本番環境というのは得てしてテスト環境よりもアクセス数等が増加するし、想定外の操作をしてしまう人もいるはずなので問題が出てもおかしくはないのだが(もちろん想定外の動作などないように、各種想定をされたプログラムがいいのはいうまでもないけれど)。
今回のプログラムで、クライアントから「トラブル発生」の連絡を受けた際に想定したのは「max_execution_time」だ。つまり想定した数よりも多いデータ数を処理しなくてはいけなくなってしまったので、当然処理時間が増え、システム規定の時間では間に合わなくなってしまった、という場合だ。
実際、現地を訪れエラーの出る処理を試してみた。しかし、エラーは一定時間をおいて出るのではなくすぐに出る。しかも表示されるエラーはIEのエラー(ちゃんと確認しておけばよかったと後悔している)。
リンクをクリックして、すぐにエラーが出るのであれば、max_execution_timeの問題ではないはずだ(PHPのエラー画面が表示されるはずだし、システム規定の時間はプログラムが稼働するはずだから)。次に想定したのは、memory_limit。取り扱うデータ量が増えることは容易に想像できるから、ini_setコマンドで多めに設定してみた。これで見事解決した。
本番環境では、得てしてプログラムが想定外の動作をしてしまうことは多々あるが、今回はその典型となるような例だった。プログラムのエラーが発生しているのか、環境的な問題でエラーが出ているのかは判断がつきにくいところではあるが、相応の経験をしていれば意外と簡単に原因を突き止められるものだなぁ、と思った次第であった。

Smarty使用時のダウンロード処理

2008/06/25 | Smarty

ファイルのダウンロード処理をおこないたいときにテンプレートエンジンを使っている場合、どんな具合にプログラムを書けばよいか迷うことがよくある。フレームワークを使っていない場合はプログラム内にダウンロード処理を直書きしてしまうけれど、フレームワーク使用時は直書きするのはなんとなく美しくない。やっぱり通常通りの処理を通過して、テンプレート内だけで処理できればスマートだと思っている。Smartyの場合だが、今回はテンプレートファイルの最初にこんな具合におまじないを記述することでダウンロード処理を実現できた。

{php}
header(“Cache-Control: public”);
header(“Pragma: public”);
header(“Content-Type: application/csv”);
header(“Content-Disposition: inline; filename=data.dat”);
header(“Content-Transfer-Encoding: binary”);
header(“Accept-Ranges: none”);
{/php}

キャッシュ制御系はSSL使用時のIEバグ対策。Content-type、Content-Dispotion、Content-Transfer-Encodingは適宜指定。実際にダウンロードさせたい部分は、この後ろに記述すればよい。

でも、実はヘッダ的には一つ足りないんだと思う。それはダウンロードさせる容量Content-Lengthだ。この記述が必要なら、上記の記述の前に事前にダウンロードデータを以下のように記述して、容量を計算して出力すればいいかもしれない。

{capture name=download}
(ダウンロードさせたいデータを記述)
{/capture}
{header_content_length var=$smarty.capture.download}

いったん出力データを変数に格納して、別途ヘッダ出力用のカスタム関数(header_content_length)を用意しておいてそれに食わせてやればいい。カスタム関数が必要でしたら・・・各自でどうぞ(今回は作らなくても動いてくれたので作らなかった)。

スタイルシートで表示・非表示

2008/06/23 | その他

今更スタイルシートか、とも思うけれど、何せ自分がウェブの世界に入ったときにはスタイルシートなんてなかったので、出会うこと全てが勉強のような気がする。

スタイルシートを使うと、HTML中に記述された文字の表示・非表示を自由に変更できる。特にJavaScriptを組み合わせると、インタラクティブなインターフェースが提供できるので、ついつい使いたくなってしまう(んでもって、大切な開発の時間が少なくなっていく)。
今日新たに一つのことに気がついた。スタイルシートで表示・非表示を制御する属性が二つあることに気がついたのだ。それらは「visibility」と「display」。何の気なしに使っていたのだが、よくよく理解していないと希望通りの動作をしてくれないので、メモしておくことにした。

■visibility
visible(既定値:表示する)、hidden(表示しない)、inherit(継承)の値をとる。基本的にこの属性をvisibility:hiddenとして与えると「HTML上に存在するが(領域は確保されるが)内容そのものは表示されない」という解釈になる。つまり高さ100pxと指定した領域を、上記の属性で囲むと100pxの高さ分のスペースは確保されたままになる。

■display
block(ブロック要素)、inline(インライン要素)、list-item(リスト要素)、none(表示しない) の値をとる。こちらでnoneが指定された場合、ブラウザは、あたかもHTML上にそのスタイルシートで囲まれた部分が記述されていないかのようにレンダリングされる。

この違い、見た目的には結構大きいので使い分けの必要がありそうだ。


守谷市(まちの情報ポータル) 無料アンケートレンタルjpForm.net