2011年12月14日水曜日

コンポーネント指向について調べてみた

イベント駆動から始まって、次はコンポーネント指向について調べてみました。

いつものようにWikipediaでコンポーネント指向を見ると、まったくわけが分かりません。いや、部品から組み立てようということらしいんですが、それって当たり前だし、ほとんど全てのフレームワークはコンポーネント指向でしょう。

要はGUIのあれと同じ・・・

困って別のサイトを見てたら、いい解説がありました。
全然別のフレームワークの紹介なのですが、上手に説明されていたので、そのまま抜き出します。
コンポーネント指向のフレームワークでは,リクエストごとではなく,コンポーネントが発火するイベントに対するハンドラとして処理を記述します。これは既存のGUIアプリケーションと同様のモデルです。
http://itpro.nikkeibp.co.jp/article/COLUMN/20070305/263875/
既存のGUIアプリと同じモデルだそうです。
あれ、イベント駆動についての最初の例と同じだ。

つまりコンポーネント指向とは、
・ウェブの画面上の各要素に対して、
・サーバー上のクラスを一対一に対応付けて処理する、
という設計方針という意味だと理解しました。

一方、イベント駆動とは、コンポーネント指向を実現するための実装技術なのでしょう。

Yiiのコンポーネントについて想像をめぐらす

YiiのウェブサイトにComponentについての説明があります。コンポーネントとは、パブリックなプロパティを持って、イベントを発生・処理できるとあります。

いまひとつよく分かりませんが、Yii Blog Demoを見ていて、面白いフォーム構造をしているのに気がつきました。

新規ポストの登録で、タイトルの名称は
<input type="text" name="Post[title]" />
となってます。

残念ながらデモのソースコードが見つからなかったので、想像ですが、おそらくPostというコンポーネントクラスが存在するのでしょう。新規投稿をすると、何らかのイベントが発生してPostコンポーネントを呼び出して、titleというプロパティに値を設定して、DBに保存する、という流れになっているのではないでしょうか。

ちなみにコメントの追加では、名前のところは
<input type="text" name="Comment[author]" />
です。

ポスト先を見ると、
http://www.yiiframework.com/demos/blog/index.php/post/1/Welcome%21
Commentという文字がURI内に見当たりません。
どうやってCommentコンポーネントに処理を渡しているのか・・・
単にURIを解析して対応するコンポーネントを決定しているわけではなさそうです。

バインディング

最後に・・・

このように、フォームや画面上に表示された要素と、バックエンド側での処理クラスを関係付けることをデータバインディングと呼ぶようです。

最初にこの言葉を聞いたのがJavaServer Faces(JSF)でした。
調べてみるとWindowsなど様々な場所で使われてる技術・言葉みたいですね。

リクエストを処理→テンプレートで表示、というウェブの作りとはちょっと違っていて面白いですね。

Underscore.phpとarryと_wwの速度比較してみた

PHP Advent jp 2011で書いた_ww(Underscore-Walla-Walla)ですが、せっかくなので他の実装と速度比較してみました。

比較対象は、実装の元ネタの__と、同じくPHP Adventで発表されたarryです。

また比較用のコードとデータはarryで使われていた「悲しき今シーズンの結果」を利用させてもらいました。ありがとうございました。


まずはリファクタリングから

が、利用するにはsortがないし、クラスは二つに分かれてるし。
最初は_wwのリファクタリングから始めました。

まずはgitでブランチを切って、開発開始です。
次にテストクラスを作成してから、さくっとクラスをマージ。
簡単に出来ました。テストがあると、変更するのに気が楽ですね。

速度比較について予測してみる

測定する前に予測を立てます。

まずは、自分の_wwが一番遅いと予想。
理由はマジックメソードを使っているので。

一番早いのはShinさんのarryクラス。
最初からチェーンするようにメソードが組み立てられているので、一番早いはず。

すると中間は、Underscore.php。
これもマジックメソード使ってないけれど、各メソード内での処理があるので、チェーンすると少し処理が増えると予想。

速度比較の結果

ソースコードはgistで公開してあります。
インストールですが、どこかのフォルダーでgit bashを開始して、
git clone git://gist.github.com/1460352.git gist-1460352
git clone git://github.com/shin1x1/arry.git
git clone git://github.com/brianhaveri/Underscore.php.git
git clone git://github.com/asaokamei/_ww.git
と打ち込んで、からgist-1460352内のcompare.phpを走らせてください。
測定ですが、Core2Duo 2.13GHzのWindows Vistaでの結果です。

2.2504210472107  // 素のPHP
5.0997409820557  // arry
9.1629009246826  // Underscore.php
7.959762096405  // _ww

予想通りarryが一番早かったです。
素のPHPに比べて2倍強になりました。結構、速い気がします。

意外だったのがUnderscore.phpより_wwのほうが速かったこと。
何度か走らせると、値が結構変わるので「ほんの少し速い」だけですが、各メソード内での処理が意外と重いのでしょう。

PHPのプロファイリング

そういえばプロファイリング(速度の測定)なんて何年振りです。
PHPだとxdebugを使えば出来るようですが、今回は簡単な関数を自作して計ることにしました。最近使い始めたNetBeansから直接測定結果が見られると便利なんですけどね。

2011年12月13日火曜日

Pradoのイベント駆動を想像してみる

PradoというPHPフレームワークのイベント駆動がどうなっているのか、Pradoのホームページを眺めているうちに、何となく想像がついてきました。

ただし、ソースコードは一切読まずの想像ですので、間違ってるかもですが。

QuickStartサンプルから

単純なラジオボタンのデモですが、このページからソースコードを眺めると、

  • Home.pageの97行目:
    <com:TButton Text="Submit" OnClick="selectRadioButton" />
  • Home.phpの10行目:
    public function selectRadioButton($sender,$param)

