ラベル Web/CMS/etc. の投稿を表示しています。 すべての投稿を表示
ラベル Web/CMS/etc. の投稿を表示しています。 すべての投稿を表示

2014年12月18日木曜日

Software Designの2015年1月号「ソフトウェア開発の未来」

久々に本屋でIT関連の雑誌を買った。
ランチの後に、近くの本屋に入って手にとって見たのが、

Software Designの2015年1月号

タイトルは「Vim使い事始め」だけど、目に止まったのは「ソフトウェア開発の未来」のほう。特にサブタイトル「請負・受託開発は変わるべきか?」が決定的だった。

内容は、渋い。
目新しいことや、びっくりするようなことは書いてない。
知ってた、みたいな話も多い。

でも、こういう普通の話を聞く機会というのは少ないので、タメになる。

そして考えがスッキリした気がする。
モヤモヤと思ってたことを、整頓した感じ。

これからもSIという名前の請負案件はなくならない。日本のIT業界内でのシェアは減ってゆくと思う。が、絶対的な金額としては、特に中小規模は減らないのではないかと思う。

そして自分はお客さんと話をして要件を聞いたりまとめたりするのは好きだ。二次三次の下請けにならない限り、請負仕事は続けてゆくと思う。ただ直接お客さんと話せない状態になったらわからないかな。

今日のポイント。

設計力は大事。
シンプルな技術で長期間のサポート。
そしてお客様の困っていることを解決すること。

2012年8月12日日曜日

ssh_exchange_identification: Connection closed by remote host

今までのように、sshでサーバーに入ろうとしたら、怒られた。
ssh_exchange_identification: Connection closed by remote host

最近、何もいじくってないのに。
いや、MacBook Airから鍵認証で入れるようにしたが・・・
サーバー側はいじってないはず。

ググると、いろいろかかれてた。
ひとつずつ、対応してみた・・・

/etc/hosts.deny


まずは、一番怪しそうなこのファイル。
中身を見たら、いろんなサイトが追加されてた。

そういえばdenyhostsをインストールしていた。
アタックしてるサイトのIPアドレスが追加されてる。

えっ、こんなにアタックがあるんだ。
ポート変更しとこう・・・

ちなみに、自分のアクセス元はありませんでした。
これが原因ではない。

/etc/ssh/sshd_config


このなかの「MaxStartups」を設定しておくのがよいらしい。
見たら、コメントアウトされてたので、「#」マークを削除。

リスタートして・・・まだ動かない。

/etc/hosts.allow


まさかね。
これじゃないよね。でも何も書いてないよな。

このページを参考にして「sshd:all」と一行追加。


動いた。


こうなると、今まで動いていたのが不思議だが、

ま、少しセキュリティも向上して、よかった、よかった。

2012年8月11日土曜日

gitのレポジトリをサクラVPSに作ってみた

サクラさんのVPSを借りた理由の一つが、自分のgitレポジトリを持ちたいということ。これでパスワード付きのソースコードだって気にしないで管理できる。

最初はgitosisかgitoliteをインストールする予定だった。
が、Stackoverflowの両者の比較ページにgitだけでレポジトリを作る方法が説明されていた。簡単そうだったので、まずはこれでゆくことにした。

ちなみに、日本語での説明はこのページに
もう書いてあるそのまま。

サーバー側でgitがインストールされているとして、
ssh [user@]server
cd repos/
mkdir test.git
cd test.git
git init --bare

ローカル側でもgitが入っていれば、
cd src/test
git init
git remote add origin [user@]server:repos/test.git
git push
これでレポジトリができて動いた。

ひとつだけ、ローカル側でgit remote add originを走らせると、こんなエラーが出た。
fatal: Not a git repository (or any of the parent directories): .git

原因はgit initを走らせていないこと、だって。

2012年7月23日月曜日

MacにPHP5.4をインストール

PHP5.4を使いたくなった。
最初はVirtualPCインストールしてUbuntuでLAMP環境作ったが、動くのはいいが開発には今ひとつな感じ。

homebrewを使ってインストール


まずは、本体のMac OS X Lionにhomebrewを使ってインストールすることにした。参考にしたのは「Mac OS X Lion: Homebrew, PHP54, MySQL and PEAR」で、ほぼ書いてある通り。


