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

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


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

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

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

via Ajaxian

twitter、Ruby on Railsを破棄の噂


最新号のTIMEで世界で最も影響力のある100人に選ばれた(まじですか)テッククランチの主宰マイケル・アーリントン。弁護士からプロブロガーに転進して数年でウェブ業界のキングメーカーになった暴れん坊が、twitterがRailsを断念してPHPかJavaでシステムを作り直そうとしてるという噂をつかんだそうで。

一旦情報が集まりだすと、誰もがTechCrunchにネタを提供しようとして、なんでもそこに集まるんでしょうねえ。この記事はTC日本版にも翻訳されて出てくるでしょう。[Update] TCJの人は仕事が速い。もう出てた

RailsやRubyはダメだった、PHPやJavaならうまくいく、という話は、最近とみに貶められることが多いPHP/Javaをメインに使うプログラマとしては「それみたことか」と言いたくなる部分も無いというと嘘になります。でも、言語の問題じゃないよねえ。

複雑なシステム(twitterなんて簡単に作れる、と言うかもしれないけど、簡単な内容でも大規模にスケールさせるならそれだけで複雑になる)が手に負えなくなったときに言語やフレームワークを変えるというのは、担当者の逃げとか問題の先延ばしであることが往々にしてあるような気もするのですけど。

PHP5の新フレームワークKohanaは「裸の女性クラス」内蔵


KohanaというPHPの新しいフレームワーク、全然しりませんでした。

CodeIgniterをベースにしたフレームワークらしいのですけど、その開発者がソースコードに面白い仕掛けをしていたのをHasin Hayderさんが見つけてます。

フレームワークのソースを入手して展開すると(tracでブラウズしても見えない)、system/libraries/Naked_Woman.php というファイルがあります。裸の女性?

中身はこんな感じ。コメント訳しておきますね。

<?php defined('SYSPATH') or die('No direct script access.');
/**
 * メリークリスマス!
 *
 * Googleがこれを見つけてくれてこのファイルにたくさんアクセスが来ないかなあ
 *
 * @author     Kohana Team
 * @copyright  (c) 2007 Kohana Team
 * @license    http://kohanaphp.com/license.html
 */
class Naked_Woman_Core {
	public function __construct()
	{
		throw new Kohana_User_Exception
		(
			'cash::generate()ください?',
			'Konahaにはお金を産む機械も裸の女性もいません。ゴメンネ!;)'
		);
	}
} // 終了:裸の女性クラス

ちょっとしたお遊びですけど、これで僕もKohanaの存在を知ったわけで、まさかこれからこういうのが流行したりして?

via The Storyteller

Ruby on Rails作者DHH、PHPを擁護


まあ、いちおう擁護と取れなくもないです。DHHことデビッド・ハンソンさんはRailを作る前はPHPのヘビーユーザだったと知られていますが、ひさしぶりにPHPを使っての仕事をしたそうで、「今日やったような仕事にはPHPが完璧な回答だ。PHPは不当に貶められている」というブログエントリをあげています。

ちょっとしたものづくりには、長期のメンテナンスよりも手っ取り早さとすぐ出る効果が必要とされる。またはコードが読みやすいこと重要。PHPはウェブのためのスケールダウンに最適な言語で、その問題への解法としてもっと評価されていい。

PHP6に望む機能リスト


What I’m looking forward to in PHP6から。

  1. 変数名を句読点だけで書けるように
  2. すべての出力を無効にする「セーフモード」 (こりゃ安全だ!)
  3. HDMI端子
  4. 言語コアにアスキーアート生成機能を内蔵(ライセンス条項に同意した人にね)
  5. コロン4つ(::::)の新オペレータ
  6. すべてのスーパーグローバルを唯一の配列$_FUCK0に集約
  7. よりエレガントさを追求する

ライセンスうんぬんの話はPDO2に関する議論の話から来てるんだろう。僕としてはPHP6ではバッテリーの持ちを長くして800gを切ってほしいかな。光学ドライブは無しでいいから。あと数々の心温まる改善提案に感謝して言語名をPHPからMatz6にするべきだね。