Ubuntu10.04 に PHP5.4.0 をインストールしてみる

PHP5.4 の新機能を試すために インストールしてみます。

ソースのダウンロード。

$ wget http://jp.php.net/get/php-5.4.0.tar.gz/from/this/mirror \
       -O php-5.4.0.tar.gz

解凍。

$ tar xzvf php-5.4.0.tar.gz
$ cd php-5.4.0/

configure
今回は /usr/local/php540 に入れます。

$ ./configure --prefix=/usr/local/php540

次のようなエラーが出たので libxml2 を入れました。

configure: error: xml2-config not found.
Please check your libxml2 installation.
$ sudo apt-get install libxml2 libxml2-dev

再度 configure 。

$ ./configure --prefix=/usr/local/php540

make & make install 。

$ make
$ make test
$ sudo make install

make test でエラーが出たんですが 今回は新機能のお試しが目的なので とりあえずインストール終了。

node.js の express を使ってみる

node.js には express という Web フレームワークがあり これを使うと簡単に Web システムの雛形が作れるそうなので 試してみます。

次のサイトを参考に進めました。

[参考]
Node.js(Express)アプリの雛形を自動生成する - アインシュタインの電話番号

express をグローバルインストール。
これで express コマンドが使えるようになります。

$ sudo npm install -g express
$ express -v
2.5.8

"-g" オプションでグローバルインストールです。

上記のサイトでやってるように hoge というアプリを作成します。

$ express hoge
$ cd hoge
$ sudo npm link express
$ npm install jade

express と jade も入れています。
express は、グローバルインストールしてあるのでリンクで入れます。 こうするとシンボリックリンクが作成されます。

これでもう雛形ができました。
さっそく動かしてみます。

$ node app.js
Express server listening on port 3000 in development mode

ポート 3000 で Web サービスが起動します。

http://127.0.0.1:3000/

次のような画面が表示されます。

WRITE_0556_01

ソースを修正して表示を "Welcome to Hoge" にします。

ソースを修正するたびに 毎回 Web サービスを起動するのは面倒なので 自動的にリロードしてくれるコマンドを入れます。 これも上記の参考サイトの通りです。

node-dev をグローバルインストールします。

$ sudo npm install -g node-dev

node コマンドの代わりに node-dev コマンドで起動します。

$ node-dev app.js
Express server listening on port 3000 in development mode

Web サービスが起動した状態で ソースを修正します。

バージョンが代わっているせいか 上記の参考サイトとは違うファイルでした。

$ vi routes/index.js
/*
 * GET home page.
 */

exports.index = function(req, res){
  res.render('index', { title: 'Express' }) // "Hoge" に変更
};

Web サービスを起動したコマンドの方を見ると ソースを変更したことによって リスタートしているようでした。

$ node-dev app.js
Express server listening on port 3000 in development mode
[INFO] Restarting
Express server listening on port 3000 in development mode

アクセスしてみます。

http://127.0.0.1:3000/

WRITE_0556_02

表示内容が変わりました。

とりあえずここまで。確かに簡単ですね。

node.js から MongoDB を使ってみる

node.jsmongoose をインストールしたので node.js から MongoDB の値を取得してみます。

次のサイトを参考に進めました。

[参考]
mongooseを使ってmongodbにアクセスしてみる - A Peak Never Ending !

まず MongoDB にデータを登録します。

$ mongo
MongoDB shell version: 1.2.2
url: test
connecting to: test
type "exit" to exit
type "help" for help
> use memo
switched to db memo
> db.memos.save({title:'test title1', body:'test body1'})
> db.memos.save({title:'test title2', body:'test body2'})
> exit

データベースは memo、コレクションは memos にします。

node.js のスクリプト memo.js を作ります。
上記の参考サイトのスクリプトをそのまま貼り付けます。

$ vi memo.js
/*
 * Mongooseでデータを取り出して表示するテスト
 */
var mongoose = require('mongoose');

// スキーマ定義
var MemoSchema = new mongoose.Schema({
  title: String,
  body: String
});
// モデルとして登録
var Memo = mongoose.model('Memo', MemoSchema);