brew tap josegonzalez/php
brew update
brew install php54


多少、あれが無い、これが無いと言われた。
が正確には、あれが無いのでこうしろ、という親切なメッセージなので英語さえ理解できれば簡単に対応できそう。

さ、動いた。
phpinfoを見ると・・・インストールされてない。

pear絡みでエラーが出てるようだ。
Xcodeを4.3.3にアップデートしろと書いてあるので、アップデートしようとしたら・・・何もしてくれない。

仕方が無い。

Macで一番簡単にPHP5.4をインストールする方法


を試してみた。
書いてある通りにcurlをコピペして待つこと5分ぐらいか。
何も応答がなくなったので、心配になったが、ちゃんとインストールしてくれた。
localhostで確認したらphp5.4.5になっていた。


2012年7月17日火曜日

UbuntuでJavaが走らない(Error: could not open `/usr/lib/jvm/java-6-sun-1.6.0.26/jre/lib/amd64/jvm.cfg')

Ubuntuで快適に仕事していたが、
突然PhpStormが動かなくなった。

直接端末からPHPStormを起動したらJavaのエラーメッセージが出た。

Error: could not open `/usr/lib/jvm/java-6-sun-1.6.0.26/jre/lib/amd64/jvm.cfg'

そこで、端末から
java -version

と打ってみたら同じエラーが出た。
Javaのインストールエラーだ。

適当に修正



ちょっとググったが、ぴったりのがなかったので、
適当にcdしながら追いかけてみた。
cd /usr/lib/jvm/java-6-sun/jre/lib/amd64

何のことはない、上記のファイルはリンクになっていた。
jvm.cfg -> /etc/java-6-sun/jvm.cfg
リンク先を見ると、java-6-sunというディレクトリがない。
代わりに「java-sun」というのがある。

そこで
sudo ln -s /etc/java-sun/jvm.cfg .

としたら治った。

ググるより、自分で解決したほうが早そうな、珍しいパターンでした。

壊れた原因は・・・


思いつくのは、さくらインターネットさんでVPSを借りた。
Ubuntuをインストールするには、VNCクライアントが必要で、それを動かすためにJREをインストールした覚えがある。それで壊れたのか。

些細な原因ですが、いちいち面倒だな。
その点、WindowsやMac/OS Xとかは、きちんとしてそう。
その代わり有償だし色々と不自由だけど。

2012年4月20日金曜日

もっと早くUbuntu+PHPStormの開発環境にすればよかった

ちょっと感動したので、書いてみます。

Ubuntuにしてから1ヶ月ほど。
あまりPHPStormを使う機会がなかったのですが、先ほどデバッグ環境を設定しました。
あまりに簡単で書くことにしました。

なお、ローカルでApache2を動かしているという前提です。

PHPStorm

PHPの開発環境として、PHPStormは最強だと思います。
何が最強か上手に指摘できないのですが、意外と軽いわりに機能が豊富。かゆいところに手が届く、といった感じです。そしてデバッガーがちゃんと動きます。今までEclipse+PDTやNetBeans使ったことはありますが、設定に偉い苦労して、やっと動いたと思ったら次の日になると動かないとか、そんなことが多かった気がします。

一度、PHPStormを使ったら、ヘビーな開発は
PHPStormを使う以外は考えられません。

もっともお仕事の作業ではDreamWeaverも捨てがたく。
仕事だとライブラリやらフレームワークをいじくることはほとんどなくて、逆にHTMLやらフロントをいじくることが多いのでHTML←→ソースビューを行き来できるDreamWeaverは便利だと思います。

xdebug

そもそも過去デバッグが動かなかった原因は、xdebugかもしれません。
Windowsのバージョンにバグが多いのか、だいたい正しいdllを選ばないと動きません。
が、Ubuntuでxdebugインストールするのはとても簡単。

Ubuntuソフトウェアセンターでxdebugを検索、
インストールボタンを押したらインストール完了。
アパッチをリスタートして、xdebugが動いてました。

コマンドで言えば(多分)
sudo apt-get install xdebug
sudo service apache2 restart
で終了。

php.iniの修正

さすがに、これだけでデバッガーは動きませんでした。
ここのPHPStorm用xdebugの設定を見ながらphp.iniを修正。

ターミナルから
sudo vi /etc/php5/apache2/conf.d/xdebug.ini

を開いて(一行しか入ってないや)、
そして以下のように修正。


[XDebug]
  zend_extension=/usr/lib/php5/20090626/xdebug.so
  xdebug.remote_enable=1
  xdebug.remote_port=9000
  xdebug.profiler_enable=1
  xdebug.profiler_output_dir=/tmp/

アパッチをリスタートして、phpinfoでxdebugが動いているのを確認。

PHPStormの設定

最後はここの「何の設定なしでxdebugとPHPStorm2でデバッグ」という少々誇張されたタイトルに書いてあるとおりに設定します。

xdebug用のブックマークを作ること。

個人的には「Start debugger」と「Stop debugger」だけブックマークを作って、デバッグを始めるときにブックマークを押します。

そしてPHPStormでは「赤い電話機アイコン」を押して緑色に変わればOK。
ブラウザーをリフレッシュすると、PHPStormでデバッグが開始されます。

path mapping

以上で、動くと思うのですが・・・
たまに「path mapping」を設定してください、といわれます。

どうも、PHPStormがデバッグするには、xdebugからデバッグ中のファイル名を受け取っているようなのですが、ときどきファイルがどれか混乱するようです。

同じファイル名がある場合など、どのファイルをデバッグするか聞いてくることがありますので、適宜選択してあげるとデバッグが始まります。

So, Happy debugging with PHPStorm!

2012年4月2日月曜日

Chrome: Your Profile Could Not Be Opened Correctly [solved]

Took me more than a week to figure this out...

Problem: 

When using Chrome's sync function using Google's account, Chrome does not shutdown gracefuly, leaving zombie process in Ubuntu OS.

The zombie process, somehow, prevents Chrome to load account data, and reports,
Your profile could not be opened correctly...
When this happens, Chrome fails to load any of the password, cookies, from the past history, even if it is on the local data. This is very annoying.

Find out the cause:

After Googled around, found out how to kill the zombie process:
pkill -9 chrome

Then, found Chrome's history data is causing this, so removing it should help:
rm -rf .config/google-chrome/Default/History*
These worked fine, but when Chrome synchronize the account, the History data came back, and the problem occurs again.

To summarize the situation,
some bad data in History is the cause of this problem,
and the bad data is in the Google Sync (up somewhere),
so Chrome sync always downloads the bad data. 

OK, the solution is
to erase the bad data from Google account.

I tried to erase the sync'ed data from Chrome's Preference menu. But nothing  worked. So, I dived into the Google's maze of account setting pages...

This worked for me:

0) disconnect from Google Account.

