<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>azul</title>
    <link>http://www.azul.systems-noel.jp/</link>
    <description>へっぽこプログラマの覚書</description>
    <!-- optional tags -->
    <language>ja</language>           <!-- valid langugae goes here -->
    <generator>Nucleus CMS v3.24</generator>
    <copyright>ｩ</copyright>             <!-- Copyright notice -->
    <category>Weblog</category>
    <docs>http://backend.userland.com/rss</docs>
    <image>
      <url>http://www.azul.systems-noel.jp//nucleus/nucleus2.gif</url>
      <title>azul</title>
      <link>http://www.azul.systems-noel.jp/</link>
    </image>
    <item>
 <title><![CDATA[PHP5.3 de デザパタ(Abstract Factory)]]></title>
 <link>http://www.azul.systems-noel.jp/index.php?itemid=83</link>
<description><![CDATA[<p>
    はい、お勉強かねがね今さらデザインパターンです。<br />
    PHP5.3系ならでは、な実装ができないものかなぁと考えてみます。<br />
    まずはAbstract Factoryからです
<p><p>
    まずは抽象クラスから。<br />
    Factoryクラスです。<br />
    abstractfactory/factory/Factory.php
</p>
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
namespace abstractfactory\factory;
&nbsp;
<span class="coMULTI">/**
 * Abstract Factory
 * @author $Author$
 *
 */</span>
abstract <span class="kw2">class</span> Factory <span class="br0">&#123;</span>
    <span class="coMULTI">/**
     * Factory type 1
     * @var integer
     */</span>
    const TYPE_1 = <span class="nu0">1</span>;
&nbsp;
    <span class="coMULTI">/**
     * Factory type 2
     * @var integer
     */</span>
    const TYPE_2 = <span class="nu0">2</span>;
&nbsp;
    <span class="coMULTI">/**
     * Return factory
     * @return Factory
     */</span>
    <span class="kw2">public</span> <a target="_blank"  href="http://www.php.net/static"><span class="kw3">static</span></a> <span class="kw2">function</span> getFactory<span class="br0">&#40;</span><span class="re0">$type</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$type</span> == self::<span class="me2">TYPE_1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            <span class="kw1">return</span> <span class="kw2">new</span> ConcreteFactory1<span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$type</span> == self::<span class="me2">TYPE_2</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            <span class="kw1">return</span> <span class="kw2">new</span> ConcreteFactory2<span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="br0">&#125;</span>
        throw <span class="kw2">new</span> \Exception<span class="br0">&#40;</span><span class="st0">'Argument of '</span> . <span class="kw2">__CLASS__</span> . <span class="st0">'::'</span> . <span class="kw2">__METHOD__</span> . <span class="st0">'() must be constant of '</span> . <span class="kw2">__CLASS__</span> <span class="br0">&#41;</span>;
    <span class="br0">&#125;</span>
&nbsp;
    <span class="coMULTI">/**
     * Create Product1
     * @return Product1
     */</span>
    abstract <span class="kw2">public</span> <span class="kw2">function</span> createProduct1<span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp;
    <span class="coMULTI">/**
     * Product2
     * @return Product2
     */</span>
    abstract <span class="kw2">public</span> <span class="kw2">function</span> createProduct2<span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span></pre>

<p>
    次にProduct11クラス。<br />
    Productは2つ扱うことにしてみます。<br />
    abstractfactory/product/Product1.php
</p>
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
namespace abstractfactory\product;
&nbsp;
<span class="coMULTI">/**
 * Abstract Product1
 * @author $Author$
 */</span>
abstract <span class="kw2">class</span> Product1 <span class="br0">&#123;</span>
    <span class="coMULTI">/**
     * Output class name of this Product
     */</span>
    abstract <span class="kw2">public</span> <span class="kw2">function</span> showName<span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span></pre>

<p>
    Product2クラス。<br />
    abstractfactory/product/Product2.php
</p>
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
namespace abstractfactory\product;
&nbsp;
<span class="coMULTI">/**
 * Abstract Product2
 * @author $Author$
 */</span>
abstract <span class="kw2">class</span> Product2 <span class="br0">&#123;</span>
    <span class="coMULTI">/**
     * Output class name of this Product
     */</span>
    abstract <span class="kw2">public</span> <span class="kw2">function</span> showName<span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span></pre>

<p>
    そしてFactoryを使用するClientクラス。<br />
    abstractfactory/Client.php
</p>
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
namespace abstractfactory;
&nbsp;
<span class="coMULTI">/**
 * Factory Client
 * @author $Author$
 */</span>
<span class="kw2">class</span> Client <span class="br0">&#123;</span>
    <span class="coMULTI">/**
     * Handle Products of specified type Factory
     * @param integer $type
     */</span>
    <span class="kw2">public</span> <span class="kw2">function</span> handleProduct<span class="br0">&#40;</span><span class="re0">$type</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        try <span class="br0">&#123;</span>
            <span class="re0">$factory</span> = factory\Factory::<span class="me2">getFactory</span><span class="br0">&#40;</span><span class="re0">$type</span><span class="br0">&#41;</span>;
            <span class="re0">$factory</span>-&gt;<span class="me1">createProduct1</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">showName</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
            <span class="re0">$factory</span>-&gt;<span class="me1">createProduct2</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">showName</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="br0">&#125;</span> catch <span class="br0">&#40;</span>\Exception <span class="re0">$e</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            throw <span class="re0">$e</span>;
        <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;</pre>

<p>
    じゃあ実装クラスです。
    Factoryクラスの実装その1である、ConcreteFactory1クラス。<br />
    abstractfactory/factory/ConcreteFactory1.php
</p>
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
namespace abstractfactory\factory;
&nbsp;
<span class="coMULTI">/**
 * ConcreteFactory1
 * @author $Author$
 */</span>
<span class="kw2">class</span> ConcreteFactory1 <span class="kw2">extends</span> Factory <span class="br0">&#123;</span>
&nbsp;
    <span class="coMULTI">/**
     * Create ConcreteProduct1_1
     * @return ConcreteProduct1_1
     */</span>
    <span class="kw2">public</span> <span class="kw2">function</span> createProduct1<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw1">return</span> <span class="kw2">new</span> \abstractfactory\product\ConcreteProduct1_1<span class="br0">&#40;</span><span class="br0">&#41;</span>;
    <span class="br0">&#125;</span>
&nbsp;
    <span class="coMULTI">/**
     * Create ConcreteProduct1_2
     * @return ConcreteProduct1_2
     */</span>
    <span class="kw2">public</span> <span class="kw2">function</span> createProduct2<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw1">return</span> <span class="kw2">new</span> \abstractfactory\product\ConcreteProduct1_2<span class="br0">&#40;</span><span class="br0">&#41;</span>;
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>

<p>
    Factoryクラスの実装その2である、ConcreteFactory2クラス。<br />
    abstractfactory/factory/ConcreteFactory2.php
</p>
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
namespace abstractfactory\factory;
&nbsp;
<span class="coMULTI">/**
 * ConcreteFactory2
 * @author $Author$
 */</span>
<span class="kw2">class</span> ConcreteFactory2 <span class="kw2">extends</span> Factory <span class="br0">&#123;</span>
&nbsp;
    <span class="coMULTI">/**
     * Create ConcreteProduct2_1
     * @return ConcreteProduct2_1
     */</span>
    <span class="kw2">public</span> <span class="kw2">function</span> createProduct1<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw1">return</span> <span class="kw2">new</span> \abstractfactory\product\ConcreteProduct2_1<span class="br0">&#40;</span><span class="br0">&#41;</span>;
    <span class="br0">&#125;</span>
&nbsp;
    <span class="coMULTI">/**
     * Create ConcreteProduct2_2
     * @return ConcreteProduct2_2
     */</span>
    <span class="kw2">public</span> <span class="kw2">function</span> createProduct2<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw1">return</span> <span class="kw2">new</span> \abstractfactory\product\ConcreteProduct2_2<span class="br0">&#40;</span><span class="br0">&#41;</span>;
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>

<p>
    ConcreteFactory1クラスが生成するProduct1の実装クラスであるConcreteProduct1_1クラス。<br />
    abstractfactory/product/ConcreteProduct1_1.php
</p>
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
namespace abstractfactory\product;
&nbsp;
<span class="coMULTI">/**
 * Concrete Product1_1
 * @author $Author$
 */</span>
<span class="kw2">class</span> ConcreteProduct1_1 <span class="kw2">extends</span> Product1 <span class="br0">&#123;</span>
    <span class="coMULTI">/**
     * Return class name of this Product
     * @return string
     */</span>
    <span class="kw2">public</span> <span class="kw2">function</span> showName<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="kw2">__CLASS__</span> . PHP_EOL;
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>

<p>
    ConcreteFactory1クラスが生成するProduct2の実装クラスであるConcreteProduct1_2クラス。<br />
    abstractfactory/product/ConcreteProduct1_2.php
</p>
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
namespace abstractfactory\product;
&nbsp;
<span class="coMULTI">/**
 * Concrete Product1_2
 * @author $Author$
 */</span>
<span class="kw2">class</span> ConcreteProduct1_2 <span class="kw2">extends</span> Product2 <span class="br0">&#123;</span>
    <span class="coMULTI">/**
     * Return class name of this Product
     * @return string
     */</span>
    <span class="kw2">public</span> <span class="kw2">function</span> showName<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="kw2">__CLASS__</span> . PHP_EOL;
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>

<p>
    ConcreteFactory2クラスが生成するProduct1の実装クラスであるConcreteProduct2_1クラス。<br />
    abstractfactory/product/ConcreteProduct2_1.php
</p>
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
namespace abstractfactory\product;
&nbsp;
<span class="coMULTI">/**
 * Concrete Product2_1
 * @author $Author$
 */</span>
<span class="kw2">class</span> ConcreteProduct2_1 <span class="kw2">extends</span> Product1 <span class="br0">&#123;</span>
    <span class="coMULTI">/**
     * Return class name of this Product
     * @return string
     */</span>
    <span class="kw2">public</span> <span class="kw2">function</span> showName<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="kw2">__CLASS__</span> . PHP_EOL;
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>

<p>
    ConcreteFactory2クラスが生成するProduct2の実装クラスであるConcreteProduct2_2クラス。<br />
    abstractfactory/product/ConcreteProduct2_2.php
</p>
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
namespace abstractfactory\product;
&nbsp;
<span class="coMULTI">/**
 * Concrete Product2_2
 * @author $Author$
 */</span>
<span class="kw2">class</span> ConcreteProduct2_2 <span class="kw2">extends</span> Product2 <span class="br0">&#123;</span>
    <span class="coMULTI">/**
     * Return class name of this Product
     * @return string
     */</span>
    <span class="kw2">public</span> <span class="kw2">function</span> showName<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="kw2">__CLASS__</span> . PHP_EOL;
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>

<p>
    以上でクラスは出そろったので、実行ファイル<br />
    abstractfactory/abstractfactory.php
</p>
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
namespace abstractfactory;
&nbsp;
<a target="_blank"  href="http://www.php.net/define"><span class="kw3">define</span></a><span class="br0">&#40;</span><span class="st0">'DIR'</span>, <a target="_blank"  href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw2">__FILE__</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;
&nbsp;
<span class="kw1">require_once</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dir"><span class="kw3">DIR</span></a> . DIRECTORY_SEPARATOR . <span class="st0">'Client.php'</span><span class="br0">&#41;</span>;
&nbsp;
<span class="kw1">require_once</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dir"><span class="kw3">DIR</span></a> . DIRECTORY_SEPARATOR . <span class="st0">'factory'</span> . DIRECTORY_SEPARATOR . <span class="st0">'Factory.php'</span><span class="br0">&#41;</span>;
<span class="kw1">require_once</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dir"><span class="kw3">DIR</span></a> . DIRECTORY_SEPARATOR . <span class="st0">'factory'</span> . DIRECTORY_SEPARATOR . <span class="st0">'ConcreteFactory1.php'</span><span class="br0">&#41;</span>;
<span class="kw1">require_once</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dir"><span class="kw3">DIR</span></a> . DIRECTORY_SEPARATOR . <span class="st0">'factory'</span> . DIRECTORY_SEPARATOR . <span class="st0">'ConcreteFactory2.php'</span><span class="br0">&#41;</span>;
&nbsp;
<span class="kw1">require_once</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dir"><span class="kw3">DIR</span></a> . DIRECTORY_SEPARATOR . <span class="st0">'product'</span> . DIRECTORY_SEPARATOR . <span class="st0">'Product1.php'</span><span class="br0">&#41;</span>;
<span class="kw1">require_once</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dir"><span class="kw3">DIR</span></a> . DIRECTORY_SEPARATOR . <span class="st0">'product'</span> . DIRECTORY_SEPARATOR . <span class="st0">'Product2.php'</span><span class="br0">&#41;</span>;
<span class="kw1">require_once</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dir"><span class="kw3">DIR</span></a> . DIRECTORY_SEPARATOR . <span class="st0">'product'</span> . DIRECTORY_SEPARATOR . <span class="st0">'ConcreteProduct1_1.php'</span><span class="br0">&#41;</span>;
<span class="kw1">require_once</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dir"><span class="kw3">DIR</span></a> . DIRECTORY_SEPARATOR . <span class="st0">'product'</span> . DIRECTORY_SEPARATOR . <span class="st0">'ConcreteProduct1_2.php'</span><span class="br0">&#41;</span>;
<span class="kw1">require_once</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dir"><span class="kw3">DIR</span></a> . DIRECTORY_SEPARATOR . <span class="st0">'product'</span> . DIRECTORY_SEPARATOR . <span class="st0">'ConcreteProduct2_1.php'</span><span class="br0">&#41;</span>;
<span class="kw1">require_once</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dir"><span class="kw3">DIR</span></a> . DIRECTORY_SEPARATOR . <span class="st0">'product'</span> . DIRECTORY_SEPARATOR . <span class="st0">'ConcreteProduct2_2.php'</span><span class="br0">&#41;</span>;
&nbsp;
<span class="re0">$client</span> = <span class="kw2">new</span> Client<span class="br0">&#40;</span><span class="br0">&#41;</span>;
try <span class="br0">&#123;</span>
    <span class="re0">$client</span>-&gt;<span class="me1">handleProduct</span><span class="br0">&#40;</span>factory\Factory::<span class="me2">TYPE_1</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span> catch <span class="br0">&#40;</span>\Exception <span class="re0">$e</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="re0">$e</span>-&gt;<span class="me1">getMessage</span><span class="br0">&#40;</span><span class="br0">&#41;</span> . PHP_EOL;
<span class="br0">&#125;</span>
&nbsp;
try <span class="br0">&#123;</span>
    <span class="re0">$client</span>-&gt;<span class="me1">handleProduct</span><span class="br0">&#40;</span>factory\Factory::<span class="me2">TYPE_2</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span> catch <span class="br0">&#40;</span>\Exception <span class="re0">$e</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="re0">$e</span>-&gt;<span class="me1">getMessage</span><span class="br0">&#40;</span><span class="br0">&#41;</span> . PHP_EOL;
<span class="br0">&#125;</span>
&nbsp;
try <span class="br0">&#123;</span>
    <span class="re0">$client</span>-&gt;<span class="me1">handleProduct</span><span class="br0">&#40;</span><span class="nu0">999</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span> catch <span class="br0">&#40;</span>\Exception <span class="re0">$e</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="re0">$e</span>-&gt;<span class="me1">getMessage</span><span class="br0">&#40;</span><span class="br0">&#41;</span> . PHP_EOL;
<span class="br0">&#125;</span></pre>

<p>
    で、実行ファイルを実行すると以下の様な出力が得られます。
</p>
<pre>
abstractfactory\product\ConcreteProduct1_1
abstractfactory\product\ConcreteProduct1_2
abstractfactory\product\ConcreteProduct2_1
abstractfactory\product\ConcreteProduct2_2
Argument of abstractfactory\factory\Factory::abstractfactory\factory\Factory::getFactory() must be constant of abstractfactory\factory\Factory
</pre>

<p>
残念ながらPHP5.3らしいことって何もできなかったですね＾＾；
名前空間を入れてみた、とか機能とはあんまり関係ないことだけです。
Abstract FactoryパターンだとClientがFactoryとProductの実装を知る必要がないので、<br />
FactoryやProductのサブクラスが増えた場合には、FactoryとProductのサブクラスを実装して<br />
Clientを使うクラスで使用するFactoryの識別(Factory::TYPE_n)を切り替える処理を実装すれば
他のクラスは便利に再利用できそうです。
</p>
<p>
大切なのはClientクラスは抽象クラスであるFactoryとProductしか扱わないこと。<br />
ここに実装クラスが入ってくると、このパターンの意味がなくなってしまいます。<br />
そして注意が必要なのは、Factoryの識別(Factory::TYPE_n)を誰が判断するか、ですね。
</p>]]></description>
 <category>PHP</category>