// mongodbに接続
mongoose.connect('mongodb://localhost:27017/memo',
  // memoの部分はデータベース名
  // コールバックでエラー時の処理が書けるみたい。
  function(err) {
    if (err) {
      console.log(err);
    } else {
      console.log('connection success!');
    }
  }
);

// findしてコンソールに出力
Memo.find({}, function(err, docs) {
  if(!err) {
    console.log("num of item => " + docs.length)
    for (var i = 0; i < docs.length; i++ ) {
      console.log(docs[i]);
    }
    mongoose.disconnect()  // mongodbへの接続を切断
    process.exit()         // node.js終了
  } else {
    console.log("find error")
  }
});

実行してみます。

$ node memo.js
connection success!
num of item => 2
{ _id: 4f73edfbb7c76c517dc7eb16,
  title: 'test title1',
  body: 'test body1' }
{ _id: 4f73edffb7c76c517dc7eb17,
  title: 'test title2',
  body: 'test body2' }

node.js から MongoDB の値が取得できました。
これで、できることの幅が広がりました。

Ubuntu10.04 に mongoose をインストールする

作業メモです。
前回の node.js の続きです。 今回は mongoose を入れます。

mongoose は node.js から mongodb を ORM っぽくアクセスするためのライブラリです。

mongoose のインストールには npm を使います。 npm は、前回の node.js のインストールで入っています。

$ which npm
/usr/local/bin/npm

プロキシ認証が必要な環境だとちょっと大変です。

まず npm にプロキシの設定をします。

$ npm config set proxy http://USER:PASSWORD@SERVER:PORT

プロキシを使う環境だと DNS が引けなくても大丈夫だったりしますが npm では下のサイトに書いてあるように名前の解決ができくてエラーになってしまいました。

[参考]
Proxy環境下でnpmインストール :ダメ人間オンライン

DNS を設定するか /etc/hosts に接続先の registry.npmjs.org を追加したりして対応します。

mongoose のインストール。

$ npm install mongoose

・・・と思いきや、またもやエラーが出ます。

npm http GET https://registry.npmjs.org/mongoose

npm ERR! Error: connect ECONNREFUSED
npm ERR!     at errnoException (net.js:670:11)
npm ERR!     at Object.afterConnect [as oncomplete] (net.js:661:19)

次のサイトに書いてあるように https だとうまくいきません。

[参考]
WindowsXP + プロキシ環境でnpmを使う - 四角革命前夜

ホームディレクトリに .npmrc ができているので編集します。

$ vi ~/.npmrc

プロキシの設定が書いてあるので 次の行を追加します。

registry = http://registry.npmjs.org/

もう 1 度インストール。

$ npm install mongoose

今度は成功しました。

Ubuntu10.04 に node.js をインストールする

作業メモです。

まず、ソースをダウンロード。

$ wget http://nodejs.org/dist/v0.6.14/node-v0.6.14.tar.gz

解凍。

$ tar xzvf node-v0.6.14.tar.gz
$ cd node-v0.6.14

configure 。

$ ./configure
Checking for program g++ or c++          : /usr/bin/g++
Checking for program cpp                 : /usr/bin/cpp
Checking for program ar                  : /usr/bin/ar
Checking for program ranlib              : /usr/bin/ranlib
Checking for g++                         : ok
Checking for program gcc or cc           : /usr/bin/gcc
Checking for gcc                         : ok
Checking for library dl                  : yes
Checking for openssl                     : yes
Checking for library util                : yes
Checking for library rt                  : yes
Checking for fdatasync(2) with c++       : yes

私の環境では 最初 次のようにエラーが出たので libssl-dev をインストールしました。

Checking for openssl                     : not found
Checking for function SSL_library_init   : not found
Checking for header openssl/crypto.h     : not found
/home/odin/node-v0.6.14/wscript:374: error: Could not autodetect 
OpenSSL support. Make sure OpenSSL development packages are ...
$ apt-get install libssl-dev 

make と make install 。

$ make
$ sudo make install

node コマンドを実行してみます。

$ node
> 3 + 5
8
> var a = 3;
undefined
> console.log(a);
3
undefined

これで終わりです。

MongoDB を使ってみる 4