Not sure if this is necessary, but I was disconnected when I did the following.

1) login to Google Account Setting. 

I used this url to get into my account setting.
https://www.google.com/settings/

no link, I found so far. 

2) turn off the Google Sync

From the account setting page, click on "Profile and privacy". 
then, scroll down to "Sign in to Dashboard" and click.
find "Chrome Sync", and click on "Stop sync and delete data from Google" or something 
(well I'm a Japanese, and I changed the language to English to write this entry. But this page was still in Japanese. so I cannot be sure how the link is written in English.)
wait for a few minutes according to the message. 

3) delete web history

From the account setting page, click on "Go to web history".
Click on "Remove all Web History", and clicked just yes to whatever the question was. 

4) start Chrome and synchronization

and it worked for me!


The Google account pages were just like a maze. 
So, many of the above may change at anytime. But I hope that this list gives some clue about this problem. 

[additional note: 2012/04/20]

The same problem happened again, about two weeks after I wrote this blog entry. So, I stopped syncing 'address bar history', and the problem went away (for now). 

2012年2月3日金曜日

AmidaMVC:設計方針を決める

さてコントローラーのアミダ式チェーンが出来たので、
今度は中身のフレームワーク。

HTTPのリクエストはコントローラーが受け取り、
コンポーネントを次々と実行する。

で、コンポーネントで何をするか?
まずは、
  1. リクエストから読み込むファイルを探して、
  2. ファイルを読み込んで、
  3. テンプレートに流し込んで、出力。
