WEB+DB PRESS Vol.32

  4774127523
  http://www.amazon.co.jp/o/ASIN/4774127523/todaysnonsenc-22/ref=nosim/
  WEB+DB PRESS編集部 (編集)
  技術評論社
  ISBN: 4774127523
  2006/04/25
  1,554 円

  新連載多すぎ.

入門 PHP セキュリティ

  4873112869
  http://www.amazon.co.jp/o/ASIN/4873112869/todaysnonsenc-22/ref=nosim/
  Chris Shiflett
  オーム社
  ISBN: 4873112869
  2006/05/09
  1,890 円

PHP 用 YAML パーサ spyc の結果をキャッシュする方法

<?php
class CacheYAML
{
    var $cache_dir;
    var $filename;
    var $cache_filename;

    function CacheYAML($cache_dir, $filename)
    {
        $this->cache_dir = $cache_dir;
        $this->filename = $filename;
        $this->cache_filename = $cache_dir . DIRECTORY_SEPARATOR . md5($filename);
    }

    function getData()
    {
        return $this->isCached() ? $this->load() : $this->store();
    }

    function isCached()
    {
        clearstatcache();
        return file_exists($this->cache_filename) && (filemtime($this->filename) <= filemtime($this->cache_filename));
    }

    function load()
    {
        return unserialize(file_get_contents($this->cache_filename));
    }

    function store()
    {
        $data = Spyc::YAMLLoad($this->filename);
        $f = fopen($this->cache_filename, 'wb');
        fwrite($f, serialize($data));
        fclose($f);
        return $data;
    }
}
?>


- 使い方

// 使用前
$config = Spyc::YAMLLoad($file);

// 使用後
$yaml = new CacheYAML('path/to/cache_dir', $file);
$config = $yaml->getData();


  元ネタの記事では,parse_ini_file() をキャッシュしていたので,いつも遅いと感じていた spyc の結果をキャッシュするようにしてみた.
  体感できるくらい速くなりました.

  PHP 5.x を使っている場合は,fopen ... fclose の部分を file_put_contents() で置き換えることができます.

  # ところで YAML ってなんて読むんだろう?わいえーえむえる?やむる?

- file_put_contents
  http://php.net/file_put_contents

- ref.: Sooey - CachedIni class
  http://www.sooey.com/journal/2006/03/15/100/

PHP の unserialize() の 多言語での実装

  を見ていて,PHP の serialize() は便利だから,もしかしたら他の言語でも実装があるのでは?
  と思ったら,案の定たくさんあった.

- JavaScript
  http://www.phpguru.org/static/PHP_Unserialize.html
  http://www.phpguru.org/downloads/PHP_Unserialize/

- Perl
  http://search.cpan.org/dist/PHP-Serialization/lib/PHP/Serialization.pm
  http://hurring.com/code/perl/serialize/

- Ruby
  http://www.aagh.net/projects/ruby-php-serialize

- Java
  http://hurring.com/code/java/serialize/

- Python
  http://hurring.com/code/python/serialize/

- C#
  http://sourceforge.net/projects/csphpserial/

- Flash/ActionScript
  http://sourceforge.net/projects/serializerclass/

- via: Using Serialized PHP with Yahoo! Web Services
  http://developer.yahoo.net/common/phpserial.html#otherlangs

- ref.: Web屋のネタ帳
  http://neta.ywcafe.net/000544.html

軽量 PHP4 フレームワーク guesswork classic

  http://classic.guesswork.jp/

  かなりシンプルでよさげ.
  ドキュメントもそれなりに整っている.
  ちょっと使って評価してみるか.

- via: /home/pochi/ChangeLog
  http://www.pochi.cc/~sasaki/chalow/2006-02-16-3.html

Ajax と OpenSearch と はてなダイアリーキーワード連想語 API を使ったはてな検索のデモ

  http://pocari.org/tools/ajax/opensearch/

  はてなダイアリーキーワード連想語 API が面白かったのと,PHP から使える PEAR::OpenSearch を発見したので
  Ajax と OpenSearch と はてなダイアリーキーワード連想語 API を使ったはてな検索というものを作ってみました.

  

  OpenSearch には PEAR::OpenSearch を,はてなダイアリーキーワード連想語 API には PEAR::XML_RPC を使っています.
  また,JavaScript のライブラリは prototype.js と script.aculo.us (effects.js のみ) を使っています.

  やっていることは簡単で,入力された検索語の関連語を XML RPC で はてなダイアリーキーワード連想語 API を使って呼び出してきます.
  また,検索語を OpenSearch のはてな検索から検索してくるということだけです.
  検索結果は,上位 10 件を表示しています.10 件以上あってもそれ以上は検索結果には表示できません.

  それを prototype.js の Ajax クラスで呼び出して,effects.js でアニメーションしながら表示しています.

  使い方は,検索語を入れて [Search] ボタンを押すだけ.
  はてなダイアリーキーワード連想語がある場合は,検索結果といっしょに表示されるので,さらに連想語のリンクを選択すれば
  その連想語で再検索をします.

  動作確認は Forefox 1.5,IE 6.0 (ともに Windows 版) で行いました.それ以外のブラウザで動作するかは不明です.

  ソース一式も置いておきます.ライセンスは Creative Commons 帰属 とします.

