ぷぎがぽぎ このページをアンテナに追加 RSSフィード

2008-10-12

[][]sfFormのメッセージの日本語化

以下のようなメッセージファイルを<アプリケーション>/i18n/form.ja.xmlに用意し

<xliff version="1.0">
  <file orginal="global" source-language="en_US" datatype="plaintext">
    <body>
      <trans-unit>
        <source>Required.</source>
        <target>未入力の必須項目があります</target>
      </trans-unit>
      <trans-unit>
        <source>Invalid.</source>
        <target>入力した値を再度確認してください</target>
      </trans-unit>
      <trans-unit>
        <source>CSRF attack detected.</source>
        <target>画面遷移が確認できませんでした</target>
      </trans-unit>
      <trans-unit>
        <source>"%value%" does not match the date format (%date_format%).</source>
        <target>"%value%"が日付のフォーマット (%date_format%)に一致しません</target>
      </trans-unit>
      <trans-unit>
        <source>The date must be before %max%.</source>
        <target>日付は %max% より前を指定してください</target>
      </trans-unit>
      <trans-unit>
        <source>The date must be after %min%.</source>
        <target>日付は %min% より後を指定してください</target>
      </trans-unit>
      <trans-unit>
        <source>"%value%" must be less than %max%.</source>
        <target>"%value%" は %max% より小さい値を指定してください</target>
      </trans-unit>
      <trans-unit>
        <source>"%value%" must be greater than %min%.</source>
        <target>"%value%" は %min% より大きい値を指定してください</target>
      </trans-unit>
      <trans-unit>
        <source>Unexpected extra form field named "%field%".</source>
        <target>"%field%" という不明のフィールドがあります</target>
      </trans-unit>
      <trans-unit>
        <source>"%value%" is too long (%max_length% characters max).</source>
        <target>入力文字数がオーバーしています (%max_length%文字以下)</target>
      </trans-unit>
      <trans-unit>
        <source>"%value%" is too short (%min_length% characters min).</source>
        <target>入力文字数が不足しています (%min_length%文字以上)</target>
      </trans-unit>
      <trans-unit>
        <source>"%value%" does not match the time format (%time_format%).</source>
        <target>"%value%"が時刻のフォーマット (%time_format%)に一致しません</target>
      </trans-unit>
      <trans-unit>
        <source>An object with the same "%column%" already exist.</source>
        <target>既に登録されています</target>
      </trans-unit>
    </body>
  </file>
</xliff>

フォームクラスで

 $this->widgetSchema->getFormFormatter()->setTranslationCatalogue('form');

とすればメッセージを日本語化できます。

ただし、getErrorSchema()をechoしたものは日本語化されないですね。

また、細かなメッセージ制御は難しいのが現状。テンプレート側で制御した方が良い印象。

このあたりをメッセージファイルだけでやりとりするのは限界かな。

ただ、とりあえず動くものを作りたいのであればこの部分だけ日本語化しておくだけでも印象は違うかも。(気持ち的なことなんですけどね)

2008-10-01

[][] コンポーネントやパーシャルの呼び出しが便利になっている件

多用することがいいかどうかは別として、symfony1.1からはコントローラー内から簡単にパーシャルやコンポーネントのレンダー結果を取得することができるようになりました。

つまり、次のようなメソッドが用意されたということです。

// in action
public function executeIndex($request)
{
  // なんか処理
  $component_result = $this->getComponent('モジュール名', 'コンポーネント名', array('渡したい変数'));
  $partial_result = $this->getPartial('テンプレート名', array('渡したい変数'));
}

一番の使い道はメールの本文をテンプレートを使って作成する方法でしょうね。

今までは別のアクションにforwardさせたりしないと分離できないという悲しい方法しかありませんでしたがこれですっきりできます。万歳。


また、テンプレートを共通化するという方法でも利用場面はありそうです。この場合レンダーの結果を変数ではなく出力するメソッド(renderComponent, renderPartial)も用意されているのでこれらを使うと便利です。

たとえば、Ajaxで同じ部品を何度も再描画するような場面ではコンポーネントを作っておいてテンプレートからは

// in template
<?php include_component('ajax', 'update') ?>

としておき、Ajaxでリクエストされるアクションでは

// in action
public function executeUpdate($request)
{
 return $this->renderComponent('ajax', 'update');
}

とすれば簡単に処理をコンポーネントに共通化できスッキリします。

また、symfony1.1からはアクションにある実行メソッドには引数として$requestを常に渡すようになりました。

これはコンポーネントの実行メソッドでも同様ですので、コンポーネントでsfRequestオブジェクトにアクセスするのはこれを使うようにすることをお忘れなく。

// in template
<?php include_component('ajax', 'update') ?>

// in component
public function executeUpdate($request)
{
  $hoge = $reuqest->getParameter('hoge');
}

このようにsymfony1.0系で不満だった部分が解消されています。

2008-09-18

[][]sfFormを楽して可読性を向上させる

1週間ぐらいsfFormと向き合っているにもかかわらず、仲良くなれてない。一通り使うまでしょうがないとわかりつつ。。

そして、symfonyの学習コストは確実にあがっていっている気がする。

ただし、プログラマとしてsymfonyのソースを読み解いたり、実装を理解するのは楽しいもんです。

話がそれそうなので本題。

symfonyの新しいフォームフレームワークとして登場したsfFormですが、なかなか面倒です。

決して楽ができるわけではないというところが痛いところです。

なので、symfonyで開発日記で紹介されているsfFormatasticPluginは導入したほうが良いです。

sfFormtasticPluginを使えばこのようにFormクラスを比較的簡単にYAMLで作り出すことが出来ます。また、Actionクラスは自分でFormクラスを書いていた時と全く同じです。sfFormtasticPluginを使うからといって、Actionクラスに手を入れる必要はありません。