これが最低必要な流れでしょう。
それぞれ、Router、Loader、そしてRenderという名前のコンポーネントを開発することにしました。
試してませんが、今でもこの3つのコンポーネントだけで動くんじゃないかな?

Router

コントローラーからpath_infoを読み込む。
単純に最後のパスがファイル名で、残りがフォルダー名。
で、探し出せればLoaderにファイル情報を渡す。 
今はルートマップから探索できるようになりました。どちらの方法でもファイルが見つから無ければPageNotFoundにアクションを変更。 

Loader

ファイル情報からファイルの中身を読み込む。
拡張子から中身の種別を判断(HTML、markdown、テキスト、PHPのソースコード)したうえで読み込む。
PageNotFoundの場合は、前もって決めておいたファイルを読み込む。最初、ファイルはLoader内に直書きしてたが、今は設定コンポーネント(Config)で設定するよう変更済み。ファイルが正常に読み込めれば、アクションをデフォルトに戻してRenderに処理を渡す。

Render

中身の種別により、マークダウンならHTMLに、テキストならnl2brとhtmlspecialcharsをかけて、PHPならソースコードハイライトして、と前処理を行う。

それから中身のデータをテンプレートに流し込む。
とにかく簡単に。単なるPHPをインクルードするだけ。

◆$siteObj

コンポーネントで色んなデータを扱う必要があるので、必要な情報は全部このオブジェクトにぶち込んで、コンポーネント間で持ち回します。デザインパターンで言えばData Transfer Objectですな。

◆Toolsフォルダー

コンポーネントが行う実際の処理はここに書く。
コンポーネントは、処理を行うルーチンを呼び出すのが仕事。

こういう汎用的なルーチンは再発明しても仕方ないので、出来るだけ自分で書かないのが方針。実際、『パーフェクトPHP』のフレームワークの章から、ほとんどのコードを書き写しました。とても参考になったいい本だと思います。

理想はsymfonyなどのフレームワークのライブラリを再利用できるといいな。

◆以上、簡潔に方針をまとめると
・コントローラーは単純に、
・コンポーネントは薄く、
・ツールは汎用的かつコピペで書く、
のが開発方針です。

2012年2月2日木曜日

AmidaMVC:Amida式チェーンを思いついた流れ

何故Amidaなんてチェーンを思いついたか?

昔作った簡単なページコントローラーがあったけど、
コードが汚くて使いづらくて。

つい書き直し始めたのが始まりだった・・・

最初は入力の値によって、決まった関数を呼び出すだけ。
次に、ひとつのクラス内のメソードを呼び出すようにしてみた。

ふむ。簡単すぎるぐらいの改造。

それではと、複数のクラスを登録して、
次のクラスを呼び出せるようにしてみた。

何か面白いぞ。

じゃぁ、デフォルトで次のクラスに進んでみよう。
お~、いい感じ。

おや?MVCフレームワークにちょうどいいんじゃない

じゃ作ってみようか。

作ってみた ← いまここ。

AmidaMVC:アミダ式チェーンとChain of Responsibilityパターン

Amida式Chainのコードです。


function dispatch( $action, &$data=NULL ) {
    // set current action.
    $return = NULL;
    $this->_dispatchAct = $action;
    $this->setAction( $action );
    $this->fireStart();
    // -----------------------------
    // chain of responsibility loop.
    while( $this->moreModels() )     {
        $this->fireDispatch();
        $action = $this->getAction();
        $return = $this->execAction( $action, $data, $return );
        if( $this->useNextComponent() ) {
            // go to next component. 
            $this->nextComponent();
        }
        else {
            $this->useNextComponent( TRUE ); // reset to TRUE. 
        }
    }
    // -----------------------------
    return $return;
}


内部に$this->_componentsという配列にコンポーネントを登録しておいてwhile文でループしているだけです。

コンポーネントの扱い

nextComponent()でarray_sliceをして、
次のコンポーネントに進みます。つまり、後へは戻れません。

ただしコンポーネント内で別のコンポーネントを登録できます。
例:prependComponent( 'appHello', 'app' );

これで自分自身の次に実行するコンポーネントを追加します。
その他、チェーンの最後に追加する、チェーンを終了するする、指定したコンポーネントまでスキップする、などが出来ます(まだAPIで全てに対応はしてませんが)。