- ソース一式 (tar.bz2)
  http://pocari.org/tools/ajax/opensearch/ajax-opensearch.tar.bz2

- Creative Commons Deed
  http://creativecommons.org/licenses/by/2.1/jp/

- ref.: PEAR :: Package :: Services_OpenSearch
  http://pear.php.net/package/Services_OpenSearch/

- ref.: はてなダイアリー - はてなダイアリーキーワード連想語APIとは
  http://d.hatena.ne.jp/keyword/%a4%cf%a4%c6%a4%ca%a5%c0%a5%a4%a5%a2%a5%ea%a ...

  また,本デモを作る際に下記のサイトを大いに参考にしています

- HOWTO: Animated Live Search // Ordered List by Steve Smith
  http://orderedlist.com/articles/howto-animated-live-search/

PEAR::XML_RPC から,はてなダイアリーキーワード連想語 API を使う方法

  はてなダイアリーキーワード連想語 API が面白そうだったので PEAR::XML_RPC から使ってみた.
  PEAR::XML_RPC のパラメータの組み立て方が気持ち悪すぎて嫌になる.こんなのわかんねーよ.

<?php
require_once 'XML/RPC.php';

$client = new XML_RPC_client('/xmlrpc', 'd.hatena.ne.jp');

$params = new XML_RPC_Value(
    array(
        'wordlist' => new XML_RPC_Value(
            array(
                new XML_RPC_Value('php'),
                new XML_RPC_Value('perl')
            ),
            'array'
        )
    ),
    'struct'
);

/*
// キーワード が一つのとき
$params = new XML_RPC_Value(
    array(
        'wordlist' => new XML_RPC_Value('php')
    ),
    'struct'
);
*/

$message = new XML_RPC_Message('hatena.getSimilarWord', array($params));
$response = $client->send($message);

if (!$response) {
    die($client->errstr);
}

if (!$response->faultCode()) {
    $value = $response->value();
    $data = XML_RPC_decode($value);
    $wordlist = array_map(
        create_function('$w', 'return $w["word"];'),
        $data['wordlist']
    );
    echo implode(', ', $wordlist);
} else {
    // 失敗
    echo 'Fault Code: ', $response->faultCode();
    echo 'Fault Reason: ', $response->faultString();
}
?>


- Programming Web Services With XML-RPC
  0596001193
  http://www.amazon.co.jp/o/ASIN/0596001193/todaysnonsenc-22/ref=nosim/
  Simon St. Laurent (著), Joe Johnston (著), Edd Dumbill (著)
  Oreilly & Associates Inc
  ISBN: 0596001193
  2001/07
  3,698 円

- はてなダイアリー - はてなダイアリーキーワード連想語APIとは
  http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%C0%A5%A4%A5%A2%A5%EA%A ...

- PEAR :: Manual :: XML_RPC
  http://pear.php.net/manual/ja/package.webservices.xml-rpc.php

PHP のデバッグが楽になる?変数の情報を見やすく表示する dBug

  http://dbug.ospinto.com/

  リンク先の説明には var_dump() と比較したみたいに書いてあるが,実際は print_r() を見やすくした感じ.

  以前紹介した PHP 用のデバッグライブラリ Tulpes PHP4 Debug Helper (debuglib.php) と基本的には同じ.
  開発時にはもっぱら debuglib.php のお世話になっているが,dBug も使ってみた.

  サポートされている変数の型は

  • 配列
  • クラス/オブジェクト
  • データベースリソース
  • XML リソース
  • イメージリソース

  実際の表示はどうなるかというと

$variable = array(
    "first"=>"1",
    "second",
    "third"=>array(
        "inner third 1",
        "inner third 2"=>"yeah"),
    "fourth");


  このような配列があった場合