とあって、サブミットボタンがクリックされると「selectRadioButton」というイベントが発生して、HomeクラスのselectRadioButtonメソードに処理を渡しているようです。

なるほど、Pradoのいうイベント駆動は、まさGUIでのイベント駆動に近いようです。JavaScriptを使ってHtml上のボタンなどにイベントを発生させて、サーバー側のPHPクラス・メソードに結び付けているのでしょう。

Yiiはイベント駆動ではないのか?

さて、Pradoは「終了?」したのか、
新しい「Yii」というフレームワークの開発を始めているということです。

Yiiの特徴は「コンポーネント指向」

これまた新しい言葉が・・・
いや、よく見たらPradoでも同じ言葉を使ってました。

ともあれ、Yiiはイベント駆動をやめたのでしょうかね?

これまた想像ですが、Restが優勢になってイベント駆動というパラダイムが分かりにくくなったからではないでしょうか?

要するにリクエストがあった場合に、どのクラスのメソードに処理をさせるのかを決定できればいいわけで、RestならURIだけで決定できます。ボタンクリックでわざわざイベントを発生させるのは無駄な気がします。

さ、次は「コンポーネント指向」について調べてみよう。

2011年12月8日木曜日

PHPでイベント駆動(event driven)って何だろう?

PHPのPradoというフレームワークがイベント駆動で、すごいらしい。
で、イベント駆動って何だろう?と思って、ちょっと調べてみた。

オブザーバーパターン

イベント駆動というと、jQueryを使って、あるDOM要素にクリックしたら~~する、というのが、まさによい例だそうです。
$( '#button' ).click( function() { alert( 'hi' );});

が、一般的にオブザーバーパターンというらしい。

しかし、イベント駆動のPHPフレームワークと言われても、サーバー側でどうイベントを利用するのかぴんと来ません。

こういうときは、自分で書いてみる。


Stackoverflowで見つけた「Event-driven architecture and hooks in PHP」を参考に、自分で書いてみました。

イベント駆動というよりは、「dumb hook」あるいは「単なるdispatcher」と書いてあるように、非常に簡単なものです。

ともかく、

eventHookというクラス(github)が出来ました。。

最初にイベント名に対して実行する関数(クロージャーでも何でも)を登録します。
eventHook::hook( 'some_event', 
  function() {  echo 'do something'; });
イベント発行は、イベントメソードを叩きます。
eventHook::event( 'some_event' );
簡単だなぁ。

でも、イベント実行時に必要な情報はどうやって渡すんだろう?

そのとき、例に挙げられてた通信バッファーを思い出した。
通信を受け取ると、(OSが?)受け取った内容をメモリ上のバッファーに書き込み始めます。オブザーバーはバッファーを監視していて、バッファーの状態が変わるとイベントを発行、関連付けられてた何かを実行します。当然バッファーに必要な情報が入っている「はず」です。

つまりイベントとは観察している対象が変わることであり、対象自体に情報があるはずです。

eventHookクラスの場合は、eventメソードのイベント名はあくまでバッファーの場所(の代わり)であり、バッファー内の情報はeventメソードと一緒に渡せばいいわけです。
説明すると難しいですが、コードにすると簡単。
eventHook::hook( 'more_event', 
  function( $arg1=NULL, $args=NULL ) {
    echo "doSomething: '$arg1', '$args'\n";
});
eventHook::event( 'more_event', 'arg#1', 'arg#2' );
// 出力:doSomething: 'arg#1', 'arg#2'
単にeventメソードに必要そうなデータを渡せば、実行関数にも同じものを渡します。
うん?実行関数で生成された何か(プライマリキーとか)受け取りたい場合はどうするんだろう?別のイベントを発行してもらうのかな???やばそうな匂いがするなぁ。

で、イベント駆動って何?

未だに肝心の「イベント駆動」がよく分かりません。
多分、イベントを連続して発行することでフレームワークの動きを実装しているのでしょう。MVCの代わりみたいなイメージなのかな。

そういえばワードプレスにもフックがたくさんあると聞いたことが・・・
あぁ、こういうことか。

先は長いなぁ。

2011年12月6日火曜日

PHPからlocalStorageに書き込み・読み込み(PHP Advent JP 2011)

PHP Advent Calendar jp 2011」6日目(12月6日)のエントリーです。

初めてアドベントカレンダーに参加したのですが、いきなり内容が被ってしまいました。そのまま公開しようと思ってたのですが、急遽ネタを思いついたので、早速作ってみました。

ちなみに最初のネタは_ww(アンダースコア・ワラワラ)というクラスです。

PHPからローカルストレージを使う

HTML5とスマートフォンが登場してから、クライアント(ブラウザー側)の技術が急速に進化していると感じます。今までのPHPでサーバー側でHTMLを構築するとは違ったウェブの構築になるのではないでしょうか。

という前振りで、HTML5で登場したlocalStorageをPHPからを操作するクラスを作ってみました。

ソースコードはgithubのphpadventjp2011で公開してあります。
localStorageクラスとサンプルが入っています。

一応、妙なスクリプトを入れられても大丈夫なはずですが・・・
セキュリティに関しては自己責任でお願いします。

基本的な使い方

基本的な考え方は
  1. PHPの変数をlocalStorageに保存するJavaScriptを自動生成。これをHTMLのどこかに貼り付けると、ブラウザーにデータを保存。
  2. ブラウザーのlocalStorageから値を読み出て隠しタグに変換するJavaScriptを自動生成。これをHTMLのフォーム内に貼り付けて、サブミットしてもらう。
  3. フォームデータを受け取るときに隠しタグから値を取得。
です。

ローカルストレージに保存してみる

PHPコードです。