アクションの扱い

$actionはコンポーネント内で必要に応じて変更されます。それ以外は変わらず同じアクション(つまり同じ名前のメソード)を呼び続けます。

Chain of Responsibilityパターン

Amida式チェーンは、Chain of Responsibility (CoR)パターンの一種だと思ってます。WikipediaでのCoRのページを見てもよく分かりません。

自分の理解では、何かを達成するのに複数のオブジェクトを使う、複数のオブジェクトを使うためにAPIを共通にする、そして実行するオブジェクトの順番を適宜変更できるようにする、というパターンだと思ってます。

なのでCoRの実装方法はいろいろあると思います。
多分、LithiumというPHPのフレームワークは、各オブジェクト内で次に呼ぶオブジェクトを指定しているようです。リンクトリストみたいですね。

それに比べるとAmida式チェーンは比較的単純だと思います。実行するオブジェクト(あるいはクラス)を最初に配列で持っています。一方、途中でオブジェクトの順番を変えたり、呼び出すメソード名を変更できるのが特徴です。


2012年2月1日水曜日

AmidaMVC:appHelloを書いてみよう

今度はちゃんと俗に言うModelみたいな書き方を。

「demo/hello」フォルダーを作ります。
その下に「_App.php」ファイルを作って、



<?php
$_ctrl->prependComponent( 'appHello',  'app' );
class appHello extends \AmidaMVC\Component\Model
{
    static function actionDefault(
        \AmidaMVC\Framework\Controller $ctrl,
        \AmidaMVC\Component\SiteObj &$siteObj  )
    {
        $html = '<h1>Hello Application</h1>' .
            '<p>Hello World from Application</p>';
        $siteObj->setContents( $html );
    }
}

と書き込みます。

次のURLにアクセス。
http://your.host.here/pathto/AmidaMVC/demo/hello/

your.host.herepathtoは適宜環境に合わせてください。
すると、


と表示されます。

今度はたくさんのルールがあります。

_App.php

アプリケーションは_App.phpファイルにあるという規約になってます。

自分自身をコンポーネントとして登録

Componentとして自分自身をチェーンに登録する必要があります。
AmidaMVCのコントローラーが$_ctrlで取得できるので、prependComponentメソードを使って登録しています。

$_ctrl->prependComponent( 'appHello',  'app' );

ここにクラス名(appHello)を入れます。
この時点では、Loaderコンポーネント内で動いています。次に実行するコンポーネントとしてクラスを登録することになります。
正直、これは格好悪いと思いってます。クラス名を固定にしてコントローラー側で自動で読み込ませようかと思ったのですが、規約を増やすより、自分でコード書いた方がいいかな、と思って。というのは嘘で、ここでViewも読み込ませたいのですが、二つのクラスを上手に読み込ませるよい規約を思いつかなかったからです。

actionDefaultメソード

Loaderがファイルを読み込んだ後、appHelloクラスを実行します。
このURLだとアクションはデフォルトになります。なのでactionDefaultメソードが呼ばれることになります。

変数は3つあります。
  • $ctrl:AmidaMVCのコントローラーオブジェクト。
  • $siteObj:ウェブサイトに関するデータを収集するオブジェクト。
  • $data:前のコンポーネントから受け渡されるデータ(必要なければ無視)。

HTMLを返す

結果のHTMLは$siteObjに登録します。
これがRenderに運ばれて、テンプレートなどの処理を行います。

$siteObj->setContents( $html );


個人的な感想・・・

ちょっと書いてますが、もっと規約を増やして自動で処理する項目を増やしたほうがいいかもしれません。

  • たとえばRenderが受け取る$data(3番目の変数)は常にコンテンツにするとか。するとappあるいはviewメソードの最後にHTMLをreturnすればRenderが受け取ってコンテンツとして処理してくれるとかです。
  • それから、コンポーネントの登録を自動で行うとか。
  • _initメソードを前もって呼び出すとか。

フレームワークは作っていて楽しい理由は、ここら辺でしょうね。
やりすぎて使いにくくならないようにするのが難しいのかもしれません。

AmidaMVC:Hello Worldを書いてみよう

何はともあれ「Hello World」
一番簡単な方法からです。

