symfony1.1のアーキテクチャ解説

Fabienさんによる図入りのアーキテクチャ解説が出てます。

symfony1.1では、クラスとクラスの間の依存関係が減らされて(decoupled)います。YAML操作とかForm処理、データベースアクセスやキャッシュなどのクラスはそれぞれが単体でも呼び出せるようになっていて、そのためには


require_once '/path/to/sfCoreAutoload.class.php';
sfCoreAutoload::register();

の2行を書くだけ。あとはsymfonyのオートローダがよしなにやってくれます。これらがsymfony プラットフォーム

真ん中の方の図にあるように、MVCフレームワークを構成しているクラス群は、symfonyプラットフォームのクラスを必要に応じて呼び出しているけれども、symfonyフレームワークのMVCを使わずに、symfonyプラットフォームの便利なクラスだけを使うこともできるし、使わないものは使わない、そう、YahooがDel.icio.us2.0でsymfonyは採用したけどpropelは採用しなかったように、柔軟に選択することができる、ということになります。

バージョン1.1では、クラス間の依存関係をZend Framework以上にde-coupleした、と言っています。

symfony is one of the most decoupled framework available in PHP, even more than the Zend Framework

Zend Frameworkと比べ、いやいや、たとえば、symfony1.1のsfFormは、ビューやコントローラから切り離しにくいZend_Formよりも、より単独でMVCを絡ませずに使うこともできる、ということです。

[メモ] symfony/sfPayloadFilterChainPluginによる文字列のフィルタ保存

sfPayloadFilterChainPlugin

掲示板とかで、表示時にフィルタをかけるんじゃなくて、保存時にまずい文字列とかを見つけて伏字にしたりするためのsymfony プラグイン。

インストール方法

> symfony plugin-install http://plugins.symfony-project.com/sfPayloadFilterChainPlugin

設定ファイル

$ cd frontend/config/pfc
$ edit frontend/config/pfc/profiles.yml
post_comment: [censor_bad_words, hide_phone_number]

$ edit frontend/config/pfc/filters.yml

  censor_bad_words:
    enabled: on
    class:   myCensorshipFilter
    params:
      bad_words:        [死ね, 死ねばいいのに, 氏ね]
      replacement_word: "王大人に死亡確認されればいいのに"
  hide_phone_number:
    enabled: on
    class:   akkyHidePhoneNumberFilter
    params:
      replacement_word: "***-****-****"

payloadでフィルタするテキストを受け渡す作りで、説明にあるように単純なpayloadクラスを作っておく

lib/payload/myTextPayload.class.php

[code lang=”php”]
class myTextPayload
{
public function getText()
{
return $this->text;
}
public function setText($text)
{
$this->text = $text;
}
}
[/code]

あとはフィルタクラスを実装して配置。autoloadさせるので置いたら”symfony cc”を呼ぶこと

lib/filter/akkyHidePhoneNumberFilter.class.php

[code lang=”php”]
/**
* hide Japan’s phone number from text
*
*/
class akkyHidePhoneNumberFilter extends sfFilter
{
// not a perfect solution
// see http://blog.livedoor.jp/nipotan/archives/17526053.html
const PATTERN = ‘/(?:0\d{1,4}[-.]?)?\d{1,4}[-.]?\d{4}/’;
/**
* Make phone number unreadable.
*
* @param string $text
* @return string
*/
public function execute($chain, $payload)
{
$replacementWord
= $this->getParameter(‘replacement_word’, ‘xxx-xxxx-xxxx’);

// Retrieve text from payload
$text = $payload->getText();

$censoredText = preg_replace(self::PATTERN, $replacementWord, $text);

// Replace payload text
$payload->setText($censoredText);

// Execute next filter in chain
$chain->execute($payload);
}
}
[/code]

あとは、実際に書き込みの発生するところで、手動(アクション側)または自動(モデル側)でこのfilterを呼び出すことで、まずい単語にマスクをかけるフィルタなどを、フィールド毎に適用させることができます。