require_once './localStorage.php';
$data = array( 'test'=>'test', 'more'=>'more' );
$js = localStorage::saveStorage( $data, 'testID' );
$js2 = localStorage::saveStorage( 'just value', 'valID' );
この$jsや$js2をHTML内で出力すると、$dataの中身をブラウザーに保存します。

ちなみに生成されたJavaScriptです。
PHP変数をJSONに変換して、localStorageに保存しています。
<script>localStorage.setItem( 
'saveID_testID', '{"test":"test","more":"more"}' );
</script>
この後、クライアント側で保存した値を使えるようになります。

PHPで受け取ってみる

面倒ですが、まずはフォームが必要です。そこで次のPHPコードを走らせてJavaScriptを生成します。
require_once './localStorage.php'; 
$js = localStorage::loadStorage( 'testID' );
$js2 = localStorage::loadStorage( 'valID' );
保存する際につけた名前(「testID」や「valID」)を指定します。

生成されたJavaScriptです。
これをフォームのどこかに出力しておきます。
<input type="hidden" name="saveID_testID" id="saveID_testID">
<input type="hidden" name="saveID_testID_EncType_" value="json">
<script>
 document.getElementById( 'saveID_testID' ).value =
 localStorage.getItem( 'saveID_testID' );
</script>

<input type="hidden" name="saveID_valID" id="saveID_valID">
<input type="hidden" name="saveID_valID_EncType_" value="json">
<script>
document.getElementById( 'saveID_valID' ).value =
localStorage.getItem( 'saveID_valID' );
</script>

PHPで受け取ってみる(パート2)

こんなPHPコードで受け取れます。
require_once './localStorage.php'; 
$data = localStorage::loadPost( 'testID' ); 
$val = localStorage::loadPost( 'valID' );
保存する際につけた名前(「testID」や「valID」)を指定してください。

保存したままの値が入ってくる(はず)です。

使い方を考えてみる

勢いで作ったクラスですが、どう使うか考えてみました。
意外と使いどころがないw

フォームに一旦出力するので使い勝手が悪い気がします。サーバーだけで使うデータならセッション使ったほうが楽でしょう。ただクライアント側のJavaScriptと変数を共有したい場合に便利かもと思ってます。

Underscore-Walla-WallaというPHPクラスを作ってみた

初めてアドベントカレンダーに参加したのですが、いきなり内容が被ってしまいました。別のトピックを考えたのですが、思いつかず。まぁ実装が違うので、このままで参加することにしました。別ネタを思いついたので、そちらを書きました。

Underscore.phpという面白いクラスが紹介されてました。

なんでもはunderscoreというjavaScriptをPHPにポートしたものだそうです。何が面白いって、

jQueryみたいにPHPコードが書ける

早速ソースコードを追いかけてみたのですが、すぐ理解できなかったので自分で書き直してみました。なるほど、分かってしまえば、単純なことを丁寧に積み重ねていたんですね。

理解のために書いたコードですが、せっかくなので、衆目の下に晒すことにしました。クラス名は_ww。アンダースコア・ワラワラと読んでください。
ちなみにWalla Wallaはアメリカ合衆国はワシントン州にある小さな町です。昔、あの近くのもっと辺鄙な場所で学生してたことがあったので、名前に使ってみました。

簡単な使い方。

まずは一番簡単なスタティック・メソードで呼ぶ方法。

// use as static method. 
$ww = _ww::each( 
    array( 1,2,3 ), 
    function($n) { echo $n . "\n"; } 
  );
実際のeachの中身は、_wwmというクラス内で定義されています。
class _wwm
{
  static public function each( $collection, $iterator ) {
    if( !empty( $collection ) )
    foreach($collection as $k=>$v) {
      call_user_func($iterator, $v, $k, $collection);
    }
  }
}
$collectionが配列で、foreach文を使って各要素について$iterator関数を呼んでいます。

これだと、普通なPHPといった感じです。
次はメソードチェーンをしてみます。

チェーンで次々と処理する

eachとかをつなぎ合わせてチェーンのように使えます。
// use as a chain of methods. 
_ww::chain(  array( 1,2,3 ) )
  ->each(  function($n) { echo "in chain $n" . "\n"; } )
  ->get(   $mid )
  ->map(   function($n) { return $n * 2; } )
  ->value( $result );
var_dump( $mid );
var_dump( $result );
ポイントは、

  • chainメソードで始めること。
  • valueメソードでチェーンを終了して、結果を受け取ること。
  • チェーンの途中で値を使いたい場合はgetメソードが使うこと。

といった所でしょうか。

チェーンの仕方を理解する

一体どうなっているか、_wwクラスの中を少し見てみます。
class _ww
{
  private $_wrapped = NULL;  // holds the data
  
  public function __construct( $collection ) {
    $this->_wrapped = (array) $collection;
  }
  public static function chain( $collection ) {
    return new _ww( $collection );
  }
}
chainメソード内で、自分をnewしてます。いや、自分自身のインスタンスを作成してます。入力された配列はオブジェクト内の$_wrappedという変数に保存されます。

で、作ったオブジェクトをすぐにreturnしてます。
これでチェーンが始まるというわけです。

メソードの呼び出し方は?