<comments>http://www.azul.systems-noel.jp/index.php?itemid=83</comments>
 <pubDate>Mon, 7 Dec 2009 18:37:00 +0900</pubDate>
</item><item>
 <title><![CDATA[PHPでJavaのEnumっぽい何かを手っ取り早く]]></title>
 <link>http://www.azul.systems-noel.jp/index.php?itemid=81</link>
<description><![CDATA[<p>
    色々出尽くしてそうなねたですが、Enumクラスを定義して、<br />
    それを継承してうんにゃらとかはなしな方向で考えます。<br />
    JavaのEnumをエミュレートしたいわけでもなく、です。<br />
    要件としては、<br />
    1.静的にインスタンスにアクセスしたい。<br />
    2.そのインスタンスは一意であることを保障したい。<br />
    3.タイプヒンティングを使いたい。<br />
    とか、そういうことです。
<p><p>
    とあるクラスに一意に定義された値で処理を行いたい時にどうしてますか?<br />
    オブジェクト定数を使ってもいいのですが、そうするとタイプヒンティングが使えないので、<br />
    予定していない値が渡された時の処理を考える必要があります。
</p>

<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
<span class="coMULTI">/**
 * Type
 */</span>
<span class="kw2">class</span> Type <span class="br0">&#123;</span>
    <span class="coMULTI">/**
     * Type A
     * @var integer
     */</span>
    const A = <span class="nu0">0</span>;
&nbsp;
    <span class="coMULTI">/**
     * Type B
     * @var integer
     */</span>
    const B = <span class="nu0">1</span>;
&nbsp;
    <span class="coMULTI">/**
     * Type C
     * @var integer
     */</span>
    const C = <span class="nu0">2</span>;
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/**
 * Chech Type
 * @param integer $type Type to check
 */</span>
<span class="kw2">function</span> checkType<span class="br0">&#40;</span><span class="re0">$type</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$type</span> == Type::<span class="me2">A</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="st0">&quot;Type is Type A<span class="es0">\n</span>&quot;</span>;
    <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$type</span> == Type::<span class="me2">B</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="st0">&quot;Type is Type B<span class="es0">\n</span>&quot;</span>;
    <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$type</span> == Type::<span class="me2">C</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="st0">&quot;Type is Type C<span class="es0">\n</span>&quot;</span>;
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="re0">$a</span> = Type::<span class="me2">A</span>;
<span class="re0">$b</span> = Type::<span class="me2">B</span>;
<span class="re0">$c</span> = Type::<span class="me2">C</span>;
&nbsp;
checkType<span class="br0">&#40;</span><span class="re0">$a</span><span class="br0">&#41;</span>;<span class="co1">//Type is A</span>
checkType<span class="br0">&#40;</span><span class="re0">$b</span><span class="br0">&#41;</span>;<span class="co1">//Type is B</span>
checkType<span class="br0">&#40;</span><span class="re0">$c</span><span class="br0">&#41;</span>;<span class="co1">//Type is C</span>
&nbsp;
checkType<span class="br0">&#40;</span><span class="nu0">5</span><span class="br0">&#41;</span>;<span class="co1">//Not expected</span>
checkType<span class="br0">&#40;</span><span class="kw2">null</span><span class="br0">&#41;</span>;<span class="co1">//Type is A, but not expected</span>
checkType<span class="br0">&#40;</span><span class="kw2">new</span> stdClass<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<span class="co1">//Error, but not expected</span>
&nbsp;</pre>

<p>
    予定しない値が渡った時の処理を考えるのも、ですが、<br />
    せっかくタイプヒンティングがあるので、<br />
    タイプヒンティングをうまく使う方法を考えます。
</p>

<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
<span class="coMULTI">/**
 * Type
 */</span>
<span class="kw2">class</span> Type <span class="br0">&#123;</span>
    <span class="coMULTI">/**
     * Instances of this class
     * @var array
     */</span>
    <span class="kw2">private</span> <a target="_blank"  href="http://www.php.net/static"><span class="kw3">static</span></a> <span class="re0">$instances</span> = <a target="_blank"  href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp;
    <span class="coMULTI">/**
     * Return Type A
     * @return Type
     */</span>
    <span class="kw2">public</span> <a target="_blank"  href="http://www.php.net/static"><span class="kw3">static</span></a> <span class="kw2">function</span> A<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw1">if</span><span class="br0">&#40;</span>!<a target="_blank"  href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span>self::<span class="re0">$instances</span><span class="br0">&#91;</span><span class="kw2">__METHOD__</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            self::<span class="re0">$instances</span><span class="br0">&#91;</span><span class="kw2">__METHOD__</span><span class="br0">&#93;</span> = <span class="kw2">new</span> Type<span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span>;
        <span class="br0">&#125;</span>
        <span class="kw1">return</span> self::<span class="re0">$instances</span><span class="br0">&#91;</span><span class="kw2">__METHOD__</span><span class="br0">&#93;</span>;
    <span class="br0">&#125;</span>
&nbsp;
    <span class="coMULTI">/**
     * Return Type B
     * @return Type
     */</span>
    <span class="kw2">public</span> <a target="_blank"  href="http://www.php.net/static"><span class="kw3">static</span></a> <span class="kw2">function</span> B<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw1">if</span><span class="br0">&#40;</span>!<a target="_blank"  href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span>self::<span class="re0">$instances</span><span class="br0">&#91;</span><span class="kw2">__METHOD__</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            self::<span class="re0">$instances</span><span class="br0">&#91;</span><span class="kw2">__METHOD__</span><span class="br0">&#93;</span> = <span class="kw2">new</span> Type<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>;
        <span class="br0">&#125;</span>
        <span class="kw1">return</span> self::<span class="re0">$instances</span><span class="br0">&#91;</span><span class="kw2">__METHOD__</span><span class="br0">&#93;</span>;
    <span class="br0">&#125;</span>
&nbsp;
    <span class="coMULTI">/**
     * Return Type C
     * @return Type
     */</span>
    <span class="kw2">public</span> <a target="_blank"  href="http://www.php.net/static"><span class="kw3">static</span></a> <span class="kw2">function</span> C<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw1">if</span><span class="br0">&#40;</span>!<a target="_blank"  href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span>self::<span class="re0">$instances</span><span class="br0">&#91;</span><span class="kw2">__METHOD__</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            self::<span class="re0">$instances</span><span class="br0">&#91;</span><span class="kw2">__METHOD__</span><span class="br0">&#93;</span> = <span class="kw2">new</span> Type<span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span>;
        <span class="br0">&#125;</span>
        <span class="kw1">return</span> self::<span class="re0">$instances</span><span class="br0">&#91;</span><span class="kw2">__METHOD__</span><span class="br0">&#93;</span>;
    <span class="br0">&#125;</span>
&nbsp;
    <span class="coMULTI">/**
     * Ordinal of this Class
     * @var integer
     */</span>
    <span class="kw2">private</span> <span class="re0">$ordinal</span>;
&nbsp;
    <span class="coMULTI">/**
     * Private constructor
     * @param integer $ordinal Ordinal of this Class
     */</span>
    <span class="kw2">private</span> <span class="kw2">function</span> __construct<span class="br0">&#40;</span><span class="re0">$ordinal</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="re0">$this</span>-&gt;<span class="me1">ordianl</span> = <span class="re0">$ordinal</span>;
    <span class="br0">&#125;</span>
&nbsp;
    <span class="coMULTI">/**
     * Revoke clone
     */</span>
    <span class="kw2">public</span> <span class="kw2">function</span> __clone<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        throw <span class="kw2">new</span> BadFunctionCallException<span class="br0">&#40;</span><span class="st0">'Clone is not allowed.'</span><span class="br0">&#41;</span>;
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/**
 * Chech Type
 * @param Type $type Type to check
 */</span>
<span class="kw2">function</span> checkType<span class="br0">&#40;</span>Type <span class="re0">$type</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$type</span> == Type::<span class="me2">A</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="st0">&quot;Type is Type A<span class="es0">\n</span>&quot;</span>;
    <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$type</span> == Type::<span class="me2">B</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="st0">&quot;Type is Type B<span class="es0">\n</span>&quot;</span>;
    <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$type</span> == Type::<span class="me2">C</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="st0">&quot;Type is Type C<span class="es0">\n</span>&quot;</span>;
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="re0">$a</span> = Type::<span class="me2">A</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="re0">$b</span> = Type::<span class="me2">B</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="re0">$c</span> = Type::<span class="me2">C</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp;
checkType<span class="br0">&#40;</span><span class="re0">$a</span><span class="br0">&#41;</span>;<span class="co1">//Type is A</span>
checkType<span class="br0">&#40;</span><span class="re0">$b</span><span class="br0">&#41;</span>;<span class="co1">//Type is B</span>
checkType<span class="br0">&#40;</span><span class="re0">$c</span><span class="br0">&#41;</span>;<span class="co1">//Type is C</span>
&nbsp;
checkType<span class="br0">&#40;</span><span class="kw2">null</span><span class="br0">&#41;</span>;<span class="co1">//Error</span>
checkType<span class="br0">&#40;</span><span class="kw2">new</span> stdClass<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<span class="co1">//Error</span>
checkType<span class="br0">&#40;</span><span class="kw2">new</span> Type<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<span class="co1">//Error</span>
<span class="re0">$a2</span> = clone <span class="re0">$a</span>;<span class="co1">//BadFunctionCallException</span>
&nbsp;</pre>

<p>
    スタティックメソッドでインスタンスにアクセスするようにしました。<br />
    privateなconstructorと__cloneメソッドを実装して、<br />
    外部からのインスタンス作成と複製を無効にすれば<br />
    インスタンスが一意であることが保障されます。<br />
    タイプヒンティングを使っているので、<br />
    checkType()の内部では$typeはTypeのインスタンスであることが保障されます。

</p>

<p>
    タイプヒンティングは便利なのですが、<br />
    足りてないところもあって、やきもきさせてくれます。<br />
    例えばスカラー型やオブジェクト型のタイプヒンティングが使えれば、<br />
    もっと便利に使えますよね。<br />
    PHPにはstdClassというクラスがあるのですが、stdClassはJavaのObject型とは違って、<br />
    全てのクラスのスーパークラスではありません。
</p>

<pre class="code">&nbsp;
<span class="kw2">function</span> foo<span class="br0">&#40;</span><span class="coMULTI">/** not allowed */</span>integer <span class="re0">$i</span>, <span class="coMULTI">/** not allowed */</span>object <span class="re0">$o</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span>
&nbsp;</pre>]]></description>
 <category>PHP</category>