今回は、実際にデータを登録して見ます。 MongoDB は、 事前にテーブルなどを作成しません。 (スキーマレスと呼ぶそうです)

データベースと言えば SQL なので 次のサイトが わかりやすくて参考になりました。

[参考]
SQL脳に優しいMongoDBクエリー入門 - あるプログラマーの後悔日誌

MongoDB の操作は JavaScript な感じです。

> db.books.insert({ name : "a" });

スキーマレスなので、 何の定義もなく いきなりこんな記述で、データを登録できてしまいます。

books の部分が『コレクション』で RDBMS だとテーブルのようなものだと思います。

そこに JSON 形式のデータを INSERT しました。

{ name : "a" }

"show collections" で コレクションの一覧を参照できます。

> show collections
books
system.indexes

さっき登録した books があります。

もう 1 件登録してみます。

> db.books.insert({ name : "b" });

コレクションの中身を見るには次のように コレクションに対して find() メソッドを使用します。

> db.books.find();
{ "_id" : ObjectId("4f5ff9e69d12fb10f7c2955f"), "name" : "a" }
{ "_id" : ObjectId("4f647e7b9d12fb10f7c29560"), "name" : "b" }

上のように暗黙的に "_id" が作成されて データが管理されます。

もう少し複雑なデータを登録してみます。

> db.books.insert({ name : "c", detail : { size : "b5", page : 120 }});
> db.books.find();
{ "_id" : ObjectId("4f5ff9e69d12fb10f7c2955f"), "name" : "a" }
{ "_id" : ObjectId("4f647e7b9d12fb10f7c29560"), "name" : "b" }
{ "_id" : ObjectId("4f6480479d12fb10f7c29561"), "name" : "c", "detail" : { "size" : "b5", "page" : 120 } }

このように MongoDB は 1 つの "_id" に対して 1 つの JSON 形式のデータ(ドキュメント)を格納する形式のようです。

Web のインターフェースを使って見てみます。

http://127.0.0.1:28017/test/books/

test の部分がデータベース名、bookes がコレクション名です。

{
  "offset" : 0,
  "rows": [
    { "_id" : { "$oid" : "4f5ff9e69d12fb10f7c2955f" }, "name" : "a" } ,
    { "_id" : { "$oid" : "4f647e7b9d12fb10f7c29560" }, "name" : "b" } ,
    { "_id" : { "$oid" : "4f6480479d12fb10f7c29561" }, "name" : "c", "detail" : { "size" : "b5", "page" : 120 } }
  ],

  "total_rows" : 3 ,
  "query" : {} ,
  "millis" : 0
}

こんなデータが返ってきました。
これなら Ajax や node.js などからも 簡単に連携できそうです。

MongoDB を使ってみる 3

今回も mongo クライアントの話です。

mongo クライアントを起動すると デフォルトでは、次のように test というデータベースに接続されます。

$ mongo
MongoDB shell version: 1.2.2
url: test
connecting to: test
type "exit" to exit
type "help" for help
>

"show dbs" で データベースの一覧を表示します。

> show dbs
admin
local
test

"use [データベース名]" で データベースを変更します。

> use local
switched to db local

DB に接続するというよりは カレントの DB を変更する、という感じですね。

Firefox の 3D ビューで遊んでみる

Firefox11 の 3D は 「何かできそう」な気がする機能なので 思いつくままに遊んでみたいと思います。

WRITE_0547_01

立体を作ってみる

3D ならでは、ですね。

超手抜きでピラミッド・・・。

WRITE_0547_02

頑張れば塔やビルとか作れそうです。

メッセージを隠してみる

3D ビューにしないとわからないメッセージを埋め込んでみます。

何もない HTML ですが・・・

WRITE_0547_03

3D ビューにすると文字が浮かんできます。

WRITE_0547_04

[サンプル]
3D ビューに文字を埋め込んでみる

他にも色々できそうな気がします。
こういう「何かできそう」という機能は楽しいですね。

Firefox11 で「3D ビュー」を有効にする

Firefox の 11 では ページインスペクタに「3D ビュー」という コンテンツの階層を 3D で表示できる機能が追加されました。

WRITE_0546_01

