Windows/symfony1.0.17のsymfony ccコマンドで警告が出る


こういうやつ。symfony ccとかでいっぱい出てきます。

Warning: chmod(): No error in C:\php\php-5.2.5\PEAR\symfony\vendor\pake\pakeFunction.php on line 273

これはWindows環境のみで起こるsymfony1.0.17のバグだそうです。warningだから動いてはいるんだけど。

symfonyコマンドでPhingエラーが出たとき


symfonyが呼んでいるPhingが、SfPeerBuilder.phpを見つけられないというエラーを吐いたとき

[PHP Error] Phing::include_once(symfony/symfony/addon/propel/builder/SfPeerBuilder.php): failed to open stream: No such file or directory [line 863 of C:/php-5.2.5/PEAR/symfony/vendor/phing/Phing.php]
[PHP Error] Phing::include_once(): Failed opening symfony/symfony/addon/propel/builder/SfPeerBuilder.php' for inclusion include_path='パス')

propel.iniの中のpropel.output.dir=以降のディレクトリ設定(sfPeerBuilderの場合はpropel.builder.peer.classとか)が違う可能性があります。他者のsymfonyプロジェクトを持ってきたときによく違っています。

ローカルで作った別のsymfonyプロジェクトからpropel.iniの該当部分をコピーすると直ったり。もちろん、元のプロジェクトの作者が意図的に変えているところは理解して残さないといけませんけど。

symfony1.1のtaskの作り方・使い方


symfony1.0ではinit-batchでCLI処理を作っていましたが、1.1ではtaskというのが導入されたようです。ブログで書かれていたチュートリアルを見ながら試してみます。バージョン1.1のCookbookにもこの解説は入るようです。

symfonyコマンドが元々呼び出せるタスク群(symfony generate:moduleとか)と同じように自分の作ったタスクを登録し、symfonyコマンドから呼び出すことができます。

$ symfony generate:task akky:hello-world

これで、akky:hello-worldという新タスクが登録されます。

symfonyコマンドを実行すると、タスクの一覧にもこのakky:hello-worldが出てきます。実行も既存タスクと同じで、

$ symfony akky:hello-world

このタスクの本体は、lib/task/akkyHelloworldTask.class.php にできています。

この生成されたコードの中に、タスクのヘルプを書いたりタスクが受け取れるパラメータを指定したり、そしてタスクの本体処理を書けます。

protected function execute($arguments = array(), $options = array())
{
// add code here
echo 'hello, world';
}

これで実行すると、symfonyコマンドからhello, worldを出力させることができました。

パラメータの受け取り方の詳細や、タスクから他のタスクを呼ぶ方法、環境に応じた処理の切り分け方法などは、元のブログ記事をどうぞ。

あと、generate:taskで作成はわかったけど、作ったタスクを消すにはどうするの、と該当するsymfonyコマンドが見当たらなくて迷ったのですけど、taskファイルを消してしまえばいいみたいです。

symfonyについて日本語で語りあうチャットが開始


人気PHPフレームワークsymfonyの新しいチャットルームが始まりました。symfonyを使っている人、興味のある人が気軽に情報交換できる場です。既に20人ものsymfony開発者が参加しています。

Skypeのパブリックチャットルームを使っているので、Skypeが必要です。スカイプはWindows, MacOSX, Linuxで動きます。

スカイプが起動したら、 http://tinyurl.com/5ek5xg にアクセスしてください。

僕は電話はほとんど使わないけど、Skypeチャットはよく使います。複数のパソコンからつなげることができて、それぞれで過去の発言をちゃんと読めるのが、某メッセンジャーより便利ですよ。

スカイプのチャットルームがはじめての方のために、便利な設定をいくつか紹介しますね。

デフォルトでは、誰かが発言するたびに、タスクバーが光ったり音がなったりします。これは人によっては邪魔でしょう。

チャットメッセージが来たときの音の通知を消す

メインウィンドウの[ツール]-[設定]-[サウンド]で、[チャットメッセージが着信したとき]のチェックをはずします

チャットルームからの通知を抑制する

チャットウィンドウの[オプション]-[チャット通知設定]で、[通知機能無効]をチェックします。

または、こっちのほうがオススメですが、同じ画面で[以下の単語が現れた時のみ通知]を選び、スペース区切りで「この単語が出てきたら通知してほしい」という単語を並べます。たとえば、

akky akimoto 秋元

とか。こうすると自分が呼ばれたときだけ通知が来ます。

チャットルームを閉じるとき、後で開きやすいように

チャットルームを閉じても、チャットには参加し続けていて、その間の会話も後で読むことができます。ただ、閉じたときに元のチャットルームを探して開くのがたいへんな場合もあるので、チャットウィンドウから[ブックマーク]-[このチャットをブックマーク]で、今いるチャットルームをブックマーク保存できます。

[関連]

#symfony-ja Skype Public Chatが出来ました

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

class myTextPayload
{
  public function getText()
  {
    return $this->text;
  }
  public function setText($text)
  {
    $this->text = $text;
  }
}

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

lib/filter/akkyHidePhoneNumberFilter.class.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);
  }
}

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

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オブジェクトにセットして保存とか)

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

秋元(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さんに指摘いただきました。考えてみればそうですね。