<comments>http://www.azul.systems-noel.jp/index.php?itemid=81</comments>
 <pubDate>Thu, 20 Aug 2009 15:00:52 +0900</pubDate>
</item><item>
 <title><![CDATA[Cairngormをもう少し便利に使う(1.ViewHelper拡張)]]></title>
 <link>http://www.azul.systems-noel.jp/index.php?itemid=80</link>
<description><![CDATA[<p>
    Cairngormを使う時はViewHelperにロジックを実装していきますが、<br />
    Cairngormは汎用的に作られているので、お約束のコーディングが増えてきます。<br />
    例えば、Viewに設定した全てのValidatorの実行だったり、<br />
    全てのValidatorの検証結果のクリアだったり、<br />
    CairngormEventのdispatchだったり、<br />
    こういうお約束なコードを全てのViewHelperに実装するのは<br />
    コードの量も増えますし、同じようなコードを何度も書くのは、バグの発生率も高まります。<br />
    なるべくシンプルな実装のViewHelperを使えるように<br />
    ViewHelperを拡張したExtendedViewHelperを考えてみます。
</p>

<p>
    ということで、今delfinoが使っているExtendedViewHelperです。<br />
    ViewHelperを実装する場合には、このExtendedViewHelperを拡張して実装しています。<br />
    ちなみに、こういうお約束の内容はFlex Builder(というかeclipse)のスニペットに登録しておくと便利です。<br />
    以下、ExtendedViewHelperのソースです。
</p>

<pre class="code">&nbsp;
package $<span class="br0">&#123;</span>PackageName<span class="br0">&#125;</span> <span class="br0">&#123;</span>
	<span class="kw3">import</span> com.<span class="me1">adobe</span>.<span class="me1">cairngorm</span>.<span class="kw3">control</span>.<span class="me1">CairngormEvent</span>;
	<span class="kw3">import</span> com.<span class="me1">adobe</span>.<span class="me1">cairngorm</span>.<span class="kw3">control</span>.<span class="me1">CairngormEventDispatcher</span>;
	<span class="kw3">import</span> com.<span class="me1">adobe</span>.<span class="me1">cairngorm</span>.<span class="me1">view</span>.<span class="me1">ViewHelper</span>;
&nbsp;
	<span class="kw3">import</span> flash.<span class="me1">events</span>.<span class="me1">Event</span>;
&nbsp;
	<span class="kw3">import</span> mx.<span class="me1">events</span>.<span class="me1">FlexEvent</span>;
	<span class="kw3">import</span> mx.<span class="me1">events</span>.<span class="me1">ValidationResultEvent</span>;
	<span class="kw3">import</span> mx.<span class="me1">validators</span>.<span class="me1">Validator</span>;
&nbsp;
	<span class="coMULTI">/**
	 * ExtendedViewHelper
	 * @author $Author$
	 * 
	 */</span>
	<span class="kw3">public</span> <span class="kw2">class</span> ExtendedViewHelper <span class="kw3">extends</span> ViewHelper <span class="br0">&#123;</span>
&nbsp;
		<span class="coMULTI">/**
		/**
		* CairngormEventDispatcher
		*/</span>
		protected <span class="kw3">static</span> <span class="kw2">var</span> dispatcher:CairngormEventDispatcher = CairngormEventDispatcher.<span class="me1">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp;
		<span class="coMULTI">/**
		 * ViewLocator
		 */</span>
		protected <span class="kw3">static</span> <span class="kw2">var</span> locator:ViewLocator = ViewLocator.<span class="me1">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp;
		<span class="coMULTI">/**
		 * Validators of ExtendedViewHelper
		 */</span>
		protected <span class="kw2">var</span> validators:<span class="kw3">Array</span> = <span class="kw2">new</span> <span class="kw3">Array</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp;
		<span class="coMULTI">/**
		 * initialization
		 * @param document view of ViewHelper
		 * @param id id of ViewHelper
		 * 
		 */</span>
		override <span class="kw3">public</span> <span class="kw2">function</span> initialized<span class="br0">&#40;</span>document:<span class="kw3">Object</span>, id:<span class="kw3">String</span><span class="br0">&#41;</span>:<span class="kw3">void</span> <span class="br0">&#123;</span>
			<span class="kw3">super</span>.<span class="me1">initialized</span><span class="br0">&#40;</span>document, id<span class="br0">&#41;</span>;
			<span class="kw3">this</span>.<span class="me1">view</span>.<span class="me1">addEventListener</span><span class="br0">&#40;</span>FlexEvent.<span class="me1">CREATION_COMPLETE</span>, <span class="kw3">this</span>.<span class="me1">initViewHelper</span><span class="br0">&#41;</span>;
		<span class="br0">&#125;</span>
&nbsp;
		<span class="coMULTI">/**
		 * Initialize method of ExtendedViewHelper.&lt;br /&gt;
		 * Override this method at sub classes.
		 * @param event Evet
		 * 
		 */</span>
		protected <span class="kw2">function</span> initViewHelper<span class="br0">&#40;</span>event:Event<span class="br0">&#41;</span>:<span class="kw3">void</span> <span class="br0">&#123;</span><span class="br0">&#125;</span>
&nbsp;
		<span class="coMULTI">/**
		 * Dispatch specified CairngormEvent.
		 * @param cairngormEvent
		 * 
		 */</span>
		protected <span class="kw2">function</span> dispatch<span class="br0">&#40;</span>cairngormEvent:CairngormEvent<span class="br0">&#41;</span>:<span class="kw3">void</span> <span class="br0">&#123;</span>
			dispatcher.<span class="me1">dispatchEvent</span><span class="br0">&#40;</span>cairngormEvent<span class="br0">&#41;</span>;
		<span class="br0">&#125;</span>
&nbsp;
		<span class="coMULTI">/**
		 * Validate all Validators
		 * @return validate result
		 * 
		 */</span>
		protected <span class="kw2">function</span> validate<span class="br0">&#40;</span><span class="br0">&#41;</span>:<span class="kw3">Boolean</span> <span class="br0">&#123;</span>
			<span class="kw1">if</span><span class="br0">&#40;</span>Validator.<span class="me1">validateAll</span><span class="br0">&#40;</span>validators<span class="br0">&#41;</span>.<span class="kw3">length</span> &lt; <span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
				<span class="kw1">return</span> <span class="kw2">true</span>;
			<span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>
				<span class="kw1">return</span> <span class="kw2">false</span>;
			<span class="br0">&#125;</span>
		<span class="br0">&#125;</span>
&nbsp;
		<span class="coMULTI">/**
		 * Clear all Validation result
		 * 
		 */</span>
		protected <span class="kw2">function</span> clearValidators<span class="br0">&#40;</span><span class="br0">&#41;</span>:<span class="kw3">void</span> <span class="br0">&#123;</span>
			<span class="kw1">for</span> each<span class="br0">&#40;</span><span class="kw2">var</span> validator :Validator <span class="kw1">in</span> <span class="kw3">this</span>.<span class="me1">validators</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
				validator.<span class="me1">dispatchEvent</span><span class="br0">&#40;</span><span class="kw2">new</span> ValidationResultEvent<span class="br0">&#40;</span>ValidationResultEvent.<span class="me1">VALID</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;
			<span class="br0">&#125;</span>
		<span class="br0">&#125;</span>
&nbsp;
	<span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;</pre>

<p>
    少し説明をすると、ViewHelperのinitializedメソッドをオーバライドして、<br />
    ViewのCREATION_COMPLETE時にinitViewHelperがコールバックとして呼ばれるように設定しているのと、<br />
    ExtendedViewHelperのdispatcherフィールドにCairngormEventDispatcherを設定しています。
</p>

<p>
    initViewHelperはViewのCREATION_COMPLETE時に呼ばれますから、<br />
    ここで例えばViewにEventListenerを設定したり、Validatorを設定したりします。<br />
    Viewに設定するValidatorは、ExtendedViewHelperのvalidatorsに追加しておくと<br />
    validateメソッドやclearValidatorsメソッドの対象にすることができます。
</p>

<p>
    dispatchメソッドは、CairngormEventを発行する際に
</p>
<pre class="code">&nbsp;
CairngormEventDispatcher.<span class="me1">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">dispatchEvent</span><span class="br0">&#40;</span>cairngormEvent<span class="br0">&#41;</span>;
&nbsp;</pre>
<p>
    と、いちいち書くのもおっくうなので、
</p>
<pre class="code">&nbsp;
<span class="kw3">this</span>.<span class="me1">dispatch</span><span class="br0">&#40;</span>cairngormEvent<span class="br0">&#41;</span>;
&nbsp;</pre>
<p>
    と手抜きをする為のメソッドです。<br />
    毎回インスタンスの取得を行わないだけ、少しクライアントにも優しい部分もあるかもしれません。
</p>

<p>
    validateメソッドは、フィールドvalidatorsに格納されているValidatorの検証を実行します。<br />
    ありがちな処理で、OKボタン押下時のコールバックなんかに使います。
</p>
<pre class="code">&nbsp;
<span class="kw3">private</span> <span class="kw2">function</span> onOKClick<span class="br0">&#40;</span>event:Event<span class="br0">&#41;</span>:<span class="kw3">void</span> <span class="br0">&#123;</span>
	<span class="kw1">if</span><span class="br0">&#40;</span><span class="kw3">this</span>.<span class="me1">validate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
		<span class="co1">//検証がOKなら処理の実行</span>
	<span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;</pre>
<p>
    とか、こんな感じですね。
</p>

<p>
    そして、clearValidatorsメソッドは、<br />
    フィールドvalidatorsに格納されているValidatorの検証結果をクリアします。<br />
    例えば、何かのVOの編集をする為のViewなんかで、<br />
    検証結果が残ったままなのもあれなので、こんな感じに使います。
</p>
<pre class="code">&nbsp;
<span class="kw3">public</span> <span class="kw2">function</span> <span class="kw3">set</span> vo<span class="br0">&#40;</span>value:VO<span class="br0">&#41;</span>:<span class="kw3">void</span> <span class="br0">&#123;</span>
	<span class="kw3">this</span>._vo = value;
	<span class="kw3">this</span>.<span class="me1">clearValidators</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span>
&nbsp;</pre>

<p>
    と、いうことでまずはViewHelperの拡張クラスについて、でした。<br />
    次はこの拡張ViewHelperを使ったViewHelperの実装についての予定です。<br />
    その後はCairngormEvent、そしてCommandについて、まとめてまいります。<br />
    そして、PureMVCについても、Cairngormシリーズの後にまとめます。
</p>

]]></description>
 <category>Flex</category>
<comments>http://www.azul.systems-noel.jp/index.php?itemid=80</comments>
 <pubDate>Thu, 2 Apr 2009 11:27:19 +0900</pubDate>
</item><item>
 <title><![CDATA[Flexのクラスとサーバサイドのクラスのマッピングがうまくいかないケース]]></title>
 <link>http://www.azul.systems-noel.jp/index.php?itemid=79</link>