[参考]
Firefox 11.0 リリースノート

[Ctrl]+[Shift]+[I] で表示する ページインスペクタ(メニューから表示する場合は「ツール」→「Web 開発」→「調査」です)の 右下に「3D」ボタンが出るはずなのですが、 自分が使ってる環境(複数)では表示されませんでした。

WRITE_0546_02

表示する方法を教えてもらったのでメモとして上げておきます。

まず about:config で設定画面を表示します。
Firefox にも表示されますが設定の変更は危険ですので 理解したうえで自己責任で試してください。

WRITE_0546_03

検索で「webgl」を探します。
出てきた中の「webgl.force-enabled」を true に変更します。

webgl.force-enabled

WRITE_0546_04

次に「tilt」を検索して 出てきた中の
「devtools.tilt.force-enabled」を true に変更します。

WRITE_0546_05

Firefox を 再起動します。

ページインスペクタを表示すると「3D」ボタンが追加されます。

WRITE_0546_06

押すと 3D ビューが開始します。
マウスのホイールやドラッグ、キーボードのカーソルキーなどで 動かすことができます。

WRITE_0546_07

同時に HTML ソースや スタイルも見れるので 3D にすれば、深いところにある定義も指定しやすくなります。

MongoDB を使ってみる 2

今回は mongo クライアントを使ってみます。

Ubuntu10.04 の場合、mongodb パッケージをインストールすると mongo クライアントも入ります。

起動します。

$ mongo
MongoDB shell version: 1.2.2
url: test
connecting to: test
type "exit" to exit
type "help" for help
>

出力されている通り help 表示してみます。

> help
HELP
  show dbs                 show database names
  show collections         show collections in current database
  show users               show users in current database
  show profile             show most recent system.profile entries with time >= 1ms 
  use <db name>            set curent database to <db name>
  db.help()                help on DB methods
  db.foo.help()            help on collection methods
  db.foo.find()            list objects in collection foo
  db.foo.find( { a : 1 } ) list objects in foo where a == 1
  it                       result of the last line evaluated; use to further iterate 

なんか色々と出ました。

exit で終了します。

> exit
bye
$

たぶん続きます。

Linux のディストリビューション名を調べる

入ってる Linux のディストリビューションがわからない場合 Ubuntu だと次のように /etc/lsb-release を見ればわかるんですが CentOS は?と聞かれたのでメモ。

$ cat /etc/lsb-release

[参考]
インストールした Linux ディストリビューション名とバージョンを確認するには - PRiMENON:DiARY

上の参考サイトによると とりあえず /etc/issue 、 あとは /etc の下に xxxx-release みたいなファイルがあるようです。

なので次のようにしておけばよいかと。

