8月に読んだ本
18月に読んだ本のメモ
OpenPNE や XOOPS などを調査中なので、その関係の書籍を何冊か読みました。
「OpenPNEでつくる!最強のSNSサイト」はかなりよかったです。
もうひとつの「OpenPNEではじめる自作SNS入門」は少し初心者向けかも。
「XOOPSコミュニティサイト構築ガイド」はモジュールの自作方法も載っていてかなり参考になりました。
OpenPNEでつくる!最強のSNSサイト
OpenPNEではじめる自作SNS入門
XOOPSコミュニティサイト構築ガイド
WEB+DB PRESS Vol.40
ご飯を大盛りにするオバチャンの店は必ず繁盛する―絶対に失敗しないビジネス経営哲学 (幻冬舎新書 し 4-1)
フラット革命
富裕層の財布―誰も知らないお金の使い方
誰も知らなかったケータイ世代
チームハックス 仕事のパフォーマンスを3倍に上げる技術
すぐに稼げる文章術 (幻冬舎新書)
グーグル革命の衝撃
PHP で多次元配列のソートを SQL の ORDER BY のように複数項目でソートする
1PHP で多次元配列の項目を複数使用して SQL の ORDER BY のようにソートする方法です。
$answer = array( "category1" => array( "ans1" => 1, "ans2" => 1, "ans3" => 1 ), "category2" => array( "ans1" => 1, "ans2" => 2, "ans3" => 0 ), "category3" => array( "ans1" => 0, "ans2" => 2, "ans3" => 1, ), );
というような配列を下記条件でソートします。
- ans1 の多い順
- ans1 が同じ場合は ans2 の多い順
- ans2 が同じ場合は ans3 の多い順
PHP の uasort 関数を使用します。
この関数はユーザーが比較関数を定義でき、その関数を使用して連想インデックスを保持したまま配列をソートします。
uasort($answer, "compare"); function compare($a, $b) { foreach ($a as $k=>$v) { if ($a[$k] > $b[$k]) { return -1; } else if ($a[$k] < $b[$k]) { return 1; } } }
上記の関数を使用してソートした結果 $answer は下記のようになりました。
$answer = array( "category2" => array( "ans1" => 1, "ans2" => 2, "ans3" => 0 ), "category1" => array( "ans1" => 1, "ans2" => 1, "ans3" => 1 ), "category3" => array( "ans1" => 0, "ans2" => 2, "ans3" => 1, ), );
MySQL で NULL を一番最後にして昇順にソートする
42008.2.27 追記
コメントで教えていただきました下記方法で簡単にできました。
is null asc の指定と 通常の asc の指定をするのがポイントですね。
SELECT id, comment FROM table ORDER BY comment IS NULL ASC, comment ASC;
—–追記ここまで—–
MySQL で昇順にソートすると NULL は一番最初に来ます。
それを最後にできないかということで下記のようなSQL を考えてみました。
SELECT id, comment, CASE WHEN comment IS NULL THEN 10000 ELSE ASCII(LEFT(comment,1)) END AS dummy FROM table ORDER BY dummy ASC, COMMENT ASC
comment カラムを昇順でソートして、NULL の場合は一番最後に NULL がきます。
あまりスマートな方法ではないのですが、これで取り合えず NULL を最後にして昇順でソートするということができました。
ORACLE とかだと下記のように簡単にできますね。
ORDER BY comment ASC NULL LAST
NULLS FIRST
NULL 値を順序の最初にするソートを行なう
NULLS LAST
NULL 値を順序の最後にするソートを行なう
ソフトバンク端末から mailto で件名と本文を入れる
1携帯サイトを作成していて mailto リンクで件名と本文を指定するのに下記のように指定します。
<a href="mailto:メールアドレス?subject=件名&body=本文">
※件名と本文は URL エンコードする必要があります。
しかしソフトバンクの3GC 端末で件名と本文の日本語がメーラに渡せないという現象がありました。
そこで、日本語を UTF-8 に変換してから URL エンコードすると渡せるようになりました。
HTML ソース自体は Shift-JIS です。
ソフトバンクの開発資料を見直したのですが、そういう記述は見つけられませんでした。
どこかに書かれているのでしょうか?
それとももっとうまいやり方があるのかなぁ。
ランダムに抽出する SQL
4ランダムに10件 SELECT する SQL です。
ORDER BY RAND() でランダムにソートして LIMIT 句で取得したい件数だけ取得します。
SELECT * FROM table ORDER BY RAND() LIMIT 10;
ランダム関数は MySQL, PostgreSQL, SQLServer で使用できます。
ランダム関数は
MySQL, SQLServer は RAND()
PostgreSQL は RANDOM()
です。
生年月日から年齢を簡単に求める方法
2担当しているシステムで生年月日から年齢を求める処理があったので、最初は PHP の strtotime などを使ってやろうかと考えていました。
しかし、ググってみると
にすごく簡単な方法が紹介されていました。
誕生日が1969年9月19日だと
$year = (int) ((date('Ymd')-19690919)/10000);
で今日現在の年齢が求められるということです。
上で紹介した記事は2年くらい前の記事なんですが、昨日はてぶをチェックしていると同じ方法が ITPro でも紹介されていましたね。
生年月日から年齢を計算する簡単な計算式:佐野裕のサーバ管理者日記:ITpro
しかし、これでなぜ求められるのか理由が書かれてなくしばらく考えてしまった。
年齢の計算は現在の年から生まれた年を引いてその数に、
今年の誕生日が来ていなければ -1、
来ていればそのままの数が年齢になるということ。
そして上の計算式ではそれをいっぺんに行っているということですね。
わからなければ実際に電卓で引き算をしてみればすぐに理解できるはず。
CakePHP HTML ヘルパーで textarea を出力する
1CakePHP の HTML ヘルパーでテキストエリアを出力するには下記のように書きます。
<?php echo $html->textarea("Model/field", array("cols"=>20, "rows"=>5, "value"=>"hoge")); ?>
checkbox や radio などと違って第2引数に HTML 属性値がくることに注意が必要です。
array("value"=>"hoge")
などと書くことにより初期値を入れることができます。
ランキングを取得するSQL
3ランキングを取得するSQL です。
同じスコアの場合は同じ順位にするなどの必要があるため結構面倒ですが、
下記SQL でイッパツで取得できます。
実際に携帯ゲームのランキングを取得するのに使用しているSQLです。
ranking テーブル
CREATE TABLE ranking ( id bigint(20) NOT NULL auto_increment, name varchar(20) NOT NULL, score bigint(20) NOT NULL, );
SQL
SELECT r1.name, r1.score, (SELECT count(r2.score) FROM ranking as r2 WHERE r2.score>r1.score)+1 as rank FROM ranking as r1 ORDER BY r1.score DESC LIMIT 10;
rank というカラム名で順位が計算されます。
同じスコアの場合は順位は同じになります。
上記SQL はトップ10を取得していますが、実際にはLIMIT句を変更することにより
ページング処理などで下位のランキングを見れるようにしています。
副問い合わせで順位を計算しています。
MySQL ではバージョンが4.1 以降でないと副問い合わせが使用できないので注意してください。
※本運用ではインデックスを適宜作成しています。
CakePHP HTMLヘルパーで checkbox を表示する
1HTMLヘルパーで checkbox を表示するには下記のように書きます。
<?php echo $html->checkbox('Model/field', null, array('value'=>1)); ?>
出力される HTML は下記のようになります。
(実際は1行で出力されますが改行入れています)
<input type="hidden" name="data[Model][field]" value="0" id="ModelField_" / <input type="checkbox" name="data[Model][field]" value="1" id="ModelField" />
checkbox と同じ名前の hidden を勝手に作ってくれるのでチェックされていなくても必ず $this->data["Model"]["field"] には値が帰ってくるのでうれしいかも。
ちなみに第2引数は checkbox では使用されていませんでした。
他のメソッドと統一するためにあるのでしょう。
第3引数に
array('checked'=>1) or array('checked'=>true) or array('checked'=>'checked')
などとするとデフォルトでチェックが入ります。
ちなみに HTML_QuickForm のように勝手に label タグで囲んではくれないので、チェックボックスの後ろに書かれた項目名などをクリックしてもチェックされるようにしたければ自分で label タグを書く必要があります。checkbox の ID は ModelField のようになるので、
<label for="ModelField"><?php echo $html->checkbox('Model/field', null, array('value'=>1)); ?>項目名</label>
とすれば「項目名」のテキストをクリックしてもチェックすることができるようになります。