<description><![CDATA[<p>
    はい、ものすごく久しぶりの更新です。<br />
    Flexでサーバサイドとの連携を行う場合には、プリミティブ型を使う以外に<br />
    Flex側のクラスとサーバサイドのクラスをマッピングさせることがよくあります。<br />
    で、このマッピングでちょっとはまってしまったのでメモです。
</p>
<p>
    今回のメモはFlex側のアプリケーションの問題なので、<br />
    サーバサイドのアーキテクチャは関係ありません。<br />
    (サーバサイドがamfphpでもPyAMFでもBlazeDSでもLSDSでも)
</p>
<p>
    例えばFlex側でこんなクラスhoge.Hoge.asを書いたとします。
<pre class="code">&nbsp;
package hoge <span class="br0">&#123;</span>
	<span class="br0">&#91;</span>RemoteClass<span class="br0">&#40;</span>alias = <span class="st0">&quot;hoge.Hoge&quot;</span><span class="br0">&#41;</span><span class="br0">&#93;</span>
	<span class="kw3">public</span> <span class="kw2">class</span> Hoge <span class="br0">&#123;</span>
		<span class="kw3">public</span> <span class="kw2">var</span> <span class="kw3">name</span>:<span class="kw3">String</span>;
		<span class="kw3">public</span> <span class="kw2">var</span> value:<span class="kw3">String</span>;
	<span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;</pre>
    そして、サーバサイドにはhoge.Hogeクラスのオブジェクト配列を返すHogeService.getHogeが実装されているとします。<br />
    で、サーバサイドのServiceをRemoteObjectとかで呼んで、結果をDataGridに格納するとします。<br />
    例えばこんなFlexアプリケーションhogeAppli.mxmlがあるとします。
<pre class="code">&nbsp;
&lt;?<span class="kw3">xml</span> <span class="kw3">version</span>=<span class="st0">&quot;1.0&quot;</span> encoding=<span class="st0">&quot;utf-8&quot;</span>?&gt;
&lt;mx:Application xmlns:mx=<span class="st0">&quot;http://www.adobe.com/2006/mxml&quot;</span> layout=<span class="st0">&quot;absolute&quot;</span>&gt;
&lt;mx:Script&gt;
	&lt;!<span class="br0">&#91;</span>CDATA<span class="br0">&#91;</span>
		<span class="kw3">import</span> mx.<span class="me1">rpc</span>.<span class="me1">events</span>.<span class="me1">ResultEvent</span>;
		<span class="kw3">private</span> <span class="kw2">function</span> getResult<span class="br0">&#40;</span>event:ResultEvent<span class="br0">&#41;</span>:<span class="kw3">void</span> <span class="br0">&#123;</span>
			dgHoge.<span class="me1">dataProvider</span> = event.<span class="me1">result</span>;
		<span class="br0">&#125;</span>
	<span class="br0">&#93;</span><span class="br0">&#93;</span>&gt;
&lt;/mx:Script&gt;
	&lt;mx:RemoteObject id=<span class="st0">&quot;remoteObject&quot;</span> destination=<span class="st0">&quot;default&quot;</span> source=<span class="st0">&quot;HogeService&quot;</span> result=<span class="st0">&quot;{getResult(event)}&quot;</span>/&gt;
	&lt;mx:VBox x=<span class="st0">&quot;0&quot;</span> y=<span class="st0">&quot;0&quot;</span>&gt;
		&lt;mx:DataGrid id=<span class="st0">&quot;dgHoge&quot;</span>&gt;
			&lt;mx:columns&gt;
				&lt;mx:DataGridColumn headerText=<span class="st0">&quot;Name&quot;</span> dataField=<span class="st0">&quot;name&quot;</span>/&gt;
				&lt;mx:DataGridColumn headerText=<span class="st0">&quot;Value&quot;</span> dataField=<span class="st0">&quot;value&quot;</span>/&gt;
			&lt;/mx:columns&gt;
		&lt;/mx:DataGrid&gt;
		&lt;mx:<span class="kw3">Button</span> id=<span class="st0">&quot;btnGetHoge&quot;</span> label=<span class="st0">&quot;getHoge&quot;</span> click=<span class="st0">&quot;{remoteObject.getHoge()}&quot;</span>/&gt;
	&lt;/mx:VBox&gt;
&nbsp;
&lt;/mx:Application&gt;
&nbsp;</pre>
</p>
<p>
    さて、btnGetHogeがクリックされて、HogeServiceのgetHogeが実行された後<br />
    getResultメソッドの引数eventのresultに格納されているのは、何のクラスのオブジェクト配列でしょう。<br />
    hoge.Hogeクラスが定義されていてマッピングも定義されているのでhoge.Hogeクラスのオブジェクト配列になりそうなものですけど<br />
    実際にはObjectクラスのオブジェクト配列になります。<br />
    どうしてこういうことになるのかというと、<br />
    Flexのソースツリーの中にhoge.Hoge.asが含まれていたとしても<br />
    アプリケーション(この場合はhogeAppli.mxml)からhoge.Hogeクラスが参照されない限りは<br />
    hoge.Hoge.asはクラスマッピングの対象にならないようです。<br />
    FlexBuilderでは、hoge.Hoge.asにシンタックスの間違いがあってコンパイルが通らないようなソースであっても<br />
    ビルドが通ってしまいますから、そもそもコンパイルの対象にならないのかもしれませんね。
</p>

]]></description>
 <category>Flex</category>
<comments>http://www.azul.systems-noel.jp/index.php?itemid=79</comments>
 <pubDate>Fri, 25 Apr 2008 18:20:53 +0900</pubDate>
</item><item>
 <title><![CDATA[ez Publishを使ったみた。]]></title>
 <link>http://www.azul.systems-noel.jp/index.php?itemid=78</link>
<description><![CDATA[<p><a href="http://ez.no/" target="_blank">ez Publish</a>を使ったみたわけですが、ちょっと覚書。</p>
<h3>Site AccessをHostモードにした場合</h3>
<p>
なんですが、[SiteAccessSettings]セクションのHostMatchMapItems[]ディレクティブが<br />
インストールウィザードで指定したものが反映されてないみたいです。<br />
ezflow_site_userとezflow_site_adminがデフォルトの<br />
ezflow_site_user.<em>ドメイン名</em>とezflow_site_admin.<em>ドメイン名</em>になっています。<br />
修正してあげないとサイトにアクセスできないので、<br />
インストールウィザードが終了した後に<br />
<em>ez Publish install directory</em>/settings/override/site.ini.append.phpを修正いたしましょう。<br />
後は<em>ez Publish install directory</em>/settings/siteaccess以下にあるディレクトリ内のsite.ini.append.phpにある<br />
[SiteSettings]セクションのAdditionalLoginFormActionURLも直したほうがよさげ。
</p>
<p>
Site AccessをデフォルトのURIにした場合には<br />
URLが<em>ez Publish Site</em>/index.php?Hogeとかそんな感じで生成されます。<br />
これを<em>ez Publish Site</em>/Hogeにしたい場合にはSite AccessをHostにする必要があります。<br />
この場合はVirtualHostを使うことになるのですが、共有サーバとかでVirtualHostを使えないけど<br />
サブドメインを使えるような場合(どのケースかとかはぐたぐた長くなるので割愛)には<br />
site.iniの[SiteAccessSettings]セクションにForceVirtualHost=trueと指定してあげるとどうにかなるかもしれません。
</p>
<h3>なんかFLVが再生されないような</h3>
<p>
Delfinoの環境では再生されませんでした。<br />
原因その1はflashvarsでmoviepathという変数を渡しているのですが<br />
これが2回出力されている
</p>
<pre>
moviepath=moviepath=Hoge
</pre>
<p>
のも原因かもしれないのでとりあえずテンプレートを修正。<br />
あ、これez Flowを使ってる場合の話です。<br />
他は試してないので分りません。<br />
<em>ez Publish install directory</em>/extension/ezflow/design/ezflow/override/templates/block/video.tplを修正します。<br />
47行目で
</p>
<pre>
        &lt;param name="flashvars" value="moviepath={$flash_var}" /&gt;
</pre>
<p>
としているので
</p>
<pre>
         &lt;param name="flashvars" value="{$flash_var}" /&gt;

</pre>
<p>
に修正。<br />
これでmoviepathが2重に送信されることはなくなったわけですが･･･はい、やっぱり流れませんね。<br />
ものがSWFなので手を出せません。<br />
ez Publishはオープンソースなので、もしかしたらソースが手に入るのかもですけど<br />
ちょっとそこまで試す気になれないのでここまで。<br />
久しぶりの更新も覚書。
</p>]]></description>
 <category>PHP</category>
<comments>http://www.azul.systems-noel.jp/index.php?itemid=78</comments>
 <pubDate>Fri, 22 Feb 2008 13:10:36 +0900</pubDate>
</item><item>
 <title><![CDATA[amfphp1.9を高速化する。]]></title>
 <link>http://www.azul.systems-noel.jp/index.php?itemid=77</link>
<description><![CDATA[<p>
    書こう書こうと思ってて後回しにしていたことですが、<br />
    amfphp1.9をそのまま使ってるともったいないですんです。<br />
    amfphpの前リーダであるPatrickさんの5 1/2 blogの<br />
    <a href="http://www.5etdemi.com/blog/archives/2007/01/amfphp-19-beta-2-ridiculously-faster/" target="_blank">Amfphp 1.9 beta 2 - ridiculously faster</a>というエントリからの話です。<br />
    ･･･もう一年近く前のエントリなんですけど＾＾；
</p>
<h3>てっとり早く結論</h3>
<p>
    結論から書くと、AMFのエンコードとデコードを行う<br />
    AMFEXTというextensionがありますから、<br />
    そのextensionをPHPにインストールしておくと<br />
    amfphp1.9がextensionを認識して、高速に動作するようになる、ということです。<br />
    Patrickさんによると<br />
    <em>We've tested it through and through, it is very stable, and let me tell you, <strong>it is ridiculously fast</strong>.<br /></em>
    <em>テストにテストを重ねてみたけど、とても安定していて、言わせてもらうなら、<strong>これめっちゃ早いで</strong>。<br /></em>
    とのことです。(いつもながらに適当訳)
</p>

<h3>で、どうするか</h3>
<p>
    <a href="http://www.teslacore.it/wiki/index.php?title=AMFEXT" target="_blank">AMFEXTのサイト</a>からソースやバイナリがダウンロードできます。<br />
    Windowsユーザなら、バイナリのzipをダウンロードすると、<br />
    bin/windows以下にPHPのバージョンごとのdllがありますから、<br />
    使っているPHPのバージョンに該当するdllをPHPのextensionディレクトリに放り込んで<br />
    php.iniにphp_extension=php_amf.dllと追記して、Webサーバを再起動すればよしです。<br />
    Linuxユーザの場合は、phpizeを使ってPECL拡張モジュールとしてコンパイルできるそうです。<br />
    これは試してないので、説明ができません＾＾；<br />
    Linuxの場合は、php.iniにextension=amf.soを追記です。
</p>
<p>
    extensionのセットアップが完了したらphpinfo()を実行するとamfの項目がでてきます。<br />
    で、amfphpのgateway.phpに直接ブラウザからアクセスしてみると、<br />
    「AMF C Extension is loaded and enabled.」の一文が増えてます。<br />
    後はextensionの力で高速になったamfphpが使える、ということですね。
</p>

<h3>ところが色々ありまして</h3>
<p>
    AMFEXTを有効にした状態で、S2Baseのamfphpプラグインを使ってみたんですけど<br />
    どうもS2Dao_ArrayListのマッピングが変わってるみたいで、<br />
    AMFEXTを有効にしていない時のソースコードそのままでは動いてくれませんでした＾＾；<br />
    原因を調べてみないと、と思ってそのままになっていたので<br />
    AMFEXTの話を書いてなかったんです。＾＾；；
</p>
<p>
    で、思い立ってちらっとソースを見ていると･･･AMFEXTってPHPライセンスじゃありませんか。<br />
    と、いうことは、AMFEXTを使った成果物はASL2.0に移行できる･･･のかな？<br />
    考えてみればエンコーダとデコーダがあるってことは、<br />
    amfphpでいうところのGatewayを作れば、S2AMF.PHP5･･･ですか？<br />
    ようやくコミッタらしい何かができますか？<br />
    そしてまたなれない翻訳大会の開始ですか？
</p>
<p>
    amfphp1.9にはgzipサポートの機能があったり<br />
    <a href="http://www.5etdemi.com/blog/archives/2007/01/amfphp-19-beta-2-ridiculously-faster/" target="_blank">Amfphp 1.9 beta 2 - ridiculously faster</a>には、<br />
    amfphp1.9の新機能の紹介が色々と書かれています。<br />
    amfphp1.9は、まだ公式サイトのドキュメントに落ちてない状態ですから<br />
    Patricさんのこのエントリを参考に色々と試してみるのもよいかと思われます。<br />
    amfphp2.0はどうなるかな。<br />
    SourceForgeの方では、ちょっと動きがないようですが。
</p>

<h3>追記</h3>
<p>
    AMFEXTのサイトに書いてあるのですが、<br />
    AMFEXTって<a href="http://pecl.php.net/package/amfext" target="_blank">PECL</a>でも公開されています。<br />
    PECLのはVersionが0.9.1になってますから、<br />
    AMFEXTのサイトにある0.9より新しいということになると思うのですが、<br />
    なんかヘッダファイルの更新日時が微妙ですね･･･＾＾；<br />
    そして、amfphpのSorceForgeのCVSにはAMFEXTが置かれてますね･･･。<br />
    こっちの方は最終更新が3/22ですから、うーん＾＾；；<br />
    AMFEXTのサイトには、SorceForgeに移行するよって書いてあるんですけど<br />
    一体どこに･･･あるんだろう･･･。<br />
    PECLのが最新版と思えばいいのかな･･･＾＾；；；
</p>
]]></description>
 <category>PHP</category>