次はeachを呼ぶのですが、_ww自体にはeachなどのメソードは実装されてません。その代わりに「magicメソード」と呼ばれる__callメソードが呼ばれます。
class _ww
{
  public function value( &$result=NULL ) {
    $result = $this->_wrapped;
    return $this->_wrapped;
  }
  public function __call( $method, $args ) {
    $arg  = array_merge( array( $this->_wrapped ), $input );
    $return = call_user_func_array( "_wwm::$method", $arg );
    if( !is_null( $return ) ) {
      $this->_wrapped = $return;
    }
    return $this;
  }
}
この中で、最初に$_wrappedに保存しておいた配列を呼び出して、残りの引数と一緒にして、実際のeachメソードを呼び出しています(call_user_func_array( "_wwm::$method", $arg )の部分)。
ここらへんがShinさんのarryクラスと実装が違うところです。あちらはeachとかが最初からチェーン内で使われることを想定して書かれてます。一方、元ネタのUnderscore.phpは書くメソードがチェーン内にいるかどうかを判定して、引数と返値を制御しています。ちなみに、_wwはスタティックはチェーン外、インスタンスの場合はチェーン内と割り切って、__callマジックメソードで引数などを作り直しています。
メソードの最後にreturn $thisをして次のチェーンへつなぎます。
この後のmapメソードも、同じように処理されます。ただmapだと返り値があるので、$_wrappedの値が変わることになります。

こうして次から次にチェーンにしたがって、$_wrappedに入っている配列に対して処理を行ってゆくことが出来ます。

チェーン部分の出力です

in chain 1       // each内で出力
in chain 2
in chain 3
array(3) {       // $midのvar_dump
  [0]=>  int(1)
  [1]=>  int(2)
  [2]=>  int(3)
}
array(3) {       // $resultのvar_dump
  [0]=>  int(2)
  [1]=>  int(4)
  [2]=>  int(6)
}

最後に

_wwのソースコードはgithubでホスティングしています。
ライセンスはMITライセンスです。

コードをちゃんと見ると、テストコードが入り込んでる、クラスが二つに分かれた、とか問題はたくさんあるのですが、ひとまず動いたので今回はここで完了としました。

よく「車輪の再発明」とか言われますが、こういう小さなクラスを書くのはとても楽しいです。実際に使うとか考えると微妙ですが、細かいことは気にしないで作ってみると楽しいと思います。

2011年12月1日木曜日

Synergyで「failed to save autostart configuration」エラーが出る

Windows VistaでSynergyを1.3.1から1.3.8に
アップグレードして、「Start」ボタンを押すと

failed to save autostart configuration

というエラーメッセージが出て動きませんでした。

◆解決方法:


このページにて発見。
http://code.google.com/p/synergy-plus/issues/detail?id=256
まぁグーグルの一番最初のエントリですが。

まず、synergy.exeを「管理者として」走らせます。
自分のPCだと以下のフォルダーにありました。
C:\Program Files\Synergy\synergy.exe

次に、Optionsの中の「AutoStart...」ボタンを押す。

「Uninstall」を押して、一旦オートスタートをリセット。
OKを何度か押す。

これで解決しました。

例によって、管理者権限の問題のようですね。

2011年11月30日水曜日

PHPのNullとissetとarray_key_exists

先ほど気がついたのですが、PHPのissetの動きを勘違いしていました。

$var=NULL;
isset( $var ); // returns FALSE
is_null( $var ); // return TRUE
is_null( $none ); // E_NOTCE

issetはNULL値をFALSE判定します。

いつから勘違いしてたんだろう。

たとえばis_nullで調べればいいのですが、
変数が存在しない場合はE_NOTICEが出ます。

実は、あることにNULL値を使おうと思ってたのです。PHPだと空白('')、FALSE、NULLと三種類あるので便利だなぁと思ってたのですが、変数の判定が出来なければ使いにくい。困ったぞ、というわけです。

で、気がついたのがarray_key_existsを使うこと。
こういう構造になっている場合、NULLでも存在判定が出来ます。

$data[ 'test' ] = NULL;
array_key_exists( 'test', $data ); // returns TRUE

何とかなりそうです。

2011年11月28日月曜日

formUpDownというJavaScript

Ctrl+矢印キーで、テーブル内のフォーム要素間を動き回るコードを書きました。
長らくリンク切れになってましたが、デモをアップしました。

http://www.workspot.jp/tech/formUpDn/formupdnTable.html

かなり格好の悪いHTMLですが、実際に動きます。
ちなみにソースコードはgithubにあります。

まだjQueryのプラグイン化すらしてませんが。

実際に使うと分かりますが、セレクト要素の動きが変です。
作ったときから、そして今でも、更にはブラウザーによって挙動が変わります。

こういったところは、JavaScriptの問題かなと考えてます。

2011年11月23日水曜日

yet another な Validator クラス

なんで、世の中に数あるValidatorクラスを作ってるのか、
などと自問自答しながら作ってます。

開発中なのですが、特徴をはっきりさせておくために、ブログでまとめます。

◆まず、面白くも何ともない普通の特徴から。

  • できるだけ簡単に使えるインターフェース、
  • タイプ(テキスト、メールアドレスとか)を指定すると前もって決めておいたルールに従ってバリデーションする、
  • フォーム入力だけでなく、普通の変数・配列でも適用可能。

とかでしょうか。
こういうのルールベースでのバリデーションとか言うのでしょうか。

◆これだけなら、別に作る必要はないわけで、一応自分なりの理由があって作ってます。ただ、他のValidatorクラスで実現してるか確認してはいませんが。

  1. バリデーション、サニテーション、フィルター、全部入り
  2. ルールの適用順番があらかじめ決まっている
  3. 複数に分割している項目も一つとしてバリデーション可能
  4. 配列入力もバリデーション可能

◆もう少し詳しく説明します。

1.全部入りルール

次のような3種類のルールがあると思うのですが、全部に対応しています。
  • サニテーション:
    ヌルバイトアタック、エンコーディングチェック、を行い、
    問題があれば安全な内容で上書きします。
  • フィルター:
    全角→半角、大文字・小文字変換、その逆、など。
  • バリデーション:
    レギュラーエクスプレッションによるフォーマットチェックなど。

2.ルールの順番を決めてある