[code lang=”php”]
class messageActions extends sfActions
{
public function executePost()
{
$payloadComment = new myTextPayload();
$payloadComment->setText($this->getRequestParameter(‘comment’));
// Filter payload
$chain = new pfcPayloadFilterChain();
$chain->loadProfile(‘post_comment’);
$chain->setPayload($payloadComment);
$chain->execute();
$this->comment = $payloadComment->getText();

(このあとpropelオブジェクトにセットして保存とか)
[/code]

で、入力フィールドのこういうのが

秋元(030-5555-5555)死ね

こうなる

秋元(***-****-****)王大人に死亡確認されればいいのに

アクションごとに適用できるフィルタをきめ細かく変更できるところと、適用するfilterをyamlで調整したり、可変のパラメータを設定できたりするところが利点なんでしょうか。もうちょっと使ってみようかと思っています。

Windows+PHP+memcached+symfony

PHPマニュアル memcache

Windows用のmemcachedもバイナリパッケージで入手できるもんですね。手元の開発環境でどうしようかと思ったら、なんでもあるもんだ。

memcached-win32 Windows用のmemcached。サービス版とコマンド版両用 バイナリ版をzipで展開して適当な場所に置く

peclのWindows用バイナリ配布pecl4win からmemecahed拡張をダウンロード。5.2.5用はないので5.2.1用を。php-5.2.5/extとかに置く。

php.iniを編集して、extention=php_memcache.dll を追加。(Apache再起動)(このバイナリのdllにはmemcacheで”d”はついてないので注意)

sfMemcachePluginを、自分のsymfonyで作ったプロジェクトに入れる。

> symfony plugin-install http://plugins.symfony-project.com/sfMemcachePlugin

関数キャッシュのmemcached化の使用レポートin日本語を参考に、設定を行なう。

config_handlers.ymlとmemcache.ymlを、(アプリ名)/config/ にコピー。memcache.ymlの中のポート番号などは自分が動かしているmemcachedの設定に合わせて変更する。

conf/factories.ymlで、ViewをキャッシュするクラスをsfMemcacheCacheに置換する。

view_cache:
  class: sfMemcacheCache

もちろん、自分のsymfony appはテンプレートキャッシュを使う設定になってないといけない。開発環境でもcacheをオンにする設定は、たとえば、(apps)/settings.ymlにて

all:
  .settings:
    cache:     on

(apps)/cache.ymlにて

all:
  enabled:     on
  with_layout: false
  lifetime:    86400

など。(実際にはこんな乱暴に全actionにキャッシュをかけちゃだめ)

あとは、設定を反映させるために、symfonyキャッシュをクリア

> symfony cc

で、実行する。devモードの場合、一回目表示される水色の「キャッシュがなかったので作ったよ」マークが二回目の表示で黄色になればOK。

実行した結果、memcachedが本当に使われているかどうかを確認するには、memcachedの内容を確認するにはにあるようなスクリプトでmemcachedの状態を表示します。

[追記] クライアント側のライブラリだからdがついてない、とelfさんに指摘いただきました。考えてみればそうですね。

JavascriptをPNG画像として圧縮する

prototype.jsをバイナリ列とみて、8ビットのPNG形式で可逆圧縮したものだそうです。

これをFirefoxやOperaなどcanvasに対応したブラウザでcanvasに描画し、getImageData()で画像からデータを取り出し、eval()してJavascriptとして再実行させることで、この画像圧縮されたprototype.jsを実行しているそうで。

作者自身も、gzipによる圧縮のほうがいいのでこれを現実的なサービスに適用する意味はないと書いているのですが、画像にスクリプト(やその他も)を埋め込むことで何かするアイデアが派生してくるかもしれないですね。Ajaxianのコメントには、これでFlickrをスクリプトストレージにできるな、というのも出ていましたけど。

via Ajaxian