<comments>http://www.azul.systems-noel.jp/index.php?itemid=77</comments>
 <pubDate>Thu, 22 Nov 2007 12:21:13 +0900</pubDate>
</item><item>
 <title><![CDATA[ViewHelperを使ったPopUpについて考えてみる。]]></title>
 <link>http://www.azul.systems-noel.jp/index.php?itemid=76</link>
<description><![CDATA[<p>
    CairngormでViewHelperを使っているコンポーネントをPopupしたい場合どうするか、という話です。<br />
    ちょっと卵が先かニワトリが先か、ということで考えてしまったのでメモ。
</p>
<p>
    Cairngormでは、ViewLocatorを使ってViewとロジックを分離します。<br />
    アプリケーションの見た目に関る部分はMXMLに記述して、動作に関る部分はViewHelperに記述することで<br />
    見た目と動作を別のものにするわけですね。<br />
    具体的にはMXMLの中でそのViewに該当するViewLocatorを宣言しておきます。<br />
    Hogeというコンポーネントに対するViewHelperがHogeViewHelperならこんな感じです。
</p>
<pre class="code">&nbsp;
<span class="sc3"><span class="re1">&lt;?xml</span> <span class="re0">version</span>=<span class="st0">&quot;1.0&quot;</span> <span class="re0">encoding</span>=<span class="st0">&quot;utf-8&quot;</span><span class="re2">?&gt;</span></span>
<span class="sc3"><span class="re1">&lt;mx:Panel</span> 
	<span class="re0">xmlns:mx</span>=<span class="st0">&quot;http://www.adobe.com/2006/mxml&quot;</span> 
	<span class="re0">xmlns:viewhelper</span>=<span class="st0">&quot;hoge.viewhelper.*&quot;</span> <span class="re2">&gt;</span></span>
	<span class="sc3"><span class="re1">&lt;viewhelper:HogeViewHelper</span> <span class="re0">id</span>=<span class="st0">&quot;hogeViewHelper&quot;</span> <span class="re2">/&gt;</span></span>
&nbsp;</pre>
<p>
    そうするとHogeViewのインスタンスが生成された時に<br />
    HogeViewHelperのインスタンスが生成されて、<br />
    HogeViewHelperのviewフィールドにHogeViewのインスタンスへの参照が設定されます。<br />
    で、あわせてViewLocatorにMXMLで指定したHogeViewHelperのidをキーとして<br />
    (Cairngormのドキュメントで言うところのcanonical name)<br />
    HogeViewHelperのインスタンスが登録されます。<br />
    後はViewLocatorのインスタンスにgetViewHelper("hogeViewHelper")とすると<br />
    HogeViewHelperのインスタンスを返してくれます。
</p>

<p>
    もう少しつっこんで書くと、<br />
    HogeViewHelperのスーパクラスであるViewHelperクラスには<br />
    initializedメソッドが定義されていて、<br />
    このメソッドの中で自身のviewとidを設定して、<br />
    対象となるViewに対してイベントリスナを設定しています。<br />
    イベントリスナはEvent.ADDEDとEvent.REMOVEDで<br />
    対象となるViewが表示対象となった時には<br />
    ViewLocatorに対して自身を登録して、<br />
    対象となるViewが表示対象外となった時には<br />
    ViewLocatorに対して自身をします。
</p>

<p>
    つまり、ViewHelperの準備が完了するには以下のステップがあります。
</p>
<ol>
    <li>ViewHelperが設定されたViewのインスタンスが生成される。</li>
    <li>ViewHelperのインスタンスが生成される。</li>
    <li>ViewHelperがimplementsしているIMXMLObjectのinitializedメソッドが呼ばれる。</li>
    <li>initializedメソッドの中でViewHelperのidフィールドとviewフィールドが設定される。</li>
    <li>initializedメソッドの中でViewに対してイベントリスナが登録される。</li>
    <li>Viewが表示対象となる。(ApplicationでaddChildされるとか)</li>
    <li>イベントリスナに登録されたコールバックメソッドの中でViewHelperがViewLocatorに登録される。</li>
</ol>
<p>
    これでようやくViewLocatorからViewHelperが取得できるようになるわけです。<br />
    反対にViewが表示対象外(ApplicationでremoveChildされるとか)すると<br />
    イベントリスナに登録されたコールバックメソッドの中でViewLocatorからViewHelperが削除されます。
</p>

<p>
    はい、長々書きましたけど次に進みます。<br />
    FlexでPopUpを実現するには、PopUpManagerというクラスの3つのスタティックメソッドを使います。<br />
    シグネチャはこんな感じになってます。
</p>
<pre class="code">&nbsp;
<span class="kw3">public</span> <span class="kw3">static</span> <span class="kw2">function</span> addPopUp<span class="br0">&#40;</span>window:IFlexDisplayObject, parent:DisplayObject, modal:<span class="kw3">Boolean</span> = <span class="kw2">false</span>, childList:<span class="kw3">String</span> = <span class="kw2">null</span><span class="br0">&#41;</span>:<span class="kw3">void</span>
<span class="kw3">public</span> <span class="kw3">static</span> <span class="kw2">function</span> createPopUp<span class="br0">&#40;</span>parent:DisplayObject, className:<span class="kw2">Class</span>, modal:<span class="kw3">Boolean</span> = <span class="kw2">false</span>, childList:<span class="kw3">String</span> = <span class="kw2">null</span><span class="br0">&#41;</span>:IFlexDisplayObject
<span class="kw3">public</span> <span class="kw3">static</span> <span class="kw2">function</span> removePopUp<span class="br0">&#40;</span>popUp:IFlexDisplayObject<span class="br0">&#41;</span>:<span class="kw3">void</span>
&nbsp;</pre>
<p>
    addPopUpかcreatePopUpでPopUpを表示して、removePopUpでPopUpを削除します。<br />
    addPopUpとcreatePopUpの違いは、<br />
    PopUpの対象をインスタンスで指定するか(addPopUp)<br />
    クラス名で指定するか(createPopUp)の違いです。
</p>

<p>
    何も考えずApplicationの中でPopUpするなら、こんなコードを書くわけです。
</p>
<pre class="code">&nbsp;
<span class="kw2">var</span> hogeView:HogeView = <span class="kw2">new</span> HogeView<span class="br0">&#40;</span><span class="br0">&#41;</span>;
PopUpManager.<span class="me1">addPopUp</span><span class="br0">&#40;</span>hogeView, <span class="kw3">this</span>, <span class="kw2">true</span><span class="br0">&#41;</span>;
&nbsp;</pre>
<p>
    さて、ViewHelperを使うならどうしましょう。<br />
    しれっと考えるとViewHelperの中にpopUpとかいうメソッドを作って<br />
    それを呼びたいところですが、Viewのインスタンスが存在していないと<br />
    ViewHelperのインスタンスも存在していません。<br />
    ViewHelperがViewLocatorに登録されるのは<br />
    Viewが表示対象になった後なので、こんなコードもアウトです。
</p>
<pre class="code">&nbsp;
<span class="kw2">var</span> hogeView:HogeView = <span class="kw2">new</span> HogeView<span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="kw2">var</span> hogeViewHelper:HogeViewHelper = HogeViewHelper<span class="br0">&#40;</span>ViewLocator.<span class="me1">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">getViewHelper</span><span class="br0">&#40;</span><span class="st0">&quot;hogeViewHelper&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;
hogeViewHelper.<span class="me1">popUp</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp;</pre>
<p>
    Viewが表示対象になるまではViewLocatorからViewHelperを取得できないので<br />
    PopUpしてからじゃないとViewHelperを使うことができない。ということです。<br />
    付け加えておくと、PopUpするためにはPopUp対象となる親コンポーネントを指定する必要があるので<br />
    親コンポーネントのViewHelperにViewを返すメソッドを定義しておいて、<br />
    子コンポーネントのViewHelperから親コンポーネントのViewHelperを取得して<br />
    親コンポーネントのViewHelperから親コンポーネントを取得してっていう<br />
    何やらスパゲッティな予感漂う実装になっちゃいますね。
</p>

<p>
    はい、ということでこんな感じの実装はどうでしょう。<br />
    まず親コンポーネントのViewHelperにこんなメソッドを用意しておきます。
</p>
<pre class="code">&nbsp;
		<span class="kw3">public</span> <span class="kw2">function</span> createPopUp<span class="br0">&#40;</span>className:<span class="kw2">Class</span>, modal:<span class="kw3">Boolean</span> = <span class="kw2">false</span>, childList:<span class="kw3">String</span> = <span class="kw2">null</span><span class="br0">&#41;</span>:IFlexDisplayObject <span class="br0">&#123;</span>
			<span class="kw2">var</span> parent:DisplayObject = ;
			<span class="kw1">return</span> PopUpManager.<span class="me1">createPopUp</span><span class="br0">&#40;</span>parent, className, modal<span class="br0">&#41;</span>;
		<span class="br0">&#125;</span>
&nbsp;</pre>
<p>
    で、PopUpする子コンポーネントのViewHelperにはこんなメソッドを。
</p>
<pre class="code">&nbsp;
		<span class="kw3">public</span> <span class="kw2">function</span> <span class="kw3">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:<span class="kw3">void</span> <span class="br0">&#123;</span>
			<span class="kw2">var</span> window:IFlexDisplayObject = IFlexDisplayObject<span class="br0">&#40;</span><span class="kw3">this</span>.<span class="me1">view</span><span class="br0">&#41;</span>;
			PopUpManager.<span class="me1">removePopUp</span><span class="br0">&#40;</span>window<span class="br0">&#41;</span>;
		<span class="br0">&#125;</span>
&nbsp;</pre>
<p>
    closeメソッドはこんな感じ親コンポーネントに実装することもできるでしょうけど
</p>
<pre class="code">&nbsp;
		<span class="kw3">public</span> <span class="kw2">function</span> <span class="kw3">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:<span class="kw3">void</span> <span class="br0">&#123;</span>
			<span class="kw2">var</span> hogeViewHelper:HogeViewHelper = HogeViewHelper<span class="br0">&#40;</span>ViewLocator.<span class="me1">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">getViewHelper</span><span class="br0">&#40;</span><span class="st0">&quot;hogeViewHelper&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;
			<span class="kw2">var</span> window:IFlexDisplayObject = IFlexDisplayObject<span class="br0">&#40;</span>hogeViewHelper.<span class="me1">getView</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;
			PopUpManager.<span class="me1">removePopUp</span><span class="br0">&#40;</span>window<span class="br0">&#41;</span>;
		<span class="br0">&#125;</span>
&nbsp;</pre>
<p>
    これだとHogeViewHelper側にViewを返すメソッド(getView())が必要になるので<br />
    ちょっといやな予感がしますね。<br />
    ちなみに親コンポーネントのViewHelperのcreatePopUpは、<br />
    addPopUpメソッドでもいける･･･と思います･･･試してませんけど＾＾；<br />
    PopUpManagerのremovePopUpメソッドが実行された時には、<br />
    REMOVEDなEventがdiapatchされますので、<br />
    ViewLocatorからHogeViewHelperの登録は削除されます。<br />
    つまり、後処理もちゃんとしてくれてるってことですね。
</p>
]]></description>
 <category>Flex</category>
<comments>http://www.azul.systems-noel.jp/index.php?itemid=76</comments>
 <pubDate>Wed, 21 Nov 2007 11:57:26 +0900</pubDate>
</item><item>
 <title><![CDATA[FlexBuilder2のエディタの色設定]]></title>
 <link>http://www.azul.systems-noel.jp/index.php?itemid=75</link>