まぁ大量のルールがある訳です。
が、例えば日本語だと、大文字→小文字変換を行う前には、全角→半角に変換しないと行けません。こういう順番を意識してルールを適用しても問題がないよう、ルールの順番を内部で持ってます。

3.複数分割項目対応

日付など、一つのデータでありながらフォーム上は複数の項目から成り立っている場合があります。例えば

$_POST = array(
 'date_y' => '2011',
 'date_m' => '11',
 'date_d' => '23',
);

find( $_POST, 'name', array( 'multiple' => array(
 'suffix' => array('y','m','d'),
 'sformat' => '$4d/$02d/$02d',
) ) );

4.配列入力のバリデーション

フォームのチェックボックスからだと、入力が配列の場合があります。
入力が配列の場合でも、それぞれの要素ごとにルールを適用してバリデーションします。またエラーがあった場合は、入力と同じ構造でエラーメッセージを返します。

例えば、数値のみの入力を可能にしている場合、
input: $input = array( 0 => '1', 1=>'3', 2=>'x', 3=>'4' );
error: $error = array( 2=>'not a number' );
という構造でエラーメッセージを作ります。

◆ソースコード

まだ開発中。
Cena-DTA内に組み込む予定なので、それから公開します。
githubにおいてあるので、探せば見つかりますが。

2011年11月19日土曜日

Simple@高円寺、2011/11/19

今日はいつものSimple勉強会@高円寺。
何をしようか考えながら、だらだらとして昼食して・・・

注目のPHPのフレームワーク

いろんなソースコードを読めるようにしようと思い立ち。
いくつか、すごそうな最新のPHPフレームワークなどを選んでみた。

  • Lithium
    CakePHPの人たちが作ってるPHP5.3用フレームワーク。
  • Fuel
    CodeIgniterの人たちが作ってるPHP5.3用フレームワーク。
  • underscore.php
    underscoreというjavaScriptのPHPポート。

コードをみても、追いかけられないorz

macでnetbeansでPHPのデバッグ環境を設定

コードを追いかけられないならデバッガーで追いかける。
MacBookAirにxdebugインストールして、デバッグ環境を整えました。
詳細は、こちらのページで。

で、underscore.phpを追いかけてみた。

が、追いかけられない。
何となくやってることは分かるけど。

staticクラスでメソードチェーンを、実現するため、引数を統一処理して、次のメソードに渡して、それを次々と処理している・・・と思う。が、追いかけきれない。

本当にすごいと思う。けど、
「こういうコードが書けるようにならなくてもいいはず」
と思うようにしよう。

◆Dioのコーディングでも

することにしました。
えぇと、フィルター(サニテーションとかバリデーション)を行うのに無名関数を使うように変更。これで変更しやすくなるはず・・・

と、static変数に無名関数を代入できない・・・
多分、staticなのに無名関数を実行しようとしてエラーなのか。
う〜ん、Lithiumみたいに__initとかで設定するか。

してみた。が、こんなのでいいのか悩む。

MacのbrewでxdebugインストールしてnetbeansでPHPのデバッグ

Simple勉強会@高円寺の作業ログ。

◆xdebugのインストール

マックでライオンでbrew使ってxdebugどうやってインストールするのか検索したが、いい感じのページが見つからず。そんなときは打ち込んでみる。

> brew install xdebug==> Downloading http://xdebug.org/files/xdebug-2.1.2.tgz######################################################################## 100.0%==> phpize==> ./configure --disable-debug --prefix=/usr/local/Cellar/xdebug/2.1.2 --enable==> make==> CaveatsTo use this software:  * Add the following line to php.ini:    zend_extension="/usr/local/Cellar/xdebug/2.1.2/xdebug.so"  * Restart your webserver.  * Write a PHP page that calls "phpinfo();"  * Load it in a browser and look for the info on the xdebug module.  * If you see it, you have been successful!==> Summary/usr/local/Cellar/xdebug/2.1.2: 348K, built in 15 seconds

なんだ。
インストール一発でできたみたい。

◆次はphp.iniの修正。

インストールからのメッセージを読めば書いてある、親切設計。
が、その通りに書いただけではnetbeansからデバッグできなかった。

ちょっとググって、下記のURLから
http://wiki.netbeans.org/HowToConfigureXDebug
これをxdebugのセクションの下にコピー。
xdebug.remote_enable=1
xdebug.remote_handler=dbgp
xdebug.remote_mode=req
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9000

これでnetbeansでデバッグできるようになりました。

2011年11月9日水曜日

Chromeのuserスクリプト書いてみた

なんて簡単に・・・
FireFoxでGreacemonkey書いたときは苦労した記憶がある。
まだJavaScriptに慣れてなかったからか、jQueryのインストールに苦労したのか・・・

ともあれ、
JavaScript書く⇒Chromeにインストール
がこんなに簡単なんて。

◆書いたコード:
// ==UserScript==
// @match http://dev.example.com/*
// ==/UserScript==