マークダウンでHello World

AmidaMVCを落としてくるとdemoフォルダーがあります。
この下に「hello.md」というファイルを作ります。

ここに
#Hello World
Hello to AmidaMVC.  
と書きます。

そして次のURLにアクセス。
http://your.host.here/pathto/AmidaMVC/demo/hello.md

your.host.herepathtoは適宜環境に合わせてください。
すると、最初のHello World画面が出るはず。


demoフォルダーの下に置いたのは、AmidaMVC直下だとルータマップが効いてしまって直接ファイルを指定してもアクセスできないためです。
中身のマークダウンファイルをHTMLに変換しています。

PHPでHello World?

次は「hello.php」を作ってみましょう。
「demo/hello.php」ファイルを作って、

<?php
echo 'Hello World from AmidaMVC';
?>
と入力して、アクセス。すると、どうでしょう。
PHPのソースコードが出てきました。


面白いでしょう?

現状でPHPを走らせるには・・・

「demo/hello.html」ファイルを作って、こう書きます。
<h1>Hello World</h1>
<?php echo '<p>Hello World from Html</p>'; ?>
と入力して、アクセスすると・・・


ちゃんとPHPとして動きました。

スキャンモードで各種ファイルを表示

AmidaMVCは要求されたURLを元にファイルシステムをスキャンできます。
ファイルを見つけたら、拡張子から中身を推測、HTMLに変換して、テンプレートに放り込んだ上で表示します。

ルートマップもあります。ルートマップに引っかかったファイルを優先して読み込みます。

対応している拡張子は:
  • マークダウン(md、markdown)
  • HTML(html)
  • テキスト(text,txt)
  • PHP ソースコード (php)
があります。
ソースコードを表示する機能は、ちょっとgitHubみたいで気に入っているのですが、さすがに変すぎるので、PHPファイルなら実行して、HTMLとして表示する予定です。

2012年1月31日火曜日

AmidaMVC:ComponentとAction

AmidaMVCが何をしているのか?

一言で言えば、コンポーネント(部品)を次々と実行するだけ。
格好良くコンポーネントと言ってますが、要するにクラスです。

コンポーネントの登録

たとえば、こんなコードです。


// Controllerを作成、
$ctrl = new \AmidaMVC\Framework\Controller();
// コンポーネントを追加。
$ctrl
    ->addComponent( 'Config', 'config' )
    ->addComponent( 'Router', 'router' )
    ->addComponent( 'Loader', 'loader' )
    ->addComponent( 'Render', 'render' )
;
// フレームワーク実行
$data = new \AmidaMVC\Component\SiteObj();
$ctrl->start( $data );

最初にSiteObjとControllerのオブジェクトを作成してから、
コントローラーにコンポーネントを追加してゆきます。

これらのコンポーネントを順番に実行してゆきます。

クラスなので、実際に走らせるにはメソード名が必要です。
最初は「actionDefault」というメソードを呼び続けます。つまり正常に動いている場合の処理をこのメソード内に書きます。

上の例だと、
・Config:設定用クラス。必要そうな値を設定。
・Router:URLから読み込むファイルを決定する。
・Loader:見つけたファイルを読み込む。
・Render:テンプレートを呼び出してHTMLを出力する。
という処理を順番に行います。

アクション

実行するメソード名は、アクションと読んでいます。
実際はactionAction、最初に「action」をつけて呼び出します。
例えばactionHelloとかです。

もしアクションが存在しない場合。
デフォルトのアクション「Default」を呼び出します。
つまり「actionDefault」のメソードが呼ばれます。

エラー処理の例

途中でエラーが起きたとします。
たとえばRouterでファイルがみつからなかった場合について考えてみます。
  • Routerでファイルがみつからない。
    この場合、Routerはアクションを「_PageNotFound」に変えて、次のコンポーネントに処理を渡します。
  • これ以降、「_PageNotFound」が呼び出されます。無ければデフォルトのアクションを実行します。
  • さて、Loaderの「_PageNotFound」のアクションでは、設定で指定していたファイル(PageNotFound.md)を読み込みます。
    この時点で、表示に必要なデータはそろったことになるので、正常系に戻します。つまり「actionDefault」を呼ぶようにコントローラーに命令します。
  • Renderはファイルが読み込まれているので、正常系の処理と同じになります。