<description><![CDATA[<p>
    前から気になっていたわけです。<br />
    やっぱりエディタっていったら黒背景が使いやすいと感じるのですが、<br />
    FlexBuilder2のエディタの色って固定なんですよね。<br />
    目を凝らしてコーディングしてる時点で無駄も多そうですし＾＾；
</p>
<p>
    で、思い立ってGoogle先生に質問してみたところ、やっぱり当たるのはFxUGです。<br />
    フォーラムの<a href="http://www.fxug.net/modules/xhnewbb/viewtopic.php?topic_id=1215" target="_blank">エディタの色の変更について</a>を見れば解決です。<br />
    Eclipceのpluginディレクトリにあるcom.adobe.flexbuilder.editors.commonにcommon.jarがあります。<br />
    このcommon.jarの中にその名もColors.xmlというファイルがあって、どうやらここで色が設定されているようです。<br />
    なので、Eclipseを終了してからcommon.jarを解凍して、Colors.xmlを編集してもう一回common.jarという名前で圧縮して<br />
    Eclipseを起動すれば、これで黒背景でも目も優しい(そもそも本末転倒)色設定になります。<br />
    common.jarを編集する前にはバックアップをとっておきましょう。<br />
    困った時はFxUGですね。
</p>

<p>
    と、スタイルの設定の仕方を学習中のDelfinoでした。<br />
    Cairngorm的にいくなら、見た目に関るところはView、動作に関るところはViewHelper。<br />
    Wikiにもちょっと書いているのですが、<a href="http://wiki.azul.systems-noel.jp/doku.php?id=3._cairngorm:1._component:viewhelper" target="_blank">ViewHelper</a>をうまく実装すれば、View(MXML)に書くのは対応するViewHelperの定義だけで済みます。<br />
    そうするとViewの中からonclick="ほげらほげら"とかいう動作に関る部分が抜けますし、<br />
    CairngormのCommandが成功した場合に実行される際の実装(IResponderのresultメソッド)もViewLocatorからViewHelperをとればよいわけです。<br />
    例えばありがちなログインに成功したら、ログイン完了画面に移行するという処理処理なら、<br />
    Stateを変える為のメソッドをViewHelperに用意しておいて、Commandのクラスのresultメソッドから<br />
    ViewHelperのステートを変えるメソッドを呼んだりとかするわけですね。<br />
    さてさて、じゃあViewの部分の表示に関るところは、というと全然不勉強だったので<br />
    ただいまStyleコンポーネントとかCSSについて勉強中であります。<br />
    チャートコンポーネントを使おうと思ったら、このあたりは必須ですね。
</p>
]]></description>
 <category>Flex</category>
<comments>http://www.azul.systems-noel.jp/index.php?itemid=75</comments>
 <pubDate>Tue, 20 Nov 2007 11:53:31 +0900</pubDate>
</item><item>
 <title><![CDATA[S2Base.PHP5をなでる(Interceptor編)]]></title>
 <link>http://www.azul.systems-noel.jp/index.php?itemid=74</link>