new dBug($variable);


  このように dBug を呼び出すと以下のような表示になる.

  dBug

  便利なのは,上記の画像の場合緑色の部分や薄い緑色の部分をクリックすると,以下のようにその部分が隠れること.
  大きな配列を表示していて目的の部分を見失いそうなときには便利.

  dBug

  また,データベースリソースが扱えるのも便利なところ.
  以下は,mysql_query() の戻り値のリソース型を表示したところ.

  dBug

  大量のデータを扱う場合には向かないと思うがちょっとしたデータを表示したい場合は便利.
  ただし,MySQL のデータベースリソースしかテストしていないようで,SQLite のリソース型は表示できなかった.

  また,PEAR::DB を使った場合はというと,

<?php
require_once 'DB.php';
require_once 'dBug.php';

define('DSN', 'mysql://userid:passwd@localhost/test');

$dbh = DB::connect(DSN);
$sql = 'SELECT * FROM empinfo';
$result = $dbh->query($sql);

new dBug($result->result);
?>


  dBug

  きちんと表示できた.


SQLite で auto-increment なフィールドを作成する方法

  PHP のマニュアルの sqlite_last_insert_rowid の項目を見ていたら

Tip: You can create auto-increment fields in SQLite by declaring them as INTEGER PRIMARY KEY in your table schema.

  つまり,SQLite で auto-increment なフィールドを作りたければ,

INTEGER PRIMARY KEY

  を指定してあげればいいらしい.

  このような記述を見つけたのでテストしてみた.

- SQLite 2.x の場合

$ sqlite test.db
SQLite version 2.8.16
Enter ".help" for instructions
sqlite> CREATE TABLE a (a INTEGER PRIMARY KEY, b TEXT);
sqlite> INSERT INTO a VALUES (NULL, 'test');
sqlite> INSERT INTO a VALUES (NULL, 'test2');
sqlite> INSERT INTO a VALUES (NULL, 'test3');
sqlite> SELECT * FROM a;
a           b
----------  ----------
1           test
2           test2
3           test3

  SQLite 2.8.16 ではうまくいった.
  では,INTEGER PRIMARY KEY に NOT NULL を指定するとどうなるか.

sqlite> CREATE TABLE b (a INTEGER NOT NULL PRIMARY KEY, b TEXT);
sqlite> INSERT INTO b VALUES (NULL, 'test');
sqlite> INSERT INTO b VALUES (NULL, 'test2');
sqlite> INSERT INTO b VALUES (NULL, 'test3');
sqlite> SELECT * FROM b;
a           b
----------  ----------
1           test
2           test2
3           test3

sqlite> INSERT INTO b (b) VALUES ('test4');
sqlite> SELECT * FROM b;
a           b
----------  ----------
1           test
2           test2
3           test3
4           test4

  これもうまくいく.

- SQLite 3.x の場合

$ sqlite3 test.db3
SQLite version 3.1.3
Enter ".help" for instructions
sqlite> CREATE TABLE a (a INTEGER PRIMARY KEY, b TEXT);
sqlite> INSERT INTO a VALUES (NULL, 'test');
sqlite> INSERT INTO a VALUES (NULL, 'test2');
sqlite> INSERT INTO a VALUES (NULL, 'test3');
sqlite> SELECT * FROM a;
a           b
----------  ----------
1           test
2           test2
3           test3

  SQLite 3.1.3 の場合も 2.x と同様にうまくいく.
  INTEGER PRIMARY KEY に NOT NULL を指定するとどうなるか.

sqlite> CREATE TABLE b (a INTEGER NOT NULL PRIMARY KEY, b TEXT);
sqlite> INSERT INTO b VALUES (NULL, 'test');
sqlite> INSERT INTO b VALUES (NULL, 'test2');
sqlite> INSERT INTO b VALUES (NULL, 'test3');
sqlite> SELECT * FROM b;
a           b
----------  ----------
1           test
2           test2
3           test3

sqlite> INSERT INTO b (b) VALUES ('test4');
sqlite> SELECT * FROM b;
a           b
----------  ----------
1           test
2           test2
3           test3
4           test4

  こちらもうまくいく.

- まとめ

INTEGER NOT NULL PRIMARY KEY

  でも

INTEGER PRIMARY KEY

  どちらでも OK.

- sqlite_last_insert_rowid
  http://www.php.net/sqlite_last_insert_rowid

- 追記
  2.8.16 の場合を修正.NOT NULL を指定してもうまくいった.

PHP Phrasebook,Essential Code and Commands (Developer's Library)

  0672328178
  http://www.amazon.co.jp/o/ASIN/0672328178/todaysnonsenc-22/ref=nosim/
  Christian Wenz (著)
  Sams
  ISBN: 0672328178
  2005/09/02
  1,866 円