$ cat /etc/issue /etc/*-release

MongoDB を使ってみる 1

ドキュメント指向とやらの MongoDB を使ってみます。

まずはインストール。
環境はいつもの Ubuntu10.04 です。

$ sudo apt-get install mongodb

パッケージがあるので apt-get します。
ただ、↓のような感じで結構色々必要なようでした。

4 upgraded, 140 newly installed, 0 to remove and 121 not upgraded.
Need to get 66.1MB of archives.
After this operation, 258MB of additional disk space will be used.

インストールが完了すると、すでに起動しています。

$ ps ax | grep mongo
28350 ? Ssl 0:00 /usr/lib/mongodb/mongod --config /etc/mongodb.conf

起動の引数になっていた設定ファイルは以下のようでした。

$ cat cat /etc/mongodb.conf
# This is an config file for MongoDB master daemon mongod
# it is passed to mongod as --config parameter

logpath = /var/log/mongodb/mongod.log
dbpath = /var/lib/mongodb/

# use 'true' for options that don't take an argument
logappend = true
bind_ip = 127.0.0.1
#noauth = true

LISTEN ポートは 27017 と 28017 が追加されてました。

$ netstat -ant
tcp  0  0 127.0.0.1:27017  0.0.0.0:*  LISTEN  -
tcp  0  0 127.0.0.1:28017  0.0.0.0:*  LISTEN  -

27017 が DB 接続用のポート(デフォルト)で、 それに +1000 した 28017 は管理用の Web ページのようです。

http://127.0.0.1:28017/

これにアクセスすると下の参考サイトような感じで 色々とデータベースの情報が見れるようです。

[参考]
HTTPインターフェース - Docs-Japanese - 10gen Confluence

また、データベースやクエリーを URL に設定してアクセスすると データを text/plain の JSON 形式で出力してくれるので Web サービスとしても簡単に利用できそうな気がします。

PHP の配列 その 6

今回は配列カーソルの話です。

PHP の配列には、『現在配列のここを見てますよ』というのを覚えておくカーソルというものがあります。

例えば次のような配列があるとします。

$fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');

each 関数は 配列のキーと値のペアを返しますが 使用するたびに次の要素に移動します。

$a = each($fruit); // 'a', 'apple' が代入される
$b = each($fruit); // 'b', 'banana' が代入される
$c = each($fruit); // 'c', 'cranberry' が代入される
$d = each($fruit); // FALSE が代入される

こんなことができるのは 配列が内部的に現在の位置を覚えているためです。

次の while ができるのも同じ理由です。

while (list($key, $val) = each($fruit)) {
    echo "$key => $val\n";
}

カーソルを初期化するための reset という関数があります。

reset($fruit);
while (list($key, $val) = each($fruit)) {
    echo "$key => $val\n";
}

他で参照されている可能性がある場合 上のようにループ処理の前では カーソルを初期化します。

気をつけなくてはならないのは、 カーソルは「配列を別の変数に代入すると初期化される」という仕様です。 「配列に変数を」ではなく「変数に配列を」なのがわかりにくいところです。

次のコードは無限ループになってしまいます。

$fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');

while (list($key, $val) = each($fruit)) {
    echo "$key => $val\n";
    $food = $fruit;  // この処理でカーソルが初期化される
}

上の処理は次の処理と同じです。

$fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');
$food = $fruit;

while (list($key, $val) = each($fruit)) {
    echo "$key => $val\n";
    reset($fruit);  // この処理でカーソルが初期化される
}

PHP の配列 その 5

今回は list の話です。

次のように、配列の形で値を返す関数があるとします。

function test() {
    return array(1, 2, 3);
}

この関数から返る値を 配列を使わずに受ける場合 list という PHP の言語要素を使用します。

list($a, $b, $c) = test();

変数 $a,$b,$c に それぞれ 1,2,3 が格納されます。

list は関数ではなく言語の構造なので 変わった記述ができます。 例えば次のように 受け側の数が少なくても OK です。

list($a, $b) = array(1, 2, 3, 4);
var_dump($a, $b);
int(1)
int(2)

受け側の変数が 2 つなので 配列も 2 つ目までが格納されます。

次のように変数を省略することもできます。

list(, $a, , $b) = array(1, 2, 3, 4);
var_dump($a, $b);
int(2)
int(4)

この場合、変数を省略した 1 つ目、3 つ目は飛ばされて 2 つ目と 4 つ目の値が格納されました。

あと、list は数字がキーの要素のみ扱うので 文字列がキーの配列は無視されてしまいます。

例えば次の例では、2 つ目と 3 つ目の文字列がキーの 要素は無視されるので $a,$b には 0,1 が入ります。

list($a, $b) = array(0 => 0, 'a' => 1, 'b' => 2, 1 => 3);

次の例の場合、キーが 1 の要素が存在しないため NOTICE が発生して $b には NULL が入ります。

list($a, $b) = array(0 => 0, 2 => 2);

要するに list は次のような処理になるわけです。

list($a, $b, $c) = $array;
  // ↑
  // この 2 つは同じ処理
  // ↓
$a = $array[0];
$b = $array[1];
$c = $array[2];

そのため、キーが負の数字の場合も無視されます。

list($a, $b) = array(1 => 1, -5 => -5, 0 => 0);

この場合、$a,$b には 0,1 が入ります。

なかなか便利な list ですが、 受け側も配列の場合、気をつけなくてはならないことがあります。

list は 右側から順に値を格納していきます。

つまり次のような場合、キーの値と定義順が逆になります。

list($a[0], $a[1]) = array(1, 2, 3, 4);
print_r($a);
Array
(
    [1] => 2
    [0] => 1
)

格納される値は変わりませんが キーが 1,0 の順で定義されています。 そのため、for と foreach で結果が変わってしまうようなことになります。

for ($i = 0, $c = count($a); $i < $c; $i++) echo $a[$i];
int(1)
int(2)
foreach ($a as $v) echo $v;
int(2)
int(1)

さらにキーを省略した場合は もっと大変なことになります。

list($a[], $a[], $a[]) = array(1, 2, 3, 4);
print_r($a);
Array
(
    [0] => 3
    [1] => 2
    [2] => 1
)

右側から順に格納されるため キーまで逆に付いてしまいます。

オマケですが、次のように list をネストさせることもできます。

list($a, list($b, $c)) = array(1, array(2, 3));

PHP の配列 その 4

前回から間が空いてしまいましたが PHP の配列に関する話を またやっていこうと思います。

PHP の配列は キーを省略して定義することができます。

$a[] = "a";
$a[] = "b";
$a[] = "c";
print_r($a);

キーを省略した場合は その配列の最大のキーの値に 1 を足した値がキーになります。 (配列が空の場合は 0 になります)

Array
(
    [0] => a
    [1] => b
    [2] => c
)

ただし、ここで最大値を求めるキーは 数値のキーのみになります。 文字列のキーが存在してもそれは無視されます。

$a["test1"] = "a";
$a["test2"] = "b";
$a[] = "c";
$a[] = "d";
print_r($a);
Array
(
    [test1] => a
    [test2] => b
    [0] => c
    [1] => d
)

このように文字列のキーは無視して 数値のキーが設定されます。

次のようなこともできます。

$a["test1"] = "a";
$a[] = "b";
$a["test2"] = "c";
$a[] = "d";
print_r($a);
Array
(
    [test1] => a
    [0] => b
    [test2] => c
    [1] => d
)

この仕様を利用して 配列のキーを 1 から始めることもできます。

$a[1] = "a";
$a[] = "b";
$a[] = "c";
print_r($a);
Array
(
    [1] => a
    [2] => b
    [3] => c
)

次のようにキーの値の間が空いていても詰められません。

$a[10] = "a";
$a[] = "b";
$a[20] = "c";
$a[] = "d";
$a[5] = "e";
$a[] = "f";
print_r($a);
Array
(
    [10] => a
    [11] => b
    [20] => c
    [21] => d
    [5] => e
    [22] => f
)

PHP 4.3 からキーの最大値が、 負の数値の場合
キーは最大値 +1 ではなく 0 になります。

$a[-5] = "a";
$a[] = "b";
Array
(
    [-5] => a
    [0] => b
)

lua に触れてみる 4

lua は変数に型を定義しませんが 型は存在します。 他の型のない言語と同じように 変数に色々な型を入れることができます。

適当に試してみます。

$ lua
>

対話モードに入りました。

> = type(a)
nil

type は引数の型を返す関数です。
変数 a が定義されていない状態では nil を返します。

> a = "test"
> = type(a)
return

> a = 2.2
> = type(a)
number

> a = true
> = type(a)
boolean

> a = {1,2,3}
> = type(a)
table

変数には関数も入れることができます。

> a = type
> = type(a)
function

当然、次のようなこともできます。

> a = type
> = a(a)
function

lua に触れてみる 3

lua は変数に型がない言語としては かなり速いそうです。

適当に試してみます。

$ time lua -e 'for i=1,1000000 do j=i end'

real    0m0.029s
user    0m0.030s
sys     0m0.000s
$ time perl -e 'for($i=0;$i<1000000;$i++){$j=$i;}'

real    0m0.143s
user    0m0.150s
sys     0m0.000s
$ time php -r 'for($i=0;$i<1000000;$i++)$j=$i;'

real    0m0.160s
user    0m0.140s
sys     0m0.020s
$ time bash -c 'for ((i=0;i<1000000;i++)) do j=i; done'

real    0m6.276s
user    0m5.910s
sys     0m0.180s

厳密な比較ではないですが なんとなく速そうですね。

Google サイト内検索

Amazonアソシエイト