<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>digital matter &#187; Programming</title>
	<atom:link href="http://blog.loadlimits.info/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.loadlimits.info</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Tue, 22 Jun 2010 10:46:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Symfonyで外部のプログラムを実行する</title>
		<link>http://blog.loadlimits.info/2010/06/symfony%e3%81%a7%e5%a4%96%e9%83%a8%e3%81%ae%e3%83%97%e3%83%ad%e3%82%b0%e3%83%a9%e3%83%a0%e3%82%92%e5%ae%9f%e8%a1%8c%e3%81%99%e3%82%8b/</link>
		<comments>http://blog.loadlimits.info/2010/06/symfony%e3%81%a7%e5%a4%96%e9%83%a8%e3%81%ae%e3%83%97%e3%83%ad%e3%82%b0%e3%83%a9%e3%83%a0%e3%82%92%e5%ae%9f%e8%a1%8c%e3%81%99%e3%82%8b/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 10:46:39 +0000</pubDate>
		<dc:creator>hotpi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[解決]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://blog.loadlimits.info/2010/06/symfony%e3%81%a7%e5%a4%96%e9%83%a8%e3%81%ae%e3%83%97%e3%83%ad%e3%82%b0%e3%83%a9%e3%83%a0%e3%82%92%e5%ae%9f%e8%a1%8c%e3%81%99%e3%82%8b/</guid>
		<description><![CDATA[Symfony 1.4でシェルのプログラムを呼び出すときに、PHPのexec関数に代わる便利なメソッドがあったのでメモ。 
sfFilesystem::execute()がそれです。   symfony API » sfFilesystem Class &#124; symfony &#124; Web PHP Framework
内部的にはproc_openで   戻り値は、標準出力と標準エラー出力が分離されて配列で返ってきます。 
タスクから、呼び出すとこんな感じになります。

    protected
        $outputBuffer = '';

    protected function execute($arguments = array(), $options = array())
    {
       [...]]]></description>
			<content:encoded><![CDATA[<p>Symfony 1.4でシェルのプログラムを呼び出すときに、PHPのexec関数に代わる便利なメソッドがあったのでメモ。 </p>
<p>sfFilesystem::execute()がそれです。   <br /><a href="http://www.symfony-project.org/api/1_4/sfFilesystem" target="_blank">symfony API » sfFilesystem Class | symfony | Web PHP Framework</a></p>
<p>内部的にはproc_openで   <br />戻り値は、標準出力と標準エラー出力が分離されて配列で返ってきます。 </p>
<p>タスクから、呼び出すとこんな感じになります。</p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>    protected
        $outputBuffer = '';

    protected function execute($arguments = array(), $options = array())
    {
        // initialize the database connection
        $databaseManager = new sfDatabaseManager($this-&gt;configuration);
        $connection = $databaseManager-&gt;getDatabase($options['connection'] ? $options['connection'] : null)-&gt;getConnection();

        // 処理待ちリストから一行取得
        $process = Doctrine::getTable('Processes')-&gt;findOneByStatus('WAIT');
        $command = $process['command'];

        // バッファクリア
        $this-&gt;outputBuffer = '';
        try {
            // 実行。第二引数は標準出力、第三引数は標準エラー出力を受け取るコールバック関数
            list($output, $err) = $this-&gt;getFilesystem()-&gt;execute($command, array($this, 'setBuffer'), array($this, 'setBuffer'));
            $process['status'] = 'SUCCESS';
            $process['message'] = $output;
            $process-&gt;save();
        } catch (RuntimeException $e) {
            // コマンドが実行できなかった場合と、終了時エラーの場合はRuntimeExceptionがthrowされる
            $process['status'] = 'FAILED';
            // エラー時はexecuteの戻り値を取得できないのでコールバックの結果からメッセージを取得
            $process['message'] = $this-&gt;outputBuffer;
            // 必要なら$e-&gt;getCode();でエラーコード取得できます
            $process-&gt;save();
        }
    }

    public function setBuffer($output)
    {
        $this-&gt;outputBuffer .= $output;
    }
</pre>
</div>
<p>/vendor/pear/php/symfony/task/project/sfProjectDeployTask.class.phpがサンプルとして使えます。 </p>
<p>もちろん、PHPのexec関数を使って<br />
  <br />exec($command, $output = array(), $return_var = 0);</p>
<p>とかしてもいいと思います。 </p>
<p>多分プラグインのインストール段階でmakeとかするときに使うんじゃないですかね。<br />
  <br />標準出力を段階的に画面に表示できるので。 </p>
<p>ただし、出力バッファの読み取り単位ごとに、0.1秒のディレイをかけているようなので、速度重視なところでは注意が必要です。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.loadlimits.info/2010/06/symfony%e3%81%a7%e5%a4%96%e9%83%a8%e3%81%ae%e3%83%97%e3%83%ad%e3%82%b0%e3%83%a9%e3%83%a0%e3%82%92%e5%ae%9f%e8%a1%8c%e3%81%99%e3%82%8b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfonyのクライアントサイドバリデータ</title>
		<link>http://blog.loadlimits.info/2010/06/symfony%e3%81%ae%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e3%82%b5%e3%82%a4%e3%83%89%e3%83%90%e3%83%aa%e3%83%87%e3%83%bc%e3%82%bf/</link>
		<comments>http://blog.loadlimits.info/2010/06/symfony%e3%81%ae%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e3%82%b5%e3%82%a4%e3%83%89%e3%83%90%e3%83%aa%e3%83%87%e3%83%bc%e3%82%bf/#comments</comments>
		<pubDate>Thu, 17 Jun 2010 14:13:45 +0000</pubDate>
		<dc:creator>hotpi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[解決]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://blog.loadlimits.info/2010/06/symfony%e3%81%ae%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e3%82%b5%e3%82%a4%e3%83%89%e3%83%90%e3%83%aa%e3%83%87%e3%83%bc%e3%82%bf/</guid>
		<description><![CDATA[SymfonyでjQueryを使ったクライアントサイドのバリデーションを簡単に実現できるjnAjaxFormValitatorというプラグインがあったので、試してみました。
このプラグインはフォームが変更された際に、Ajaxでサーバにバリデーションルールと値を送ってサーバサイドでバリデーションをかけ、その結果を表示します。
結論から言うと、簡単に導入できて便利ですが、一部セキュリティ的に難あり、
1.2用ですが、ちょっとの修正で1.4でも使えます。
まずはダウンロード。
Plugins &#124; jnAjaxFormValidatorPlugin &#124; 1.0.2 &#124; symfony &#124; Web PHP Framework
 
ダウンロードしなくてもサーバから直接インストールできるらしいのですが、今回はtgzファイルをダウンロードしてきてインストールしました。
$ ./symfony plugin:install ./jnAjaxFormValidatorPlugin-1.0.2.tgz   &#62;&#62; plugin&#160;&#160;&#160; installing plugin &#34;./jnAjaxFormValidatorPlugin-1.0.2.tgz&#34;    &#62;&#62; sfSymfonyPluginManager Installation successful for plugin &#34;./jnAjaxFormValidatorPlugin-1.0.2.tgz&#34;
インストール成功したら、アプリケーション以下のconfig/setting.ymlを開いてモジュールを有効にする設定を書きます。
all:   &#160; .settings:    &#160;&#160;&#160; enabled_modules:&#160;&#160;&#160;&#160;&#160;&#160;&#160; [default, jnAjaxFormValidator]
READMEは全部スペルミスでjnAjaxFormValitatorになっているのでコピペすると間違えます。
次はアプリケーション以下のconfig/routing.ymlに以下を追加します。
 # &#8212;&#8211; jnAjaxFormValidator &#8212;&#8211;  jnAjaxFormValidator_validateJSON:  &#160; url:&#160;&#160; /jnAjaxFormValidator/validateJSON  &#160; [...]]]></description>
			<content:encoded><![CDATA[<p>SymfonyでjQueryを使ったクライアントサイドのバリデーションを簡単に実現できる<a href="http://www.symfony-project.org/plugins/jnAjaxFormValidatorPlugin" target="_blank">jnAjaxFormValitator</a>というプラグインがあったので、試してみました。</p>
<p>このプラグインはフォームが変更された際に、Ajaxでサーバにバリデーションルールと値を送ってサーバサイドでバリデーションをかけ、その結果を表示します。</p>
<p>結論から言うと、簡単に導入できて便利ですが、一部セキュリティ的に難あり、</p>
<p>1.2用ですが、ちょっとの修正で1.4でも使えます。</p>
<p>まずはダウンロード。</p>
<p><a href="http://www.symfony-project.org/plugins/jnAjaxFormValidatorPlugin" target="_blank">Plugins | jnAjaxFormValidatorPlugin | 1.0.2 | symfony | Web PHP Framework</a></p>
<p><a href="http://blog.loadlimits.info/wp-content/uploads/2010/06/20100617223542.png"><img style="border-bottom: 0px;border-left: 0px;border-top: 0px;border-right: 0px" border="0" alt="20100617223542" src="http://blog.loadlimits.info/wp-content/uploads/2010/06/20100617223542_thumb.png" width="496" height="313" /></a> </p>
<p>ダウンロードしなくてもサーバから直接インストールできるらしいのですが、今回はtgzファイルをダウンロードしてきてインストールしました。</p>
<p>$ ./symfony plugin:install ./jnAjaxFormValidatorPlugin-1.0.2.tgz   <br />&gt;&gt; plugin&#160;&#160;&#160; installing plugin &quot;./jnAjaxFormValidatorPlugin-1.0.2.tgz&quot;    <br />&gt;&gt; sfSymfonyPluginManager Installation successful for plugin &quot;./jnAjaxFormValidatorPlugin-1.0.2.tgz&quot;</p>
<p>インストール成功したら、アプリケーション以下のconfig/setting.ymlを開いてモジュールを有効にする設定を書きます。</p>
<p>all:   <br />&#160; .settings:    <br />&#160;&#160;&#160; enabled_modules:&#160;&#160;&#160;&#160;&#160;&#160;&#160; [default, jnAjaxFormValidator]</p>
<p>READMEは全部スペルミスでjnAjaxFormVali<strong>t</strong>atorになっているのでコピペすると間違えます。</p>
<p>次はアプリケーション以下のconfig/routing.ymlに以下を追加します。</p>
<p> # &#8212;&#8211; jnAjaxFormValidator &#8212;&#8211;  <br />jnAjaxFormValidator_validateJSON:  <br />&#160; url:&#160;&#160; /jnAjaxFormValidator/validateJSON  <br />&#160; param: { module: jnAjaxFormValidator, action: validateJSON }  <br /> 
<p>その後、キャッシュをクリアします。</p>
<p>$ ./symfony cc</p>
<p>バリデーションを使用するテンプレートの先頭にでも、</p>
<p> &lt;?php use_helper(&#8216;ajaxFormValidator&#8217;) ?&gt;  <br />&lt;?php echo ajaxAllFieldsValidators($form) ?&gt;  <br /> 
<p>と書いておけばOKです。</p>
<p>インストール手順はこれで完了ですが、このままだとSymfony 1.4で動かないので、actions.class.phpを修正します。</p>
<p>/plugins/jnAjaxFormValidatorPlugin/modules/jnAjaxFormValidator/actions/actions.class.php 29行目   <br />sfLoader::loadHelpers(&#8216;I18N&#8217;);    <br />↓    <br />sfContext::getInstance()-&gt;getConfiguration()-&gt;loadHelpers(array(&#8216;I18N&#8217;));</p>
<p>以上で完了です。</p>
<p><a href="http://blog.loadlimits.info/wp-content/uploads/2010/06/20100617225540.png"><img style="border-bottom: 0px;border-left: 0px;border-top: 0px;border-right: 0px" border="0" alt="20100617225540" src="http://blog.loadlimits.info/wp-content/uploads/2010/06/20100617225540_thumb.png" width="439" height="176" /></a> </p>
<p>あと、書き出されるエラーが   <br />&lt;ul class=&quot;error_list&quot;&gt;&lt;li&gt;エラーメッセージ&lt;/li&gt;&lt;/ul&gt;    <br />の構造に固定されているので、必要であればヘルパー側を修正する必要があります。</p>
<p>難点は、バリデーションのルールをブラウザ側に一度保持することです。単純にバリデータクラス名とバリデーションルール、値をJSからサーバに送信してバリデータを実行しているだけなので。</p>
<p><a href="http://blog.loadlimits.info/wp-content/uploads/2010/06/20100617225648.png"><img style="border-bottom: 0px;border-left: 0px;border-top: 0px;border-right: 0px" border="0" alt="20100617225648" src="http://blog.loadlimits.info/wp-content/uploads/2010/06/20100617225648_thumb.png" width="463" height="165" /></a></p>
<p>上の図はリクエスト時のパラメータです。GETで送られます。何が問題かというと、サーバ内のバリデーションルールが表に流れるので、攻撃者が穴を見つけやすくなるということですね。</p>
</p>
<p>バリデーションは完璧で、特にクリティカルな要件でないなら使えると思います。</p>
<p>あと、返されるエラーメッセージはformで定義したものを使えないので、デフォルトのエラーメッセージになります。</p>
<p>デフォルトのエラーメッセージは、アプリケーションのConfigurationなどで</p>
<p>sfValidatorBase::setDefaultMessage(&#8216;max_length&#8217;, &#8216;%max_length%文字までにしてください&#8217;);</p>
<p>などとしておくか、カタログファイルでも変更できます。</p>
<p>ちなみにソースコードはびっくりするくらいシンプル。チェコ人が作ったらしく、I18Nも意識されてます。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.loadlimits.info/2010/06/symfony%e3%81%ae%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88%e3%82%b5%e3%82%a4%e3%83%89%e3%83%90%e3%83%aa%e3%83%87%e3%83%bc%e3%82%bf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>sfWidgetFormInputCheckboxの正負を反転させる その２</title>
		<link>http://blog.loadlimits.info/2010/06/sfwidgetforminputcheckbox%e3%81%ae%e6%ad%a3%e8%b2%a0%e3%82%92%e5%8f%8d%e8%bb%a2%e3%81%95%e3%81%9b%e3%82%8b-%e3%81%9d%e3%81%ae%ef%bc%92/</link>
		<comments>http://blog.loadlimits.info/2010/06/sfwidgetforminputcheckbox%e3%81%ae%e6%ad%a3%e8%b2%a0%e3%82%92%e5%8f%8d%e8%bb%a2%e3%81%95%e3%81%9b%e3%82%8b-%e3%81%9d%e3%81%ae%ef%bc%92/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 09:53:54 +0000</pubDate>
		<dc:creator>hotpi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[解決]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://blog.loadlimits.info/2010/06/sfwidgetforminputcheckbox%e3%81%ae%e6%ad%a3%e8%b2%a0%e3%82%92%e5%8f%8d%e8%bb%a2%e3%81%95%e3%81%9b%e3%82%8b-%e3%81%9d%e3%81%ae%ef%bc%92/</guid>
		<description><![CDATA[前回のエントリで、モデルを拡張して読み出し時と保存時に正負反転させる方法を紹介しましたが、カラム名と実際の動作が逆になってしまって紛らわしいので、widgetとvalidatorで反転させることにしました。Symfony 1.4+Doctrineです。
既存のsfWidgetFormInputCheckboxとsfValidatorBooleanを継承して実装します。
lib/widget/sfWidgetFormInputCheckboxInverse.class.php

&#60;?php

class sfWidgetFormInputCheckboxInverse extends sfWidgetFormInputCheckbox
{
    public function render($name, $value = null, $attributes = array(), $errors = array())
    {

        if (!(null !== $value &#38;&#38; $value !== false))
        {
         [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.loadlimits.info/2010/06/sfwidgetforminputcheckbox%E3%81%AE%E6%AD%A3%E8%B2%A0%E3%82%92%E5%8F%8D%E8%BB%A2%E3%81%95%E3%81%9B%E3%82%8B-%E3%81%9D%E3%81%AE%EF%BC%91/" target="_blank">前回のエントリ</a>で、モデルを拡張して読み出し時と保存時に正負反転させる方法を紹介しましたが、カラム名と実際の動作が逆になってしまって紛らわしいので、widgetとvalidatorで反転させることにしました。Symfony 1.4+Doctrineです。</p>
<p>既存のsfWidgetFormInputCheckboxとsfValidatorBooleanを継承して実装します。</p>
<p>lib/widget/sfWidgetFormInputCheckboxInverse.class.php</p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>&lt;?php

class sfWidgetFormInputCheckboxInverse extends sfWidgetFormInputCheckbox
{
    public function render($name, $value = null, $attributes = array(), $errors = array())
    {

        if (!(null !== $value &amp;&amp; $value !== false))
        {
            $attributes['checked'] = 'checked';
        }

        if (!isset($attributes['value']) &amp;&amp; null !== $this-&gt;getOption('value_attribute_value'))
        {
            $attributes['value'] = $this-&gt;getOption('value_attribute_value');
        }

        return parent::render($name, null, $attributes, $errors);
    }
}
</pre>
</div>
<p>lib/validator/sfValidatorBooleanInverse.class.php</p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>&lt;?php

class sfValidatorBooleanInverse extends sfValidatorBoolean
{

    protected function configure($options = array(), $messages = array())
    {
        parent::configure($options, $messages);
        $this-&gt;setOption('empty_value', true);
    }

    protected function doClean($value)
    {
        if (in_array($value, $this-&gt;getOption('true_values')))
        {
          return false;
        }

        if (in_array($value, $this-&gt;getOption('false_values')))
        {
          return true;
        }

        throw new sfValidatorError($this, 'invalid', array('value' =&gt; $value));
    }

}
</pre>
</div>
<p>ほぼ、逆にしたメソッドでオーバーライドしただけです。チェックボックスにチェックを入れなかった場合の挙動がデフォルトではfalseなので、trueに変更しています。</p>
<p>これをformクラスから</p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>        $this-&gt;widgetSchema['show_flag'] = new sfWidgetFormInputCheckboxInverse();
        $this-&gt;validatorSchema['show_flag'] = new sfValidatorBooleanInverse();
</pre>
</div>
<p>のように定義してやればいいだけです。</p>
<p>例によってカラムのタイプがbooleanになっていることを確認してください。なっていないと0でも1でもtrueと判断されてしまうので。</p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>        $this-&gt;hasColumn('show_flag', 'boolean', null, array(
             'type' =&gt; 'boolean',
             'notnull' =&gt; true,
             'default' =&gt; 0,
             ));
</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.loadlimits.info/2010/06/sfwidgetforminputcheckbox%e3%81%ae%e6%ad%a3%e8%b2%a0%e3%82%92%e5%8f%8d%e8%bb%a2%e3%81%95%e3%81%9b%e3%82%8b-%e3%81%9d%e3%81%ae%ef%bc%92/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>sfWidgetFormInputCheckboxの正負を反転させる その１</title>
		<link>http://blog.loadlimits.info/2010/06/sfwidgetforminputcheckbox%e3%81%ae%e6%ad%a3%e8%b2%a0%e3%82%92%e5%8f%8d%e8%bb%a2%e3%81%95%e3%81%9b%e3%82%8b-%e3%81%9d%e3%81%ae%ef%bc%91/</link>
		<comments>http://blog.loadlimits.info/2010/06/sfwidgetforminputcheckbox%e3%81%ae%e6%ad%a3%e8%b2%a0%e3%82%92%e5%8f%8d%e8%bb%a2%e3%81%95%e3%81%9b%e3%82%8b-%e3%81%9d%e3%81%ae%ef%bc%91/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 09:39:01 +0000</pubDate>
		<dc:creator>hotpi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[解決]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://blog.loadlimits.info/2010/06/sfwidgetforminputcheckbox%e3%81%ae%e6%ad%a3%e8%b2%a0%e3%82%92%e5%8f%8d%e8%bb%a2%e3%81%95%e3%81%9b%e3%82%8b-%e3%81%9d%e3%81%ae%ef%bc%91/</guid>
		<description><![CDATA[symfony 1.4にて。データベースの定義は「表示」フラグなのに、フォームでは「非表示」時にチェックを入れさせたい場合などがありまして。
データベースのカラム自体の意味を変えるのは、逆にフォームの意味が今後変わったときにどうするんだという話なので、今回はモデルでの入出力時点で値を変更する方法を試してみました。
actAsで各モデルの好きなカラムを反転できる拡張にしてみました。
lib/InvertBoolean.class.php


&#60;?php

class InvertBoolean extends Doctrine_Template
{
    protected $_options = array(
        'columns' =&#62; array()
    );

    public function setTableDefinition()
    {
        $this-&#62;addListener(new InvertBooleanListener($this-&#62;_options));
    }

    public function setUp()
 [...]]]></description>
			<content:encoded><![CDATA[<p>symfony 1.4にて。データベースの定義は「表示」フラグなのに、フォームでは「非表示」時にチェックを入れさせたい場合などがありまして。</p>
<p>データベースのカラム自体の意味を変えるのは、逆にフォームの意味が今後変わったときにどうするんだという話なので、今回はモデルでの入出力時点で値を変更する方法を試してみました。</p>
<p>actAsで各モデルの好きなカラムを反転できる拡張にしてみました。</p>
<p>lib/InvertBoolean.class.php</p>
<p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>&lt;?php

class InvertBoolean extends Doctrine_Template
{
    protected $_options = array(
        'columns' =&gt; array()
    );

    public function setTableDefinition()
    {
        $this-&gt;addListener(new InvertBooleanListener($this-&gt;_options));
    }

    public function setUp()
    {
    }
}
</pre>
</div>
<p>lib/model/invert_boolean/InvertBooleanListener.class.php</p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>&lt;?php

class InvertBooleanListener extends Doctrine_Record_Listener
{
    protected $_options;

    public function __construct(array $options)
    {
        $this-&gt;_options = $options;
    }

    public function postHydrate(Doctrine_Event $event)
    {
        $obj = $event-&gt;data;
        foreach ($this-&gt;_options['columns'] as $column) {
            $obj-&gt;$column = !($obj-&gt;$column);
        }
        $event-&gt;set('data', $obj);
    }

    public function preSave(Doctrine_Event $event)
    {
        foreach ($this-&gt;_options['columns'] as $column) {
            $value = !($event-&gt;getInvoker()-&gt;get($column));
            $event-&gt;getInvoker()-&gt;set($column, $value);
        }
    }
}
</pre>
</div>
<p>postHydrateでデータをデータベースから読み出してきてハイドレートした後に、preSaveで保存する前にそれぞれデータを反転しています。</p>
<p>カラムのタイプはあらかじめbooleanにしておく必要があります。schema.ymlからデータベース生成した場合は問題ないかと思います。そうでないなら、モデルのsetUpメソッドにでも</p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>        $this-&gt;hasColumn('show_flag', 'boolean', null, array(
             'type' =&gt; 'boolean',
             'notnull' =&gt; true,
             'default' =&gt; 0,
             ));
</pre>
</div>
<p>など。</p>
<p>これを使用できるようにするために、同じくモデルのsetUpメソッドに</p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>$this-&gt;actAs('InvertBoolean', array('columns'=&gt;array('show_flag')));</pre>
</div>
<p>とすればOKです。actAsのcolumnsオプションに複数カラム名設定すれば複数カラムを一括で指定できます。</p>
<p>これで、sfWidgetFormInputCheckboxを使ったチェックボックスにチェックを入れたときにデータベースに0が保存され、チェックを外すと1が保存されるカラムができあがりました。</p>
<p>問題点として、カラム名と反対の動きをすることになるので、うっかりする可能性が高まります。</p>
<p>なので、動作は確認しましたが、結局この案は使ってません。次のエントリーで紹介するカスタムウィジェットの方法を使っています。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.loadlimits.info/2010/06/sfwidgetforminputcheckbox%e3%81%ae%e6%ad%a3%e8%b2%a0%e3%82%92%e5%8f%8d%e8%bb%a2%e3%81%95%e3%81%9b%e3%82%8b-%e3%81%9d%e3%81%ae%ef%bc%91/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WSH用の便利関数</title>
		<link>http://blog.loadlimits.info/2010/06/wsh%e7%94%a8%e3%81%ae%e4%be%bf%e5%88%a9%e9%96%a2%e6%95%b0/</link>
		<comments>http://blog.loadlimits.info/2010/06/wsh%e7%94%a8%e3%81%ae%e4%be%bf%e5%88%a9%e9%96%a2%e6%95%b0/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 07:51:34 +0000</pubDate>
		<dc:creator>hotpi</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[VBScript]]></category>

		<guid isPermaLink="false">http://blog.loadlimits.info/2010/06/wsh%e7%94%a8%e3%81%ae%e4%be%bf%e5%88%a9%e9%96%a2%e6%95%b0/</guid>
		<description><![CDATA[整理のために古いディスクを漁っていたら、汎用的に使えそうなWSH(VBScript)の関数群が出てきたのでメモ。
機能はファイルコピー、テンポラリディレクトリの取得、ファイルリストの取得、テキストファイルの中身を配列に読み込む、ファイルとディレクトリの存在確認、正規表現のマッチ。当時のことはよく覚えていないけど、とりあえずPHPライクに便利関数が欲しかったんだと思います。


Function FileCopy(src,dst,overwrite)

	Dim objFS, objWshShell
	Set objWshShell = WScript.CreateObject("WScript.Shell")
	Set objFS = WScript.CreateObject("Scripting.FileSystemObject")

	objFS.CopyFile src,dst,overwrite

End Function

Function GetTemporaryDirectory

	Dim objWshShell
	Set objWshShell = WScript.CreateObject("WScript.Shell")

	GetTemporaryDirectory = objWshShell.ExpandEnvironmentStrings("%TEMP%")

End Function

Function GetFileList(dir, reg)

	Dim objFS, objFolder
	Dim fileCol,tmpFile,fileNames
	Dim i
	Set objFS = WScript.CreateObject("Scripting.FileSystemObject")
	Set objFolder = objFS.GetFolder(dir)
	Set fileCol = objFolder.Files

	fileNames = Array(1)
	i = 0
	For Each tmpFile in fileCol
		If RegMatch(reg, tmpFile.name, False) Then
			fileNames(i) = tmpFile.name
			i = i + 1
			Redim Preserve fileNames(i)
		End [...]]]></description>
			<content:encoded><![CDATA[<p>整理のために古いディスクを漁っていたら、汎用的に使えそうなWSH(VBScript)の関数群が出てきたのでメモ。</p>
<p>機能はファイルコピー、テンポラリディレクトリの取得、ファイルリストの取得、テキストファイルの中身を配列に読み込む、ファイルとディレクトリの存在確認、正規表現のマッチ。当時のことはよく覚えていないけど、とりあえずPHPライクに便利関数が欲しかったんだと思います。</p>
<p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>Function FileCopy(src,dst,overwrite)

	Dim objFS, objWshShell
	Set objWshShell = WScript.CreateObject("WScript.Shell")
	Set objFS = WScript.CreateObject("Scripting.FileSystemObject")

	objFS.CopyFile src,dst,overwrite

End Function

Function GetTemporaryDirectory

	Dim objWshShell
	Set objWshShell = WScript.CreateObject("WScript.Shell")

	GetTemporaryDirectory = objWshShell.ExpandEnvironmentStrings("%TEMP%")

End Function

Function GetFileList(dir, reg)

	Dim objFS, objFolder
	Dim fileCol,tmpFile,fileNames
	Dim i
	Set objFS = WScript.CreateObject("Scripting.FileSystemObject")
	Set objFolder = objFS.GetFolder(dir)
	Set fileCol = objFolder.Files

	fileNames = Array(1)
	i = 0
	For Each tmpFile in fileCol
		If RegMatch(reg, tmpFile.name, False) Then
			fileNames(i) = tmpFile.name
			i = i + 1
			Redim Preserve fileNames(i)
		End If
	Next

	GetFileList = fileNames

End Function

Function FileReadArray(filename)

	Const ForReading = 1, ForWriting = 2

	Dim objFS, objFileStream
	Dim lines
	Dim i
	Set objFS = WScript.CreateObject("Scripting.FileSystemObject")
	Set objFileStream = objFS.OpenTextFile(filename, ForReading)

	lines = Array(1)
	i = 0
	Do While objFileStream.AtEndOfStream &lt;&gt; True
		lines(i) = objFileStream.ReadLine
		i = i + 1
		Redim Preserve lines(i)
	Loop

	FileReadArray = lines

End Function

Function FileExists(filepath)

	Dim objFS
	Set objFS = WScript.CreateObject("Scripting.FileSystemObject")

	FileExists = objFS.FileExists(filepath)

End Function

Function DirectoryExists(dir)

	Dim objFS
	Set objFS = WScript.CreateObject("Scripting.FileSystemObject")

	DirectoryExists = objFS.FolderExists(dir)

End Function

Function SetRegistry(strName, anyValue ,strType)

	Dim objWshShell
	Set objWshShell = WScript.CreateObject("WScript.Shell")

	objWshShell.RegWrite strName, anyValue, strType

End Function

Function RegMatch(pattern, string, ignoreCase)

	Dim regEx, Matches
	Set regEx = New RegExp
	regEx.Pattern = pattern
	regEx.IgnoreCase = ignoreCase
	regEx.Global = True
	Set Matches = regEx.Execute(string)

	If Matches.Count = 0 Then
		RegMatch = False
	Else
		RegMatch = True
	End If

End Function
</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.loadlimits.info/2010/06/wsh%e7%94%a8%e3%81%ae%e4%be%bf%e5%88%a9%e9%96%a2%e6%95%b0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>admin generatorの編集後のリダイレクト先変更</title>
		<link>http://blog.loadlimits.info/2010/05/admin-generator%e3%81%ae%e7%b7%a8%e9%9b%86%e5%be%8c%e3%81%ae%e3%83%aa%e3%83%80%e3%82%a4%e3%83%ac%e3%82%af%e3%83%88%e5%85%88%e5%a4%89%e6%9b%b4/</link>
		<comments>http://blog.loadlimits.info/2010/05/admin-generator%e3%81%ae%e7%b7%a8%e9%9b%86%e5%be%8c%e3%81%ae%e3%83%aa%e3%83%80%e3%82%a4%e3%83%ac%e3%82%af%e3%83%88%e5%85%88%e5%a4%89%e6%9b%b4/#comments</comments>
		<pubDate>Wed, 19 May 2010 04:31:06 +0000</pubDate>
		<dc:creator>hotpi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[解決]]></category>
		<category><![CDATA[admin generator]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://blog.loadlimits.info/2010/05/admin-generator%e3%81%ae%e7%b7%a8%e9%9b%86%e5%be%8c%e3%81%ae%e3%83%aa%e3%83%80%e3%82%a4%e3%83%ac%e3%82%af%e3%83%88%e5%85%88%e5%a4%89%e6%9b%b4/</guid>
		<description><![CDATA[admin generatorのeditアクションで、編集後に再度編集画面ではなく、リストに飛ばしたい要件があったのでメモ。例によってSymfony 1.4+Doctrine+admin generator。

class hogeActions extends autoHogeActions
{
    public function executeUpdate(sfWebRequest $request)
    {
        $this-&#62;forward404Unless($request-&#62;isMethod('put'));

        $this-&#62;hoge = $this-&#62;getRoute()-&#62;getObject();
        $this-&#62;form = $this-&#62;configuration-&#62;getForm($this-&#62;hoge);

        if ($this-&#62;form-&#62;bindAndSave($request-&#62;getParameter($this-&#62;form-&#62;getName()), [...]]]></description>
			<content:encoded><![CDATA[<p>admin generatorのeditアクションで、編集後に再度編集画面ではなく、リストに飛ばしたい要件があったのでメモ。例によってSymfony 1.4+Doctrine+admin generator。</p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>class hogeActions extends autoHogeActions
{
    public function executeUpdate(sfWebRequest $request)
    {
        $this-&gt;forward404Unless($request-&gt;isMethod('put'));

        $this-&gt;hoge = $this-&gt;getRoute()-&gt;getObject();
        $this-&gt;form = $this-&gt;configuration-&gt;getForm($this-&gt;hoge);

        if ($this-&gt;form-&gt;bindAndSave($request-&gt;getParameter($this-&gt;form-&gt;getName()), $request-&gt;getFiles($this-&gt;form-&gt;getName()))) {
            $this-&gt;redirect('hoge');
        }

        $this-&gt;setTemplate('edit');
    }
}
</pre>
</div>
<p>executeUpdateをオーバーライドすればOKのようです。ここではisMethodがputなことに注意。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.loadlimits.info/2010/05/admin-generator%e3%81%ae%e7%b7%a8%e9%9b%86%e5%be%8c%e3%81%ae%e3%83%aa%e3%83%80%e3%82%a4%e3%83%ac%e3%82%af%e3%83%88%e5%85%88%e5%a4%89%e6%9b%b4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfonyでのsave時に独自の処理を挟む</title>
		<link>http://blog.loadlimits.info/2010/05/symfony%e3%81%a7%e3%81%aesave%e6%99%82%e3%81%ab%e7%8b%ac%e8%87%aa%e3%81%ae%e5%87%a6%e7%90%86%e3%82%92%e6%8c%9f%e3%82%80/</link>
		<comments>http://blog.loadlimits.info/2010/05/symfony%e3%81%a7%e3%81%aesave%e6%99%82%e3%81%ab%e7%8b%ac%e8%87%aa%e3%81%ae%e5%87%a6%e7%90%86%e3%82%92%e6%8c%9f%e3%82%80/#comments</comments>
		<pubDate>Wed, 19 May 2010 02:12:16 +0000</pubDate>
		<dc:creator>hotpi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[解決]]></category>
		<category><![CDATA[admin generator]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://blog.loadlimits.info/2010/05/symfony%e3%81%a7%e3%81%aesave%e6%99%82%e3%81%ab%e7%8b%ac%e8%87%aa%e3%81%ae%e5%87%a6%e7%90%86%e3%82%92%e6%8c%9f%e3%82%80/</guid>
		<description><![CDATA[Symfony 1.4+Doctrineで、admin generatorな環境です。editなど、自動生成なので、どこをオーバーライドすれば目的の動作になるのかわかりにくいことがありますね。
例えば、あるモデルのステータスを変更すると同時に、他のモデルに対しても操作したい場合があるとします。
まぁ、mergeFormとかembedFormとか使ってもいいのですが、今回は他テーブルのプライマリキーをフォームから選択させたかったので、汎用性のあるdoSaveでの処理を追加してみました。
symfony Forms in Action &#124; 第11章 &#8211; Doctrine との統合 &#124; symfony &#124; Web PHP Framework

class BackendHogeForm extends HogeForm
{
    public function configure()
    {
        parent::configure();

        // 使用するフィールドを指定
        $this-&#62;useFields(array('status'));

 [...]]]></description>
			<content:encoded><![CDATA[<p>Symfony 1.4+Doctrineで、admin generatorな環境です。editなど、自動生成なので、どこをオーバーライドすれば目的の動作になるのかわかりにくいことがありますね。</p>
<p>例えば、あるモデルのステータスを変更すると同時に、他のモデルに対しても操作したい場合があるとします。</p>
<p>まぁ、mergeFormとかembedFormとか使ってもいいのですが、今回は他テーブルのプライマリキーをフォームから選択させたかったので、汎用性のあるdoSaveでの処理を追加してみました。</p>
<p><a href="http://www.symfony-project.org/forms/1_2/ja/11-Doctrine-Integration" target="_blank">symfony Forms in Action | 第11章 &#8211; Doctrine との統合 | symfony | Web PHP Framework</a></p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>class BackendHogeForm extends HogeForm
{
    public function configure()
    {
        parent::configure();

        // 使用するフィールドを指定
        $this-&gt;useFields(array('status'));

        // 別モデルのIDリストを選択するフォームを作成する
        $choices = array(100 =&gt; '100:value1', 101 =&gt; '101:value2');
        $this-&gt;widgetSchema['other_model_id'] = new sfWidgetFormSelect(array('choices' =&gt; $choices));
        $this-&gt;validatorSchema['other_model_id'] = new sfValidatorChoice(array('choices' =&gt; array_keys($choices)));
    }

    protected function doSave($con = null)
    {
        if ($this-&gt;getValue('status') == 'DONE') {
            Doctrine::getTable('OtherModel')-&gt;find($this-&gt;getValue('other_model_id'))
                -&gt;setIsSelected(TRUE)
                -&gt;save();
        }
        return parent::doSave($con);
    }
}
</pre>
</div>
<p>基本的にはdoSaveをオーバーライドするだけです。ちなみにuseFieldsメソッドを使うと必要なフィールド以外を全部unsetしてくれるので便利です。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.loadlimits.info/2010/05/symfony%e3%81%a7%e3%81%aesave%e6%99%82%e3%81%ab%e7%8b%ac%e8%87%aa%e3%81%ae%e5%87%a6%e7%90%86%e3%82%92%e6%8c%9f%e3%82%80/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SymfonyのAdmin generatorでリストにフィルタを表示させない方法</title>
		<link>http://blog.loadlimits.info/2010/05/symfony%e3%81%aeadmin-generator%e3%81%a7%e3%83%aa%e3%82%b9%e3%83%88%e3%81%ab%e3%83%95%e3%82%a3%e3%83%ab%e3%82%bf%e3%82%92%e8%a1%a8%e7%a4%ba%e3%81%95%e3%81%9b%e3%81%aa%e3%81%84%e6%96%b9%e6%b3%95/</link>
		<comments>http://blog.loadlimits.info/2010/05/symfony%e3%81%aeadmin-generator%e3%81%a7%e3%83%aa%e3%82%b9%e3%83%88%e3%81%ab%e3%83%95%e3%82%a3%e3%83%ab%e3%82%bf%e3%82%92%e8%a1%a8%e7%a4%ba%e3%81%95%e3%81%9b%e3%81%aa%e3%81%84%e6%96%b9%e6%b3%95/#comments</comments>
		<pubDate>Mon, 10 May 2010 08:03:17 +0000</pubDate>
		<dc:creator>hotpi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[解決]]></category>
		<category><![CDATA[admin generator]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://blog.loadlimits.info/2010/05/symfony%e3%81%aeadmin-generator%e3%81%a7%e3%83%aa%e3%82%b9%e3%83%88%e3%81%ab%e3%83%95%e3%82%a3%e3%83%ab%e3%82%bf%e3%82%92%e8%a1%a8%e7%a4%ba%e3%81%95%e3%81%9b%e3%81%aa%e3%81%84%e6%96%b9%e6%b3%95/</guid>
		<description><![CDATA[Admin generatorを使っていて、リスト表示をするときにフィルタが不要な場合があります。例えば行が少ないとか、すでに決まったフィルタが別にある場合など。フィルタのフォーム自体を消したい場合は以下の方法で。
apps/backend/modules/MODULE_NAME/templates/    に     _filters.php     を空で作成すればいいだけです。
admin generatorでの開発とはキャッシュを読む作業と見つけたり…
追記
コメントで教えていただいた方法で、もっと簡単に実現できました。filterのclassをfalseにするだけでOKです。


generator:
  class: sfDoctrineGenerator
  param:
    config:
      filter:
        class: false


]]></description>
			<content:encoded><![CDATA[<p>Admin generatorを使っていて、リスト表示をするときにフィルタが不要な場合があります。例えば行が少ないとか、すでに決まったフィルタが別にある場合など。フィルタのフォーム自体を消したい場合は以下の方法で。</p>
<p>apps/backend/modules/MODULE_NAME/templates/    <br />に     <br />_filters.php     <br />を空で作成すればいいだけです。</p>
<p>admin generatorでの開発とはキャッシュを読む作業と見つけたり…</p>
<p>追記</p>
<p>コメントで教えていただいた方法で、もっと簡単に実現できました。filterのclassをfalseにするだけでOKです。</p>
</p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>generator:
  class: sfDoctrineGenerator
  param:
    config:
      filter:
        class: false
</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.loadlimits.info/2010/05/symfony%e3%81%aeadmin-generator%e3%81%a7%e3%83%aa%e3%82%b9%e3%83%88%e3%81%ab%e3%83%95%e3%82%a3%e3%83%ab%e3%82%bf%e3%82%92%e8%a1%a8%e7%a4%ba%e3%81%95%e3%81%9b%e3%81%aa%e3%81%84%e6%96%b9%e6%b3%95/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Symfonyでメール送信のデバッグをする</title>
		<link>http://blog.loadlimits.info/2010/03/symfony%e3%81%a7%e3%83%a1%e3%83%bc%e3%83%ab%e9%80%81%e4%bf%a1%e3%81%ae%e3%83%87%e3%83%90%e3%83%83%e3%82%b0%e3%82%92%e3%81%99%e3%82%8b/</link>
		<comments>http://blog.loadlimits.info/2010/03/symfony%e3%81%a7%e3%83%a1%e3%83%bc%e3%83%ab%e9%80%81%e4%bf%a1%e3%81%ae%e3%83%87%e3%83%90%e3%83%83%e3%82%b0%e3%82%92%e3%81%99%e3%82%8b/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 02:12:14 +0000</pubDate>
		<dc:creator>hotpi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[解決]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://blog.loadlimits.info/2010/03/symfony%e3%81%a7%e3%83%a1%e3%83%bc%e3%83%ab%e9%80%81%e4%bf%a1%e3%81%ae%e3%83%87%e3%83%90%e3%83%83%e3%82%b0%e3%82%92%e3%81%99%e3%82%8b/</guid>
		<description><![CDATA[Symfony1.4で、メールを送信するコードで、開発中にテンプレートの動作確認をしたい場合があります。Swift Mailerを使っているなら、すべての送信メールのあて先を上書きして特定のメールアドレスにすることができるので、やり方メモ。
The More with symfony book &#124; メール &#124; symfony &#124; Web PHP Framework
設定の仕方は簡単で、アプリケーションのconfig\factories.ymlにdelivery_strategy: single_addressを指定すればOK。同時にdelivery_addressに、あて先メールアドレスを記述します。
dev:   &#160; mailer:    &#160;&#160;&#160; param:    &#160;&#160;&#160;&#160;&#160; delivery_strategy: single_address    &#160;&#160;&#160;&#160;&#160; delivery_address: dev@localhost
これで開発環境のローカルユーザdevにメールが送られます。
元々のヘッダ指定 to、cc、bcc のどれに送られたメールなのかを確認できるよう、それぞれ X-Swift-To、X-Swift-Cc、X-Swift-Bcc というヘッダが追加されます。

あとはローカルのメールをMewとかで読めばOKです。
もちろんdelivery_addressを外部のメールアドレスに指定してもいいですよ。
PayPalの開発環境みたいにメールのSandBoxとか統合されないかなぁ。
]]></description>
			<content:encoded><![CDATA[<p>Symfony1.4で、メールを送信するコードで、開発中にテンプレートの動作確認をしたい場合があります。Swift Mailerを使っているなら、すべての送信メールのあて先を上書きして特定のメールアドレスにすることができるので、やり方メモ。</p>
<p><a href="http://www.symfony-project.org/more-with-symfony/1_4/ja/04-Emails" target="_blank">The More with symfony book | メール | symfony | Web PHP Framework</a></p>
<p>設定の仕方は簡単で、アプリケーションのconfig\factories.ymlにdelivery_strategy: single_addressを指定すればOK。同時にdelivery_addressに、あて先メールアドレスを記述します。</p>
<p>dev:   <br />&#160; mailer:    <br />&#160;&#160;&#160; param:    <br />&#160;&#160;&#160;&#160;&#160; delivery_strategy: single_address    <br />&#160;&#160;&#160;&#160;&#160; delivery_address: dev@localhost</p>
<p>これで開発環境のローカルユーザdevにメールが送られます。</p>
<blockquote><p>元々のヘッダ指定 <code>to</code>、<code>cc</code>、<code>bcc</code> のどれに送られたメールなのかを確認できるよう、それぞれ <code>X-Swift-To</code>、<code>X-Swift-Cc</code>、<code>X-Swift-Bcc</code> というヘッダが追加されます。</p>
</blockquote>
<p>あとはローカルのメールをMewとかで読めばOKです。</p>
<p>もちろんdelivery_addressを外部のメールアドレスに指定してもいいですよ。</p>
<p>PayPalの開発環境みたいにメールのSandBoxとか統合されないかなぁ。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.loadlimits.info/2010/03/symfony%e3%81%a7%e3%83%a1%e3%83%bc%e3%83%ab%e9%80%81%e4%bf%a1%e3%81%ae%e3%83%87%e3%83%90%e3%83%83%e3%82%b0%e3%82%92%e3%81%99%e3%82%8b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>複数の入力欄にまたがるValidationのエラーを特定の入力欄に表示させたい場合</title>
		<link>http://blog.loadlimits.info/2010/03/%e8%a4%87%e6%95%b0%e3%81%ae%e5%85%a5%e5%8a%9b%e6%ac%84%e3%81%ab%e3%81%be%e3%81%9f%e3%81%8c%e3%82%8bvalidation%e3%81%ae%e3%82%a8%e3%83%a9%e3%83%bc%e3%82%92%e7%89%b9%e5%ae%9a%e3%81%ae%e5%85%a5%e5%8a%9b/</link>
		<comments>http://blog.loadlimits.info/2010/03/%e8%a4%87%e6%95%b0%e3%81%ae%e5%85%a5%e5%8a%9b%e6%ac%84%e3%81%ab%e3%81%be%e3%81%9f%e3%81%8c%e3%82%8bvalidation%e3%81%ae%e3%82%a8%e3%83%a9%e3%83%bc%e3%82%92%e7%89%b9%e5%ae%9a%e3%81%ae%e5%85%a5%e5%8a%9b/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 17:10:02 +0000</pubDate>
		<dc:creator>hotpi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[解決]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://blog.loadlimits.info/2010/03/%e8%a4%87%e6%95%b0%e3%81%ae%e5%85%a5%e5%8a%9b%e6%ac%84%e3%81%ab%e3%81%be%e3%81%9f%e3%81%8c%e3%82%8bvalidation%e3%81%ae%e3%82%a8%e3%83%a9%e3%83%bc%e3%82%92%e7%89%b9%e5%ae%9a%e3%81%ae%e5%85%a5%e5%8a%9b/</guid>
		<description><![CDATA[sfFormでSymfony 1.4のお話。
PostValidatorのエラーメッセージをどこに出せばいいんだ？という状況で使用できます。

class SomethingInputForm extends BaseForm
{
    public function configure()
    {
        // ...
        $this-&#62;validatorSchema-&#62;setPostValidator(
            new sfValidatorCallback(array('callback' =&#62; array($this, 'myCallbackFunc')))
        [...]]]></description>
			<content:encoded><![CDATA[<p>sfFormでSymfony 1.4のお話。</p>
<p>PostValidatorのエラーメッセージをどこに出せばいいんだ？という状況で使用できます。</p>
<div style="padding-bottom: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;float: none;padding-top: 0px" class="wlWriterEditableSmartContent">
<pre>class SomethingInputForm extends BaseForm
{
    public function configure()
    {
        // ...
        $this-&gt;validatorSchema-&gt;setPostValidator(
            new sfValidatorCallback(array('callback' =&gt; array($this, 'myCallbackFunc')))
        );
    }

    public function myCallbackFunc($validator, $values) {
        // 何かバリデーション
        if (!($values['input1'] == $values['input2'] == $values['input3'])) {
            $error = new sfValidatorError($validator, 'error message ...');
            throw new sfValidatorErrorSchema($validator, array('input1' =&gt; $error));
        }

        return $values;
    }
}
</pre>
</div>
<p>こんな感じで、input1のエラーとして出力できるので、テンプレートのエラー表示が楽になります。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.loadlimits.info/2010/03/%e8%a4%87%e6%95%b0%e3%81%ae%e5%85%a5%e5%8a%9b%e6%ac%84%e3%81%ab%e3%81%be%e3%81%9f%e3%81%8c%e3%82%8bvalidation%e3%81%ae%e3%82%a8%e3%83%a9%e3%83%bc%e3%82%92%e7%89%b9%e5%ae%9a%e3%81%ae%e5%85%a5%e5%8a%9b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