links = 
  document.evaluate(
    '//a[contains(@href,"http://www.example.com")]|', 
    document, null, 
    XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (i = 0; i < links.snapshotLength; i++) {
  links.snapshotItem(i).href = 
    links.snapshotItem(i).href.replace( 
    /\/\/www.example.com/i, "//dev.example.com" );
}


開発サーバー(dev.example.com)を立ち上げたけど、絶対パスでリンクが張ってある箇所が多いので、ユーザースクリプトでリンク先を強制書き直し。

◆上のファイルを自分のPCに保存。

「test-server.user.js」とかにして保存した。

で、Chrome上にドラッグ&ドロップで、ドロップ。

すると、

  • 左下に確認画面(Extensionはコンピュータにダメージ与えるかもしれないけど、続けていい?)が出るので「Continue」を押す、
  • ダイアログウィンドウが出るので「Install」ボタンを押す、
  • で、インストール完了。

何度もやる作業なので、インストールが簡単なのは素晴らしい。


2011年11月8日火曜日

ChromeでGreasemonkey:JavaScriptでリンク先を変更

仕事で使いそうなので。メモ。

◆ChromeでもGreasemonkeyが使えるらしい。
http://internet.watch.impress.co.jp/docs/news/20100202_346437.html

知らなかった~
早速、ウェブページ内のリンクを書き換えるスクリプトを書きたい。

◆が、jQueryが使えないとの話。

まぁこういうスクリプトを入れればよさそうだ。
http://stackoverflow.com/questions/2246901/how-can-i-use-jquery-in-greasemonkey-scripts-in-google-chrome

◆でも、もっとピュアJavaScriptでリンクの書き換えぐらい出来ないのか?

ちょっとググルと、サンプルコードがあった。
http://userscripts.org/topics/1966?page=1

document.evaluateってなんだ!

そんなメソード知らなかった!!!
XPathって言うんだ。。。
うん?「XPath」は聞いたことがある気がする・・・

なんか、とてつもなく、使えそう。
http://www.softel.co.jp/blogs/tech/archives/2067

こちらは、引数について説明が細かくある。
http://deltatech.blog90.fc2.com/blog-entry-332.html

ちょっとしたことでも、jQueryが便利だから使ってたけど、
ピュアJavaScriptでも、かなりのことが出来そう。

2011年11月6日日曜日

gitのbranchを覚える

gitを使うなら、branchを覚えるべきらしい。
なので、勉強がてらにメモ。

◆githubにレポジトリがある状態から

既にgithubでレポジトリを作ってるとして、まずはclone。

git clone git@github.com:asaokamei/test.git

◆ブランチの作成と確認

覚えるのはgit {branch|checkout} コマンド。
これでローカルレポジトリ上でbranchを作成したり、
branchを行ったり来たりできる。

まずはブランチを作成。そして現在のブランチを確認。
> git branch jpn
> git branch
  jpn
* master
新しいブランチ「jpn」に切り替え。そして現在のブランチを確認。
> git checkout jpn
Switched to branch 'jpn'
>git branch
* jpn
  master


◆で、ここからgit gui(笑

軟弱ものなので、gui版を使ってます。
「git gui &」でgui版を走らせます。

すると「現在のブランチ jpn」と出てます。
うまくいってる感じ。

適当にファイルを追加・編集したら
コミットしてプッシュを押すと、「元のブランチ」で
jpn
master

が出た。
「jpn」が選ばれてるのを確認してから、
「リモート:origin」でプッシュ。

githubで確認したら、ちゃんとブランチが切られてできてました。

◆簡単でした。

なんか悩んでましたが、これだけなら簡単ですね。
gui版を使えば、どこにプッシュするかもわかりやすいので、
間違えないですみそうです。

まぁブランチの入門編でしかないですが。

2011年10月22日土曜日

fluxflexを使ってみる@Simple

PHPが使えて、githubから簡単インストール、で有名な?
Fluxflexを使ってみます。
https://www.fluxflex.com/

日本人がサンホセ(シリコンバレーのことですね)で立ち上げた新しいPaaSらしいです。

◆アカウント作成・認証。

簡単にtwitterを使って認証。
ものの5分たたずに最初のsandoboxが立ち上がった。
http://sandbox-6bh0ihgi.fluxflex.com/

素晴らしい。

◆新しいプロジェクト作成

適当にプロジェクト名を決定して・・・
もしかして大文字不可?

ともあれ、名前を入力して、Create A New Project を押して、完了。

名前:cenadta-demo


◆fluxflex用のgithubレポジトリを作成

CenaDTA-fluxflexというレポジトリを作成。

次に作業フォルダーを作って、
public_htmlというフォルダーを作成。ここが公開フォルダーになるとのこと。

その中に、Cena-DTAを放り込む。
噂ではgit内に別のgitがある場合、fluxflexが動かないらしい。
ので、.gitフォルダーはすべて削除。

データベース接続の設定ファイル内のユーザー名などをCENA_DB_USERに変更。後述しますが、設定を変換できるらしい。

そんで、git commit してpush。

◆fluxflexでの設定の方法

さて、githubからimportする際に、DBへの接続パラメータを上書きできるようになってます。これがないと、公開レポジトリ使うとパスワードが漏れてしまいます。

まずは、SetUpの中のDatabaseで、データベース接続パラメターを確認。
同じくSetUp内のInitialize Scriptで、Initializer ScriptとSetEnv Variablesをセットアップ。こんな感じ。
[replace]
public_html/demo/dba.ini.php   CENA_DB_USER     DBA_USER
DB_USER   cenadta-demo
ここで、Github Importで、先のgithubレポジトリ
git@github.com:asaokamei/CenaDTA-fluxflex.git

を指定してimport!

◆動いた・・・が、

早速、DBの初期化。
が、データベースの接続で

SQLSTATE[HY000] [2002] Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

と怒られた。

◆なぜでしょう?

まずimportする際に、「Run initialize scripts for setting up the project.」にチェックを入れて押すことに。これで少し前進した様子。

次に、fluxflexのstatistics内のInitialization Logsにエラーを発見。


[!FAILED] invalid fixture key : XPS in line 3

とあって、XPSという文字列の変換に失敗している様子。その後のファイルが見つかりませんのエラーは、最初のエラーが原因で発生しているようで、無視して大丈夫みたい。

うん?XPSなんて文字は指定してないぞ。
どうやら、XPSは環境変数に設定されていない場合のエラーのようです。

◆もう一度、落ち着いてimportとinitializationから

まず、Initialize Scriptの[replace]ですが、
  ファイル名、変換する文字、変換後の文字、
なのですが、変換後の文字はEnvironemntを通して設定するようです。

ただし、最初から次の変数は環境変数に設定されているようです。

# DB_USER ... The username of the project database. This name is the same as project name in almost all cases.
# DB_PASSWORD ... The password of the project database.
# DB_HOST ... The hostname of the project database.
# PROJECT_NAME ... The project name.
なので、Initialize Scriptに、
[replace]
public_html/demo/dba.ini.php   CENA_DB_USER     DB_USER
public_html/demo/dba.ini.php   CENA_DB_PASSWORD    DB_PASSWORD
public_html/demo/dba.ini.php   CENA_DB_HOST     DB_HOST
public_html/demo/dba.ini.php   CENA_DB_NAME     PROJECT_NAME
と設定するだけで動きました。
追記:最初は.fixファイルを使うつもりだったのですが。
忘れてた。こちらの方がgitで管理できるので便利と思われる。

◆Cena-DTAのでもサイトが公開!

http://cenadta-demo.fluxflex.com/

よろしく〜
まだセキュリティ関係があれなので、気をつけて使ってください。
変なデータ入れられても、XSSしてしまいます。
また、定期的にDB内はクリーンアップしますので、大事なデータとか入れないように。

◆文字化けしている。

が、ちょっとみたら文字化けしていますね。
DBに入れた文字が化けてるみたいです。

fluxflexからphpMyAdminを使えますので、早速ログイン。
データベースの操作メニューで、照合順序をみたら、latinとなってます。
これをutf8_unicode_ciに変更して、実行。
一旦テーブルをドロップしてから、作り直したらなおりました。

午後いっぱいかかりましたが、サイト一個アップするのも簡単になりました。
素晴らしいサービスです。いい時代です。

Simple@中山

いつもの勉強会@中山。

◆まずは血圧の測定。

最近、医者に高血圧といわれ薬を飲み始めた。
ので、今日は一日の血圧の変動を測定する。

測定器は、アマゾンで評価のよかった手首ではかるタイプのやつ(右)。ただ医者で測定するより20ぐらい低く出る。

06:09 116−66
11:45 126−79
16:54 139−80


◆何しようかな。

◆Dioモジュール作ってます(PHP)

https://github.com/asaokamei/Dio

Yet-another-validatorですが、入力値のサニタイズ、文字種変換、バリデーション、の全部入りモジュールです。こんな感じで使える予定。

$mail = Dio::request( 'user_mail', 'email',
  array(
    'default' => 'text@example.com',
    'required' => TRUE,

    'toHankaku' => TRUE,
    'string' => 'lower',

    'regexp' => array( '*jp$', 'err_msg' => '日本ドメインのみ可' ),
  )
);


特徴は:
  • できるだけ簡単に。
    例のような感じで、普通に簡単に使えるようにしたい。
  • 文字種変換など順番を指定できる。
    全角英数字を半角に変換してからバリデーションする、とか順番が大事なので、前もって順番を指定しておいて、適当に使っても大丈夫にしたい。
  • 複数の項目を一つにして読み込める。
    例:date_y, date_m, date_d を「date」として読み込めます。
まだ一度も走らせてません。シンタックスエラーすら未チェック状態。

◆今日の課題を決定:fluxflex

to-be-continue


2011年9月17日土曜日

Simple@高円寺、Qunitなど

いつものSimple勉強会。今日は高円寺にて。
まったりとスタート。

◆QUnitでユニットテスト

Cena-DTAのJavaScriptのユニットテストをするためにQUnitを使ってみた。
http://docs.jquery.com/Qunit

テストコードを作るのはとても簡単。

非同期(asynchronous)の場合のテストもできる。
http://net.tutsplus.com/tutorials/javascript-ajax/how-to-test-your-javascript-code-with-qunit/

「QUnit asynchronous」でググって最初のページだけど。
疑似コードは:

test( "asynchronous test sample", function() {
  stop(); // テストを一旦止める
  async( callback_func );
    var callback_func = function() {
      start(); // テスト再開
      ok( true );
    }
{);

・時間の読めない関数(async)を呼ぶ前に、一旦テストをstop、
・コールバック関数で、実際に実行される箇所で、テストstart、
・それからテスト条件を書く、
という感じ。

面倒な点といえば・・・
テストしたいのがDOMに正しく書かれたかどうかのため、テストの設定が大変だった。また書かれた内容をjQueryで読み込んでとかも面倒。

これはQUnitが原因ではなくて、おしなべてJavaScript全般にいえることでしょう。

◆もっとテストを

結構、テスト書くのは大変です。
どの機能を、どうやってテストしたらいいのか、考えるだけでも時間がかかってます。先にテストを考えてから作るといいんですかね?

それって、ボトムアップみたいな開発ならできそうなのですが、トップダウンで作ってるとき(つまり試行錯誤しながらクラス設計する場合)後回しにしてしまいそう。いや、後回しにして、後でテスト足りなくて困るという・・・

2011年9月13日火曜日

PHPカンファレンスでCena-DTA発表

2011年9月10日のPHPカンファレンスでCena-DTAの発表してきました。
緊張したなぁ~

UStream
http://www.ustream.tv/recorded/17175804

発表資料
http://www.slideshare.net/asao_jp/cenadta-php-conference-2011-slides

技評さんの「PHPカンファレンス2011 スペシャルレポート」
http://gihyo.jp/news/report/01/phpcon2011/0001?page=2

技術評論社さんには
「まだ過渡期の技術ですが今後どんどん
 開発が進んでいく注目の技術かもしれません。」
と書いてもらえました。

うん?
「今後どんどん開発が進んでいく~かも」とは、どういう意味でしょう?
もっと頑張れ、ということかも知れません。

確かに、発表内容は技術の紹介が半分近くを占めてます。
発表タイトルにある「アプリ開発」には、ちょっとしか触れてません。
聞いてくれた人には、思ってたのと違う内容だったかも知れません。

そういう意味で、まだまだ過渡期。
次こそは、「ぜひ使ってください」という発表をしたいです。

使ってもらえるためには、何が必要でしょう?
コードとプロトコルをきれいにする?
セキュリティを極める?

自分としては、摘要可能なRDBの範囲を見極めたいです。
まだまだ単純なケースでしかCena-DTAが有効であることを示せてません。
もっと複雑な構造だったら?
もっと大量のデータだったら?

それと、他の技術もあるけど、
どういう場合にCena-DTAを使うべきなの?

こういった疑問に答えられるようになりたいです。

2011年8月11日木曜日

Mac OS X Lion で homebrew を使ってみる。

◆homebrewかmacports

今はhomebrewがおされらしい。
macportsの問題は色々あるみたいだけど、OSアップデートしたら環境全部壊れた、見たいな事がある、らしいと理解しました。

◆インストール

色々なサイトを参考に、インストール自体は問題なく出来たように見えました。

◆が、インストールがおかしい

最初はインストールしたのですが、
brew update
/usr/local/.git: Permission denied
Error: Failure while executing: git init
などといわれます。
もう一度homebrewをインストールしてみても、似たようなエラー。

まさかね、と思いながら探していると
http://stackoverflow.com/questions/6936678/cant-install-homebrew-on-mac-os-x-lion

ちょっと怖いけど、次のコマンドを発行。

chmod 777 /usr/local
エラーは直りました。


◆早速、mysql.server start

エラーはなし。
が、今度はmysql -u root -pでソケットがありませんとエラーが出ます。
mysql_config --socketなどで調べたけど、訳が分からず。
リブートしたら動いた。



2011年6月25日土曜日

Simple@Idx 2011/06/25

CenaをGithubに登録する作業。

数ヶ月前にSSHを設定して、動いていたのだけど、
パスフレーズをなくしてしまった。

ので、SSHの再設定するのに四苦八苦。
いろいろググッたけど、結局Githubのヘルプ読むのが
一番簡単だった。

https://github.com/asaokamei/Cena-DTA

で、Cena-DTAのソースコードをプッシュ。
友人のマック上で展開して、動作確認してもらって、

  動*い*た。

MySQLの設定部も問題なく進んだし。

さて、GPLv2で公開した。
ということは、もう後戻りはできない、ということですね。

2011年4月23日土曜日

Simple@Idx 2011/04/23

久々に中山で勉強会。

◆CenaDTAと名づけることに

cenaはイタリア語で夕食の意味。
意味のある言葉をプロジェクト名にすると、後々面倒なので「Cena-DTA」にすることにした。
「Cena Data Transfer Agent」の略ということで。

◆gitHub

今後のバージョン管理はgitHub使うことにした。
有名だからという程度の理由。今まではローカルHDD上でmercurial使ってたので、過去の履歴はすべて破棄されることになる。が、仕方ないんだろうなぁ。

で、早速インストール。
セットアップの方法にしたがって、インストーラーをダウンロードして走らせると、説明とまったく同じ画面とバージョン番号が出ていた。これって、実はすごいことだと思う。

説明にしたがってSSHキーを取得したりしているうちに動き出した。

が、コミットしてもgitHubに反映されない。
これはpushが必要だから、と思ったがgitGuiからpushできず。
結局、gitBashから説明どおりに打ち込んで公開完了した。

https://github.com/asaokamei/Cena-DTA

◆眠くなってきたのでウェブサイトでも作ることに

ざっくりとデザインを決めてアップ。
http://www.workspot.jp/cena/

2011年2月26日土曜日

Simple@Idx 2011/02/26

デモをアンドロイドの実機で動かすのが目標。

実機はGalaxy S。Android 2.2が乗ってます。
デモはノートブックPCのローカル環境で動いてます。

◆無線LAN環境を整えよう

LogitecのUSB無線LANはAPモードになる。
アンドロイドからWiFiでPCにつなげられる。

つながったと思ったら不安定だったので、
最新のドライバーにアップグレード。

◆つなげてみよう

PCのローカルIPを調べて、
ブラウザーに直接打ち込むと、
お、動いた。

ここまでは簡単。

◆デモが動かない。

HTMLは表示されるが、WebSqlDatabaseからの読み込まない。
PHP、JavaScript自体の問題はないみたい。
デバッグ情報もalertもOK…
さて、どうしたものか。

◆Android SDKをインストールしてみる。

するとJDKもインストールしろといわれたので、した。
インストールは簡単に終了。が、動かない。

どうもコンポーネントのダウンロードに失敗していたらしい。
Windowsなので、「管理者として実行」としたら動いた。
例の「Program Files」フォルダー以下に書き込めないのが原因だろう。

・・・

なんか動いたみたい。
すごく遅い。

お、動いた。
WebSqlDatabaseも動いた。
エミュレーター上では問題なし。

◆Galaxy Sの問題?

お、Galaxy Sのファームウェアバージョンアップがあった。
Samsung KiesをPCにインストールする必要があるのか。
どうしよう。

簡単なWebSqlDatabaseのサンプル・デモを作ったのを思い出した。
Galaxy Sで確認すると、動いた。

◆jQueryをアップグレード

デモのjQueryが1.4.1と古かったので、1.5.1にアップグレードしてみた。
すると、PC上のChromeでも動かない。
直さないといけないみたい。

仕方ないので1.4.4にアップグレード。PC、エミュレーターでは動く。
が、実機では動かない。

◆実機でデバッグ

しろと。
ADBとやらを動かして、consoleのアウトプットをみると。
このあたりのリンクを参考にして。
http://www.nanaze.com/2009/01/debugging-javascript-on-android.html

以上で、時間切れ。