<description><![CDATA[<p>
    なんだか間があいてしまいましたが、S2Base.PHP5をなでて参ります。<br />
    今回はInterceptor編、AOPってやつですね。
</p>
<p>
    用語の解説は専門のサイトにお任せすることにして、<br />
    AOPっていうのは、OOPでいうところのクラスに横断することを集約してしまおうという考え方だと思ってます。<br />
    例えば、デバッグの為にメソッドの引数と戻り値をログ出力することを考えるとします。<br />
    これをひとつひとつのクラスのメソッドに実装していったら大改修です。<br />
    そこで引数と戻り値をログ出力する機能をAOPでいうところのAdviceとして実装して<br />
    対象となるクラスの任意の場所(Jointpoint)の集合(Pointcut)を定義して<br />
    AdviceをPointcutに対して適応(Weave)するのです。
</p>

<p>
    さて、さっそく実践。<br />
    S2Container.PHP5では、AdviceをInterceptorとして実装します。<br />
    で、Interceptorを適応するにはdiconのcomponent要素にaspect要素を定義するか<br />
    クラスにAnnotationを記述するか<br />
    S2ContainerApplicationContextの自動アスペクトを使います。<br />
    今回はS2ContainerApplicationContextの自動アスペクトを使います。
</p>

<p>
    S2Container.PHP5には元々組み込まれているInterceptorがあるのですが<br />
    せっかくなので自作いたしましょう。<br />
    せっかくついでなので、前のエントリに書いたEntityのValidationを行うInterceptorを使います。<br />
    このIntercetptorは、Daoに対して適応してinsert、updateといった更新系のメソッドが実行される際に<br />
    引数として渡されたEntityに値が設定されているかどうかをチェックして、<br />
    値が入っていなければ、例外を発行します。<br />
    Entityに値が必要かどうかを定義するのに<em>プロパティ名_REQUIRED</em>という定数をEntityに定義することにします。
</p>

<p>
    このなでるシリーズではS2BasePluginクラスがEntityです。<br />
    では早速S2BasePluginクラスのコード。
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
<span class="kw2">class</span> S2BasePlugin <span class="br0">&#123;</span>
    const TABLE = <span class="st0">&quot;s2base_plugin&quot;</span>;
    <span class="kw2">public</span> <span class="kw2">function</span> __construct<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span><span class="br0">&#125;</span>
&nbsp;
    protected <span class="re0">$id</span>;
    const id_COLUMN = <span class="st0">&quot;id&quot;</span>;
    <span class="kw2">public</span> <span class="kw2">function</span> setId<span class="br0">&#40;</span><span class="re0">$val</span><span class="br0">&#41;</span><span class="br0">&#123;</span><span class="re0">$this</span>-&gt;<span class="me1">id</span> = <span class="re0">$val</span>;<span class="br0">&#125;</span>
    <span class="kw2">public</span> <span class="kw2">function</span> getId<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span><span class="kw1">return</span> <span class="re0">$this</span>-&gt;<span class="me1">id</span>;<span class="br0">&#125;</span>
&nbsp;
    protected <span class="re0">$name</span>;
    const name_COLUMN = <span class="st0">&quot;name&quot;</span>;
    const name_REQUIRED = <span class="st0">&quot;true&quot;</span>;
    <span class="kw2">public</span> <span class="kw2">function</span> setName<span class="br0">&#40;</span><span class="re0">$val</span><span class="br0">&#41;</span><span class="br0">&#123;</span><span class="re0">$this</span>-&gt;<span class="me1">name</span> = <span class="re0">$val</span>;<span class="br0">&#125;</span>
    <span class="kw2">public</span> <span class="kw2">function</span> getName<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span><span class="kw1">return</span> <span class="re0">$this</span>-&gt;<span class="me1">name</span>;<span class="br0">&#125;</span>
&nbsp;
&nbsp;
    <span class="kw2">public</span> <span class="kw2">function</span> __toString<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="re0">$buf</span> = <a target="_blank"  href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="re0">$buf</span><span class="br0">&#91;</span><span class="br0">&#93;</span> = <span class="st0">'id =&gt; '</span> . <span class="re0">$this</span>-&gt;<span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="re0">$buf</span><span class="br0">&#91;</span><span class="br0">&#93;</span> = <span class="st0">'name =&gt; '</span> . <span class="re0">$this</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="kw1">return</span> <span class="st0">'{'</span> . <a target="_blank"  href="http://www.php.net/implode"><span class="kw3">implode</span></a><span class="br0">&#40;</span><span class="st0">', '</span>,<span class="re0">$buf</span><span class="br0">&#41;</span> . <span class="st0">'}'</span>;
    <span class="br0">&#125;</span>
&nbsp;
&nbsp;
    <span class="coMULTI">/*
    private $prop;
    const prop_RELNO = 0;
    const prop_RELKEYS = 'this_fk:other_pk';
    public function setProp(OtherEntity $entity){ $this-&gt;prop = $entity; }
    public function getProp(){ return $this-&gt;prop; }
    */</span>
<span class="br0">&#125;</span>
&nbsp;</pre>
    一行増えただけですね。<br />
    プロパティnameは、必ず値が必要であるということを定義しました。<br />
    続いてInterceptorを作成します。<br />
    s2baseのコンソールを起動して、Interceptorを作成します。<br />
    作成するInterceptorの名前はEntityValueValidatorInterceptorとします。
<pre class="code">&nbsp;
<span class="br0">&#91;</span> Command list <span class="br0">&#93;</span>
<span class="nu0">0</span> : <span class="re0"><span class="br0">&#40;</span><a target="_blank"  href="http://www.ss64.com/nt/exit.html"><span class="kw1">exit</span></a><span class="br0">&#41;</span></span>
<span class="nu0">1</span> : <span class="re0">dao</span>
<span class="nu0">2</span> : <span class="re0">dicon</span>
<span class="nu0">3</span> : <span class="re0">entity</span>
<span class="nu0">4</span> : <span class="re0">goya</span>
<span class="nu0">5</span> : <span class="re0">interceptor</span>
<span class="nu0">6</span> : <span class="re0">module</span>
<span class="nu0">7</span> : <span class="re0">service</span>
choice ? : <span class="re0"><span class="nu0">5</span></span>
&nbsp;
<span class="br0">&#91;</span> Module list <span class="br0">&#93;</span>
<span class="nu0">0</span> : <span class="re0"><span class="br0">&#40;</span><a target="_blank"  href="http://www.ss64.com/nt/exit.html"><span class="kw1">exit</span></a><span class="br0">&#41;</span></span>
<span class="nu0">1</span> : <span class="re0">sample_module</span>
choice ? : <span class="re0"><span class="nu0">1</span></span>
&nbsp;
interceptor class name ? : <span class="re0">EntityValueValidatorInterceptor</span>
&nbsp;
<span class="br0">&#91;</span> generate information <span class="br0">&#93;</span>
  module name            : <span class="re0">sample_module</span>
  interceptor class name : <span class="re0">EntityValueValidatorInterceptor</span>
&nbsp;
confirm ? <span class="br0">&#40;</span>y/n<span class="br0">&#41;</span> : <span class="re0">y</span>
&nbsp;</pre>
    これでEntityValueValidatorInterceptorが<br />
    sampleプロジェクトのapp/modules/sample_module/interceptorディレクトリに作成されました。<br />
    作成されたEntityValueValidatorInterceptorは、こんな感じです。
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
<span class="kw2">class</span> EntityValueValidatorInterceptor
    <span class="kw2">extends</span> S2Container_AbstractInterceptor <span class="br0">&#123;</span>
&nbsp;
    <span class="coMULTI">/**
     * @param S2Container_MethodInvocation $invocation
     *    - $invocation-&gt;getThis()      : return target object
     *    - $invocation-&gt;getMethod()    : return ReflectionMethod of target method
     *    - $invocation-&gt;getArguments() : return array of method arguments
     */</span>
    <span class="kw2">public</span> <span class="kw2">function</span> invoke<span class="br0">&#40;</span>S2Container_MethodInvocation <span class="re0">$invocation</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="kw1">return</span> <span class="re0">$invocation</span>-&gt;<span class="me1">proceed</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;</pre>
    EntityValueValidatorInterceptor::invoke()がJoinpointで実行されます。<br />
    今は、元々の処理を実行して結果を返すという内容になっています。<br />
    で、このEntityValueValidatorInterceptorをこんな感じに変更します。
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
<span class="kw2">class</span> EntityValueValidatorInterceptor
    <span class="kw2">extends</span> S2Container_AbstractInterceptor <span class="br0">&#123;</span>
&nbsp;
    <span class="coMULTI">/**
     * column annotation sufix
     *
     */</span>
    const COLUMN_ANNOTATION_SURFIX = <span class="st0">&quot;_COLUMN&quot;</span>;
&nbsp;
    <span class="coMULTI">/**
     * value required surfix
     * @var string
     */</span>
    const REQUIRED_ANNOTATION_SURFIX = <span class="st0">&quot;_REQUIRED&quot;</span>;
&nbsp;
    <span class="coMULTI">/**
     * Getter name prefix
     * @var string
     */</span>
    const GETTER_PREFIX = <span class="st0">&quot;get&quot;</span>;
&nbsp;
    <span class="coMULTI">/**
     * @param S2Container_MethodInvocation $invocation
     *    - $invocation-&gt;getThis()      : return target object
     *    - $invocation-&gt;getMethod()    : return ReflectionMethod of target method
     *    - $invocation-&gt;getArguments() : return array of method arguments
     */</span>
    <span class="kw2">public</span> <span class="kw2">function</span> invoke<span class="br0">&#40;</span>S2Container_MethodInvocation <span class="re0">$invocation</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="re0">$args</span> = <span class="re0">$invocation</span>-&gt;<span class="me1">getArguments</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="re0">$className</span> = <span class="kw2">null</span>;
        <span class="re0">$reflectionClass</span> = <span class="kw2">null</span>;
        <span class="re0">$getterName</span> = <span class="kw2">null</span>;
        <span class="re0">$getterMethod</span> = <span class="kw2">null</span>;
        <span class="re0">$getterResult</span> = <span class="kw2">null</span>;
        <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$args</span> <span class="kw1">as</span> <span class="re0">$arg</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            <span class="re0">$className</span> = <a target="_blank"  href="http://www.php.net/get_class"><span class="kw3">get_class</span></a><span class="br0">&#40;</span><span class="re0">$arg</span><span class="br0">&#41;</span>;
            <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$className</span> != <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                <span class="re0">$reflectionClass</span>  = <span class="kw2">new</span> ReflectionClass<span class="br0">&#40;</span><span class="re0">$className</span><span class="br0">&#41;</span>;
                <span class="co1">//is entity?</span>
                <span class="kw1">if</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/strpos"><span class="kw3">strpos</span></a><span class="br0">&#40;</span><span class="re0">$reflectionClass</span>-&gt;<span class="me1">getFileName</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, S2BASE_PHP5_ENTITY_DIR<span class="br0">&#41;</span> !== <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                    <span class="co1">//get props</span>
                    <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$reflectionClass</span>-&gt;<span class="me1">getProperties</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw1">as</span> <span class="re0">$prop</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                        <span class="co1">//is column of table?</span>
                        <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$reflectionClass</span>-&gt;<span class="me1">hasConstant</span><span class="br0">&#40;</span><span class="re0">$prop</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> . self::<span class="me2">COLUMN_ANNOTATION_SURFIX</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                            <span class="co1">//getter exist?</span>
                            <span class="re0">$getterName</span> = self::<span class="me2">GETTER_PREFIX</span> . <span class="re0">$prop</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
                            <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$reflectionClass</span>-&gt;<span class="me1">hasMethod</span><span class="br0">&#40;</span><span class="re0">$getterName</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                                <span class="re0">$getterMethod</span> = <span class="re0">$reflectionClass</span>-&gt;<span class="me1">getMethod</span><span class="br0">&#40;</span><span class="re0">$getterName</span><span class="br0">&#41;</span>;
                                <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$getterMethod</span>-&gt;<span class="me1">isPublic</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                                    <span class="co1">//value required?</span>
                                    <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$reflectionClass</span>-&gt;<span class="me1">hasConstant</span><span class="br0">&#40;</span><span class="re0">$prop</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> . self::<span class="me2">REQUIRED_ANNOTATION_SURFIX</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                                        <span class="re0">$getterResult</span> = <span class="re0">$getterMethod</span>-&gt;<span class="me1">invoke</span><span class="br0">&#40;</span><span class="re0">$arg</span><span class="br0">&#41;</span>;
                                        <span class="co1">//value exist?</span>
                                        <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$getterResult</span> !== <span class="nu0">0</span> &amp;&amp; <span class="re0">$getterResult</span> == <span class="kw2">null</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                                             throw <span class="kw2">new</span> Exception<span class="br0">&#40;</span><span class="re0">$prop</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> . <span class="st0">&quot; is required.&quot;</span><span class="br0">&#41;</span>;
                                        <span class="br0">&#125;</span>
                                    <span class="br0">&#125;</span>
                                <span class="br0">&#125;</span>
                            <span class="br0">&#125;</span>
                        <span class="br0">&#125;</span>
                    <span class="br0">&#125;</span>
                <span class="br0">&#125;</span>
            <span class="br0">&#125;</span>
        <span class="br0">&#125;</span>
        <span class="kw1">return</span> <span class="re0">$invocation</span>-&gt;<span class="me1">proceed</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;</pre>
    定数はそれぞれ以下の様な役割です。<br />
    COLUMN_ANNOTATION_SURFIXはS2DaoのCOLUMNアノテーションを定数で行う場合の命名規則です。<br />
    REQUIRED_ANNOTATION_SURFIXは先程書いたフィールドが必須かどうかを表す規則です。<br />
    GETTER_PREFIXはプロパティのGetterメソッドの命名規則です。
</p>

<p>
    EntityValueValidatorInterceptor::invoke()の中身は<br />
    まずメソッドの引数を取得($methodInvocation-&gt;getArguments();)<br />
    引数のクラス名を取得して($className = get_class($arg);)<br />
    引数がクラスかどうかを判断。(if ($className != false))<br />
    クラスであるならReflectionを取得して($reflectionClass  = new ReflectionClass($className);)<br />
    Entityかどうかを判断。(if(strpos($reflectionClass-&gt;getFileName(), S2BASE_PHP5_ENTITY_DIR) !== false))<br />
    EntityであるならプロパティのReflextionを取得してプロパティごとにループ。<br />
    (foreach($reflectionClass-&gt;getProperties() as $prop) {)<br />
    プロパティがテーブルのカラムと関連付けられているかを判断して<br />
    (if($reflectionClass->hasConstant($prop-&gt;getName() . self::COLUMN_ANNOTATION_SURFIX)) {)<br />
    プロパティのGetterメソッド名を取得して($getterName = self::GETTER_PREFIX . $prop-&gt;getName();)<br />
    Getterメソッドがあるかどうか判断。(if($reflectionClass-&gt;hasMethod($getterName)) {)<br />
    Getterメソッドがpublicかどうかを判断して、(if($getterMethod-&gt;isPublic()) {)<br />
    値が必要かどうかを判断。(if($reflectionClass-&gt;hasConstant($prop-&gt;getName() . self::REQUIRED_ANNOTATION_SURFIX)) {)<br />
    値が必要なら、GetterメソッドのReflectionを実行。<br />
    ($getterResult = $getterMethod-&gt;invoke($arg);)<br />
    値がなければ例外発行。<br />
    という流れです。
</p>

<p>
    では早速このInterceptorをDaoに適応します。<br />
    sample_moduleモジュールの設定ファイルが<br />
    sampleプロジェクトのapp/modules/sample_module/sample_module.inc.phpにあります。<br />
    ここでS2ContainerApplicationContextの設定を行っていますので、<br />
    このファイルを変更します。<br />
    オリジナルはこんな感じです。
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
S2ContainerApplicationContext::<span class="me2">init</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">import</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw2">__FILE__</span><span class="br0">&#41;</span> . <span class="st0">'/dao'</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">import</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw2">__FILE__</span><span class="br0">&#41;</span> . <span class="st0">'/entity'</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">import</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw2">__FILE__</span><span class="br0">&#41;</span> . <span class="st0">'/interceptor'</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">import</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw2">__FILE__</span><span class="br0">&#41;</span> . <span class="st0">'/service'</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">import</span><span class="br0">&#40;</span>S2BASE_PHP5_ROOT . <span class="st0">'/app/commons/dao'</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">import</span><span class="br0">&#40;</span>S2BASE_PHP5_ROOT . <span class="st0">'/app/commons/dicon/dao.dicon'</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">registerAspect</span><span class="br0">&#40;</span><span class="st0">'/Dao$/'</span>, <span class="st0">'dao.interceptor'</span><span class="br0">&#41;</span>;
&nbsp;
<span class="kw2">?&gt;</span>
&nbsp;</pre>
    前回も話しましたが、すでにDaoに対してdao.interceptorが定義されています。<br />
    で、このファイルをこう修正します。
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
S2ContainerApplicationContext::<span class="me2">init</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">import</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw2">__FILE__</span><span class="br0">&#41;</span> . <span class="st0">'/dao'</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">import</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw2">__FILE__</span><span class="br0">&#41;</span> . <span class="st0">'/entity'</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">import</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw2">__FILE__</span><span class="br0">&#41;</span> . <span class="st0">'/interceptor'</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">import</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="kw2">__FILE__</span><span class="br0">&#41;</span> . <span class="st0">'/service'</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">import</span><span class="br0">&#40;</span>S2BASE_PHP5_ROOT . <span class="st0">'/app/commons/dao'</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">import</span><span class="br0">&#40;</span>S2BASE_PHP5_ROOT . <span class="st0">'/app/commons/dicon/dao.dicon'</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">registerAspect</span><span class="br0">&#40;</span><span class="st0">'/Dao$/'</span>, <span class="st0">'EntityValueValidatorInterceptor'</span>, <span class="st0">'insert,update'</span><span class="br0">&#41;</span>;
S2ContainerApplicationContext::<span class="me2">registerAspect</span><span class="br0">&#40;</span><span class="st0">'/Dao$/'</span>, <span class="st0">'dao.interceptor'</span><span class="br0">&#41;</span>;
&nbsp;
<span class="kw2">?&gt;</span>
&nbsp;</pre>
    S2ContainerApplicationContext::registerAspect()を使って<br />
    正規表現でDaoという文字列で終わるクラスのinsertとupdateというメソッドに(Pointcut)<br />
    EntityValueValidatorInterceptor(Advice)を適応(Weave)しています。
</p>

<p>
    さて、せっかくなのでUnitTestを実行して、Interceptorが動作しているかどうか確かめてみましょう。<br />
    sampleプロジェクトのtest/modules/sample_module/dao/S2BasePluginDaoTest.phpを編集します。
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
<span class="kw2">class</span> S2BasePluginDaoTest <span class="kw2">extends</span> PHPUnit_Framework_TestCase <span class="br0">&#123;</span>
    <span class="kw2">private</span> <span class="re0">$module</span> = <span class="st0">'sample_module'</span>;
    <span class="kw2">private</span> <span class="re0">$container</span>;
    <span class="kw2">private</span> <span class="re0">$dao</span>;
    <span class="kw2">private</span> <span class="re0">$pdo</span>;
&nbsp;
    <span class="kw2">public</span> <span class="kw2">function</span> __construct<span class="br0">&#40;</span><span class="re0">$name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        parent::__construct<span class="br0">&#40;</span><span class="re0">$name</span><span class="br0">&#41;</span>;
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw2">public</span> <span class="kw2">function</span> testInsert<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="re0">$plugin</span> = <span class="kw2">new</span> S2BasePlugin<span class="br0">&#40;</span><span class="br0">&#41;</span>;
        try <span class="br0">&#123;</span>
            <span class="re0">$this</span>-&gt;<span class="me1">dao</span>-&gt;<span class="me1">insert</span><span class="br0">&#40;</span><span class="re0">$plugin</span><span class="br0">&#41;</span>;
            <span class="re0">$this</span>-&gt;<span class="me1">fail</span><span class="br0">&#40;</span><span class="st0">&quot;Invalid insert!&quot;</span><span class="br0">&#41;</span>;
        <span class="br0">&#125;</span> catch <span class="br0">&#40;</span>Exception <span class="re0">$e</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="br0">&#125;</span>
&nbsp;
        <span class="re0">$plugin</span>-&gt;<span class="me1">setName</span><span class="br0">&#40;</span><span class="st0">&quot;TestPlugin&quot;</span><span class="br0">&#41;</span>;
        try <span class="br0">&#123;</span>
            <span class="re0">$this</span>-&gt;<span class="me1">dao</span>-&gt;<span class="me1">insert</span><span class="br0">&#40;</span><span class="re0">$plugin</span><span class="br0">&#41;</span>;
        <span class="br0">&#125;</span> catch <span class="br0">&#40;</span>Exception <span class="re0">$e</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            <span class="re0">$this</span>-&gt;<span class="me1">fail</span><span class="br0">&#40;</span><span class="st0">&quot;Invalid insert!&quot;</span><span class="br0">&#41;</span>;
        <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw2">public</span> <span class="kw2">function</span> testUpdate<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="re0">$plugin</span> = <span class="kw2">new</span> S2BasePlugin<span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp;
        <span class="re0">$serviceResult</span> = <span class="re0">$this</span>-&gt;<span class="me1">dao</span>-&gt;<span class="me1">findAllList</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="re0">$iterator</span> = <span class="re0">$serviceResult</span>-&gt;<span class="me1">iterator</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="re0">$plugin</span> = <span class="re0">$iterator</span>-&gt;<span class="me1">current</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp;
        <span class="re0">$plugin</span>-&gt;<span class="me1">setName</span><span class="br0">&#40;</span><span class="kw2">null</span><span class="br0">&#41;</span>;
        try <span class="br0">&#123;</span>
            <span class="re0">$this</span>-&gt;<span class="me1">dao</span>-&gt;<span class="me1">update</span><span class="br0">&#40;</span><span class="re0">$plugin</span><span class="br0">&#41;</span>;
            <span class="re0">$this</span>-&gt;<span class="me1">fail</span><span class="br0">&#40;</span><span class="st0">&quot;Invalid update!&quot;</span><span class="br0">&#41;</span>;
        <span class="br0">&#125;</span> catch <span class="br0">&#40;</span>Exception <span class="re0">$e</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="br0">&#125;</span>
&nbsp;
        <span class="re0">$plugin</span>-&gt;<span class="me1">setName</span><span class="br0">&#40;</span><span class="st0">&quot;TestPlugin&quot;</span><span class="br0">&#41;</span>;
        try <span class="br0">&#123;</span>
            <span class="re0">$this</span>-&gt;<span class="me1">dao</span>-&gt;<span class="me1">update</span><span class="br0">&#40;</span><span class="re0">$plugin</span><span class="br0">&#41;</span>;
        <span class="br0">&#125;</span> catch <span class="br0">&#40;</span>Exception <span class="re0">$e</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            <span class="re0">$this</span>-&gt;<span class="me1">fail</span><span class="br0">&#40;</span><span class="st0">&quot;Invalid update!&quot;</span><span class="br0">&#41;</span>;
        <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
&nbsp;
&nbsp;
    <span class="kw2">public</span> <span class="kw2">function</span> setUp<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span>
        <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="kw2">__CLASS__</span> . <span class="st0">'::'</span> . <span class="re0">$this</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> . PHP_EOL;
        <span class="re0">$moduleDir</span> = S2BASE_PHP5_ROOT . <span class="st0">&quot;/app/modules/{$this-&gt;module}&quot;</span>;
        <span class="kw1">require_once</span><span class="br0">&#40;</span><span class="re0">$moduleDir</span> . <span class="st0">&quot;/{$this-&gt;module}.inc.php&quot;</span><span class="br0">&#41;</span>;
        <span class="re0">$this</span>-&gt;<span class="me1">container</span> = S2ContainerApplicationContext::<span class="me2">create</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="re0">$this</span>-&gt;<span class="me1">dao</span> = <span class="re0">$this</span>-&gt;<span class="me1">container</span>-&gt;<span class="me1">getComponent</span><span class="br0">&#40;</span><span class="st0">'S2BasePluginDao'</span><span class="br0">&#41;</span>;
        <span class="re0">$dataSource</span> = <span class="re0">$this</span>-&gt;<span class="me1">container</span>-&gt;<span class="me1">getComponent</span><span class="br0">&#40;</span><span class="st0">&quot;dataSource&quot;</span><span class="br0">&#41;</span>;
        <span class="re0">$this</span>-&gt;<span class="me1">pdo</span> = <span class="re0">$dataSource</span>-&gt;<span class="me1">getConnection</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="re0">$this</span>-&gt;<span class="me1">pdo</span>-&gt;<span class="me1">beginTransaction</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw2">public</span> <span class="kw2">function</span> tearDown<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <a target="_blank"  href="http://www.php.net/print"><span class="kw3">print</span></a> PHP_EOL;
        <span class="re0">$this</span>-&gt;<span class="me1">pdo</span>-&gt;<span class="me1">rollBack</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="re0">$this</span>-&gt;<span class="me1">pdo</span> = <span class="kw2">null</span>;
        <span class="re0">$this</span>-&gt;<span class="me1">container</span> = <span class="kw2">null</span>;
        <span class="re0">$this</span>-&gt;<span class="me1">dao</span> = <span class="kw2">null</span>;
    <span class="br0">&#125;</span>
&nbsp;
<span class="br0">&#125;</span>
&nbsp;
&nbsp;</pre>
    S2BasePluginDaoTest::testInsert()でinsert時の動作を、<br />
    S2BasePluginDaoTest::testUpdate()でupdate時の動作を試験しています。<br />
    では早速UnitTestを実行。
    sampleプロジェクトディレクトリ内で以下のコマンドを発行します。
<pre class="code">&nbsp;
% s2base test Dao
&nbsp;</pre>
    Daoという名前を含むTestを実行する、という意味です。<br />
    すると結果は
<pre class="code">&nbsp;
PHPUnit <span class="nu0">3.1</span><span class="nu0">.8</span> by Sebastian Bergmann.
&nbsp;
S2BasePluginDaoTest::testInsert
.S2BasePluginDaoTest::testUpdate
.
&nbsp;
Time: <span class="nu0">0</span> seconds
&nbsp;
&nbsp;
OK <span class="br0">&#40;</span><span class="nu0">2</span> tests<span class="br0">&#41;</span>
&nbsp;</pre>
    テストも完了です。
</p>

<p>
    S2Baseの基本となるmodule、Entity、Dao、Service、Interceptorを一通りなでましたので、<br />
    これでひとまずS2Baseをなでるシリーズは完結です。<br />
    S2Base2.0系から導入されたS2ContainerApplicationContextがでいい仕事をしてます。<br />
    Interceptorの適応も含めたdiconレスなコンポーネント定義で定義ファイルから開放されます。<br />
    ということで次回以降のSeasar.PHPをなでるシリーズは<br />
    S2ContainerApplicationContextをなでてみようかな、とか思っています。
</p>]]></description>
 <category>PHP</category>
<comments>http://www.azul.systems-noel.jp/index.php?itemid=74</comments>
 <pubDate>Thu, 25 Oct 2007 13:21:00 +0900</pubDate>
</item><item>
 <title><![CDATA[Entityのvalidation]]></title>
 <link>http://www.azul.systems-noel.jp/index.php?itemid=73</link>
<description><![CDATA[<p>ちょっとちらっと考えたことをメモ。</p><p>
例えばnot nullなcolumnを持つtableのEntity(S2DaoでいうところのEntity)があったとして、<br />
このEntityに対してユーザが任意にデータ入力をするとします。<br />
すると当然not nullなプロパティに値が入ってないなんてことはよくあることで<br />
こういうところはUIのvalidatorとかで制御する･･･んでしょうね、きっと一般的に。<br />
(前に使ったJSF+Spring+Hibernateではそうでした。)<br />
とすると、たくさんUIがあると当然漏れとか、あるいはtableの仕様変更があったりすると、さぁ大変ですよね。<br />
validationをすり抜けてnullのままinsertやupdateがかかったとしても、<br />
実行時例外がでて、それはそれで終了ではありますけど。
</p>

<p>
こういうvalidationってインテグレーション層で行ったほうがいいんじゃないかな、と思ったわけです。<br />
ここはZipCodeじゃないと、とかメールアドレスじゃないととかいうのは上位でvalidationすればいいわけですし<br />
そういうことなら手を煩わせるのは仕方ないと思います。<br />
S2Baseを使えばDaoやEntityは自動生成されます。<br />
ここでEntityに対して、このプロパティはnot nullですよAnnotationを自動的に付加してあげれば<br />
(仮にプロパティ名_REQUIREDというオブジェクト定数を自動生成するとします。)<br />
こんなInterceptorを使えば、例外を投げることができますよね。
<pre class="code">&nbsp;
<span class="kw2">&lt;?php</span>
<span class="coMULTI">/**
 * Validate required property of entity  
 *
 */</span>
<span class="kw2">class</span> EntityValueValidatorInterceptor <span class="kw2">extends</span> S2Container_AbstractInterceptor <span class="br0">&#123;</span>
&nbsp;
    <span class="coMULTI">/**
     * column annotation sufix
     *
     */</span>
    const COLUMN_ANNOTATION_SURFIX = <span class="st0">&quot;_COLUMN&quot;</span>;
&nbsp;
    <span class="coMULTI">/**
     * value required surfix
     * @var string
     */</span>
    const REQUIRED_ANNOTATION_SURFIX = <span class="st0">&quot;_REQUIRED&quot;</span>;
&nbsp;
    <span class="coMULTI">/**
     * Getter name prefix
     * @var string
     */</span>
    const GETTER_PREFIX = <span class="st0">&quot;get&quot;</span>;
&nbsp;
    <span class="coMULTI">/**
     * invoke Interceptor
     * @param S2Container_MethodInvocation $methodInvocation
     * @return mixed Method result
     */</span>
&nbsp;
    <span class="kw2">public</span> <span class="kw2">function</span> invoke<span class="br0">&#40;</span>S2Container_MethodInvocation <span class="re0">$methodInvocation</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        <span class="re0">$args</span> = <span class="re0">$methodInvocation</span>-&gt;<span class="me1">getArguments</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="re0">$className</span> = <span class="kw2">null</span>;
        <span class="re0">$reflectionClass</span> = <span class="kw2">null</span>;
        <span class="re0">$getterName</span> = <span class="kw2">null</span>;
        <span class="re0">$getterMethod</span> = <span class="kw2">null</span>;
        <span class="re0">$getterResult</span> = <span class="kw2">null</span>;
        <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$args</span> <span class="kw1">as</span> <span class="re0">$arg</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            <span class="re0">$className</span> = <a target="_blank"  href="http://www.php.net/get_class"><span class="kw3">get_class</span></a><span class="br0">&#40;</span><span class="re0">$arg</span><span class="br0">&#41;</span>;
            <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$className</span> != <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                <span class="re0">$reflectionClass</span>  = <span class="kw2">new</span> ReflectionClass<span class="br0">&#40;</span><span class="re0">$className</span><span class="br0">&#41;</span>;
                <span class="co1">//is entity?</span>
                <span class="kw1">if</span><span class="br0">&#40;</span><a target="_blank"  href="http://www.php.net/strpos"><span class="kw3">strpos</span></a><span class="br0">&#40;</span><span class="re0">$reflectionClass</span>-&gt;<span class="me1">getFileName</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, S2BASE_PHP5_ENTITY_DIR<span class="br0">&#41;</span> !== <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                    <span class="co1">//get props</span>
                    <span class="kw1">foreach</span><span class="br0">&#40;</span><span class="re0">$reflectionClass</span>-&gt;<span class="me1">getProperties</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw1">as</span> <span class="re0">$prop</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                        <span class="co1">//is column of table?</span>
                        <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$reflectionClass</span>-&gt;<span class="me1">hasConstant</span><span class="br0">&#40;</span><span class="re0">$prop</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> . self::<span class="me2">COLUMN_ANNOTATION_SURFIX</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                            <span class="co1">//getter exist?</span>
                            <span class="re0">$getterName</span> = self::<span class="me2">GETTER_PREFIX</span> . <span class="re0">$prop</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
                            <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$reflectionClass</span>-&gt;<span class="me1">hasMethod</span><span class="br0">&#40;</span><span class="re0">$getterName</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                                <span class="re0">$getterMethod</span> = <span class="re0">$reflectionClass</span>-&gt;<span class="me1">getMethod</span><span class="br0">&#40;</span><span class="re0">$getterName</span><span class="br0">&#41;</span>;
                                <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$getterMethod</span>-&gt;<span class="me1">isPublic</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                                    <span class="co1">//value required?</span>
                                    <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$reflectionClass</span>-&gt;<span class="me1">hasConstant</span><span class="br0">&#40;</span><span class="re0">$prop</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> . self::<span class="me2">REQUIRED_ANNOTATION_SURFIX</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                                        <span class="re0">$getterResult</span> = <span class="re0">$getterMethod</span>-&gt;<span class="me1">invoke</span><span class="br0">&#40;</span><span class="re0">$arg</span><span class="br0">&#41;</span>;
                                        <span class="co1">//value exist?</span>
                                        <span class="kw1">if</span><span class="br0">&#40;</span><span class="re0">$getterResult</span> !== <span class="nu0">0</span> &amp;&amp; <span class="re0">$getterResult</span> == <span class="kw2">null</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
                                             throw <span class="kw2">new</span> Exception<span class="br0">&#40;</span><span class="re0">$prop</span>-&gt;<span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> . <span class="st0">&quot;is required.&quot;</span><span class="br0">&#41;</span>;
                                        <span class="br0">&#125;</span>
                                    <span class="br0">&#125;</span>
                                <span class="br0">&#125;</span>
                            <span class="br0">&#125;</span>
                        <span class="br0">&#125;</span>
                    <span class="br0">&#125;</span>
                <span class="br0">&#125;</span>
            <span class="br0">&#125;</span>
        <span class="br0">&#125;</span>
&nbsp;
        <span class="re0">$ret</span> = <span class="re0">$methodInvocation</span>-&gt;<span class="me1">proceed</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
        <span class="kw1">return</span> <span class="re0">$ret</span>;
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;</pre>
後はUI側でS2BaseValueRequiredExceptionをcatchした場合にエラーメッセージなりを出すようにしてあげればよいですよね。<br />
AOPの設定もS2Base2.0系のApplicationContextを使えば、楽ちんです。
<pre class="code">&nbsp;
S2ContainerApplicationContext::<span class="me2">registerAspect</span><span class="br0">&#40;</span><span class="st0">'/Dao$/'</span>, <span class="st0">'EntityValueValidatorInterceptor'</span>, <span class="st0">'insert,update'</span><span class="br0">&#41;</span>;
&nbsp;</pre>
こんなのがあれば、少なくともUIレベルでここで値がいりますよvalidationを書く手間は省けますよね。<br />
varcharの長さとかそういうのも対称にすれば、もう少しちゃんとしたvalidationもできそうです。
</p>

<p>･･･というか実際のnot nullチェックとかってみなさんどうしてるんでしょ？＾＾；</p>
]]></description>
 <category>PHP</category>
<comments>http://www.azul.systems-noel.jp/index.php?itemid=73</comments>
 <pubDate>Fri, 19 Oct 2007 12:10:58 +0900</pubDate>
</item>
  </channel>
</rss>