とまぁ、こんな感じで、エラーがあった場合に異常系の処理をして、処理が終われば正常系の処理に戻したりが出来ます。これでフレームワークの設計が簡単になるんじゃないかと思った訳です。

2012年1月30日月曜日

AmidaMVC:今更PHPマイクロフレームワーク作ってみた

ちょこちょこ書いてますが、PHPのmicroframework作ってみました。
今更の感覚が強いですが、
  • 勉強のため、
と思って作ってみました。

でも勉強のためだけで作ることは無かったですね。
実は
  • アミダ式Dispatcher(と勝手に命名)
というロジックを思いついてしまって。
それをMVCフレームワークに応用したら面白そうだなと思ったら、作ってみたくて仕方がなくなり作ったという次第です。

ウェブサイトを作っていて、面倒なのがエラー処理。
ページが見つからないなどの処理をきれいに行いたいと思ってました。

アミダ式の説明は後で行いますが、
標準の処理が簡単なだけでなく、エラーなどの異常系の処理も簡単にできるのではないかと思っています。
まぁ自分が初めて考えついたロジックとは思いませんし、誰かがMVCに応用していてもおかしくはない、というか実はこれがMVCの標準的な処理だった、なんてオチはないといいのですが。こういうのは広い知識を持ってないのがつらいところです。

◆特徴は?

せっかく作ったので、何か特徴があるはず…
  • モデルやビューが無くても動く。
    一つのファイルにPHPとHTMLが混在していても、ちゃんとテンプレート内に入るようになります。もちろんクラスを作っても大丈夫。
  • ルートを設定してもしなくても動く。
  • ファイルビューワーとして、マークダウンファイルやテキストファイルをHTMLとして表示することが出来ます。PHPファイルもソースコードとして表示できたりします。
  • ファイルシステムがベース
    特徴なのかどうか分かりませんがデータベースは必要ありません。遅いと思いがちなファイルですが、今後SSDが普及するにつれ十分なスピードが出るようになるのではないでしょうか?すると簡単にファイルで作れるフレームワークも便利かなぁと。
その他、ファイルを直接修正したりすることも(多分簡単に)出来るはずなのですが、こうなるとフレームワークなのかCMSなのか分からなくなるので、適当なところで切り上げないと。

2012年1月17日火曜日

クロージャーを使ったPSR-0準拠のクラスローダー

PSR-0をベースにしたクラスローダーを探したのですが、全てクラスベースのクラスローダーしか見つかりませんでした。でコピーするのが面倒だったので、クロージャーを使ったクラスローダー作ってみました。
こういうのにクロージャーって便利なんですね。
初めてクロージャーをちゃんと使った気がする。
ソースコードはgitHubのGistにて公開しました。
https://gist.github.com/1620960#file_class_loader_ns.php


特徴は、パラメータ無しで動きます。

◆使い方は、たとえば次のようなクラスをロードする場合。
new AmidaMVC\Folder\SomeClass();

対応するクラスのが次の場所だったとします。
pathto/src/AmidaMVC/Folder/SomeClass.class

こういう場合は、pathto/src/AmidaMVC/bootstrap.php
などに上のGistコードを貼り付けてください。

spl_autoload_register( ClassLoader() );
普通、多分、他のコードを見る感じだとクラスをロードするには、ライブラリで使っているネームスペースとパスを指定する必要があります。
この関数は、呼ばれた場所がライブラリの一番上と仮定して、現在のフォルダーをネームスペース(例の場合はAmidaMVC)、そして現在のフォルダーをのぞいたパス(例の場合はpathto/src/)を設定します。

◆ただし、関数の定義が別ファイルにある場合は、先のbootstrap.phpで

spl_autoload_register( ClassLoader( __DIR__ ) );

とすれば動く「はず」です(動作は未確認)。

◆注意

今コードを見たら、バグがありますね。
少なくとも自分の環境では動いているので、ちょっと修正すれば動くと思います。また時間を見つけたら修正します。

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など様々な場所で使われてる技術・言葉みたいですね。

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

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年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に変更して、実行。
一旦テーブルをドロップしてから、作り直したらなおりました。

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