symfony1.1使いに役立つかもしれないsfFormについての知識

ただし、build-formで作成したクラスや上記で作成したFormクラスをそのまま使うことはほとんどなく拡張クラスにて設定を上書きしたりすることになります。

そのときに、自動生成されたFormクラスのソースをコピペして変更したりするとソースの可読性が落ちてしまいます。

というのも、yamlの設定では項目ごとに記述しているのに、ソースでは項目ごとではなく、setterを使ってwidget毎やvalidator毎のメソッドに集約されてしまっているからです。

    $this->setWidgets(array(
      ‘mail’     => new sfWidgetFormInput,
      ‘password’ => new sfWidgetFormInputPassword,
    ));

    $this->setValidators(array(
      ‘mail’     => new sfValidatorString(array(), array(‘required’ => ‘メールアドレスは必須です’)),
      ‘password’ => new sfValidatorString(array(‘min_length’ => 6), array(‘min_length’ => ‘パスワードは6文字以上で設定してください’, ‘required’ => ‘パスワードは必須です’)),
    ));

というわけで、拡張クラスで項目の設定を変更するときは項目名を$keyなどの変数にいれておいて、以下のようなコーディングで項目毎の設定をconfigure()メソッド内に書くようにしています。

    //--------------------------------------------------//
    // mail
    $key = 'mail';
    $this->widgetSchema[$key] = new sfWidgetFormInput();
    $this->widgetSchema->setLabel($key, 'メールアドレス');
    $this->widgetSchema->setHelp($key, 'PCのメールアドレスを入力してください');
    // $this->widgetSchema[$key]->setHidden(true);  // フォームをhiddenにする場合
    $this->validatorSchema[$key] = new sfValidatorString();
    $this->validatorSchema[$key]->setOption('required', true);
    $this->validatorSchema[$key]->setMessage('required', 'メールアドレスは必須です');
    //--------------------------------------------------//
    // password
    $key = 'password';
    $this->widgetSchema[$key] = new sfWidgetFormPassword();
    $this->widgetSchema->setLabel($key, 'パスワード');
    // $this->widgetSchema->setHelp($key, '');
    // $this->widgetSchema[$key]->setHidden(true);  // フォームをhiddenにする場合
    $this->validatorSchema[$key] = new sfValidatorString();
    $this->validatorSchema[$key]->setOption('required', true);
    $this->validatorSchema[$key]->setMessage('min_length', 'パスワードは6文字以上で設定してください');
    $this->validatorSchema[$key]->setOption('min_length', 6);
    $this->validatorSchema[$key]->setMessage('required', 'パスワードは必須です');

この書き方でさきほどの書き方と同じ機能が実装されます。

メリットは

  • 項目毎の設定がわかりやすい。(arrayから可能な限り解放される)
  • 不要な機能はコメントアウトすればいい
  • 機能を追加、変更したい場合は行単位のコピペで対応できる

もちろんデメリットは行数が増える*1。。ですが、メンテナンス性では向上すると思いますがいかがでしょ?

*1:$r = $this->validatorSchema[$key] のようにリファレンス変数を用意するのもありですね

2008-09-06

[] バッチのタスクでデータベースを使う場合

symfony1.0系とそれ以降の違いで大きなものの1つがバッチ処理の管理方法です。

1.0系ではバッチ用のコントローラーをbatchディレクトリに作成していましたが、1.1系以降ではタスク(コマンド)で管理します。

もちろん、初期化コマンドが用意されているのでgenerate:taskにネームスペースとタスク名をわたすだけでOKです。

$ ./symfony generate:task batch:taskname

で、タスクの中でDBアクセスを行う場合は、本家では

    $databaseManager = new sfDatabaseManager($this->configuration);

を記述するように書かれていますが、

ref: http://www.symfony-project.org/blog/2008/06/14/batches-are-dead-long-life-to-tasks

このまま記述してタスクを実行しても次のようなエラーになります。

$ ./symfony batch:taskname
PHP Catchable fatal error:  Argument 1 passed to sfDatabaseManager::__construct() must be an instance of sfApplicationConfiguration, instance of ProjectConfiguration given, 

原因はアプリケーション名を指定していないからでした。

生成されたタスクファイルの以下の行をコメントアウトを外し、アプリケーション名をオプションで必ず渡すようにします。

  $this->addArgument('application', sfCommandArgument::REQUIRED, 'The application name');

これで、

$ ./symfony batch:taskname admin

のようにアプリケーション名を渡すことでデータベースアクセスが正常にできました。

よく考えてみれば当たり前だけどハマった。

2008-09-03

[] symfony1.0から1.1に慣れる ~ その1 ~

そのうちwikiにまとめた方が有用なんでしょうが、とりあえずここにメモ。

タスクはhelpで確認する

symfony1.1からタスクの利用方法がhelpオプションを指定することで確認できるので見ておいたほうが幸せになれる

$ ./symfony help <タスク名>

エスケープの設定

$ ./symfony generate:app admin --escaping-strategy=on --csrf-secret=HogeHageFuge

エスケープの設定が1.0のころと変わってるので理解しておくこと。

ちなみに、設定ファイルをいじらなくてもアプリケーション作成タスクのオプションでonにすればよい。

というのもescaping-strategyはデフォルトでoffになっているので。

また、csrf-secretはCSRF対策としてのトークンに用いる秘密のキーを設定できます。これもやっておくとよろし

データベースの設定もタスクで

ファイルを直接さわらなくてもタスクが用意されている。

$ ./symfony configure:database

アドミンジェネレータを使う場合は互換モードをonに

symfony1.1はアドミンジェネレータがまだsfFormなどに対応していないため、

compat_10: on にしなければならない。

2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2015 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2016 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |