[s2container-php5:86] Re: 【質問】s2dao.php5に関して2点(PRADO連携・update)

Yusuke Hata [E-MAIL ADDRESS DELETED]
2007年 3月 14日 (水) 01:40:24 JST


ハタです。
すいません、ウソっぱち書いてました。

S2Dao_DBMetaDataFactoryがロードできないクラスのロードを行う件についてですが
class_exists('class', false)だと__autoloadの読み込みは行われないんですね。。。
事前にrequireするのは変なので(?)、当面の対応として

        if(strcasecmp($dbmd, 'S2Dao_MySQLDBMetaData') === 0){
            return new S2Dao_StandardDBMetaData($db, $dbms);
        } else if(class_exists($dbmd)){
            return new $dbmd($db, $dbms);
        }
        return new S2Dao_StandardDBMetaData($db, $dbms);

として修正しました。
本来ならどこかにマッピングをする必要があると思いますので
S2Daoとしてロードできる部分はどこかでマッピングしようと思います。
また、autoloadでrequireする場合もクラスの存在チェックを行ってもらうように
ドキュメントの一部に記述しておきます。

ex)
function __autoload($className){
    // exists for...
    if(class_exists($className, false) || interface_exists($className, false)){
        // S2ContainerClassLoader::load($className);
        // XXX
        require $className . '.class.php';
    }
}

以上です。

On Tue, 13 Mar 2007 00:29:14 +0900
Yusuke Hata <[E-MAIL ADDRESS DELETED]> wrote:

> ハタです。こんばんわ
> 
> まず、S2Dao_DBMetaDataFactoryのclass_exists($dbmd)は
> class_exists($dbmd, false)が正解でした。
> こちらは私の修正ミスで、本来ならば存在しないクラスのロードは行わないよ
> うに実装すべき点でした。(修正しておきます)
> 
> また、本来PDOはMySQLドライバ実装の動きをしますが(getColumnMetaなどにつ
> いて)、それの実装がされていないPDOドライバOracleやSybaseなどと互換を持
> つために用意しているのが DBMetaDataインタフェースになっています。
> 
> なので、MySQLについてはS2Dao_StandardDbMetaDataクラスで実装していると
> おりで問題がないハズです。この件についてはclass_exists($dbmd, false)と
> して、 MySQLではS2Dao_StandardDbMetaDataを使うようにしてください。
> # 私の怠慢でドキュメントに残していない部分が多いですねorz
> 
> そして
> > S2Dao_NotSingleRowUpdatedRuntimeException
> > Description
> > Target for update must be single row(actual:0).(ProductEntity)
> 
> これはMySQL以外でもおこりゆる更新が行われなかった場合の例外なのですが
> この件については、どう対応するかは "実装次第" となると思います。
> 
> 更新が行われなかった際にfalseを返すとか、更新されなかったので0
> (integer)を返すというのは更新されている状態(値)が判別しにくいため、
> DAOの例外として上記どおりの実装になっています。 (本家Javaも同じ実装)
> 
> で、この例外をどのように扱うかの一実装として
> S2DaoAssertAtLeastOneRowInterceptorがあげられます。
> org.seasar.dao.interceptorsのパッケージにあるのですが上記のinterceptor
> は更新結果が1件未満の場合に例外を発生させるもの(今回の例外実装と同じ)
> です。
> 
> もし、更新がなくとも処理は継続したい && try/catchを含めないとするなら
> ば、上記のようにinterceptor内で綴じ込めてしまうのも1つの実装パターンと
> 思います。
> 
> また、上記のようなinterceptorを含むdiconの記述例は以下になります。
> <components>
>     <component class="EmployeeDao">
>         <aspect>
>             <component class="S2DaoInterceptor">
>                 <aspect>
>                     <component
> class="S2DaoAssertAtLeastOneRowInterceptor" /> </aspect>
>             </component>
>         </aspect>
>     </component>
> </components>
> 
> ということで、投げやりですがDAOの実装として更新がなかった場合の実装は
> アプリ任せてしまう他、ないものと考えています。
> 
> 以上です。よろしくお願いします。
> 
> On Mon, 12 Mar 2007 23:08:08 +0900
> "Yoshinari Ueyama" <[E-MAIL ADDRESS DELETED]> wrote:
> 
> > 植山です。
> > 週末にPHPでのプログラミングを楽しんだのですが、その際に発生したこと
> > に関して2点ほど質問があります。いろいろとご意見をお聞かせください。
> > 
> > 1.Mysqlでのupdate処理
> > 
> > 今までSQLITEのみで作業をしていたのは片手落ち、MysqlでのDB操作も試さ
> > ねば・・・と思い、 MYSQLを用いたS2Daoプログラミングを行っていくと、
> > 下記のようなエラーが発生しました。
> > 
> > S2Dao_NotSingleRowUpdatedRuntimeException
> > Description
> > Target for update must be single row(actual:0).(ProductEntity)
> > 
> > データの編集画面において、データを変更せずにdaoのupdate($entity)メ
> > ソッドを実行した際に発生することがわかり、 おそらく下記の挙動が原因
> > だと推測しています。
> > 
> > -------------------------------------------------------------------------------------------------------------------------------
> > http://dev.mysql.com/doc/refman/4.1/ja/update.html
> > カラムの値がそのカラムの現在の値に設定される場合、MySQL はそれが現在
> > の値であることを認識し、更新処理を行いません。
> > -------------------------------------------------------------------------------------------------------------------------------
> > 
> > これは、本来どのように対処すべきなのでしょうか?
> > 1)画面入力値チェックの一環としてデータが変更されていないことを確認
> > し、変更されていなければupdate処理を実行しない。
> > 2)エラーが発生しないようにS2Daoの修正を行う。
> > 
> > 2)S2Dao_MySQLDBMetaDataクラスについて
> > 
> > S2Base.PHP5のPRADO pluginとS2Dao.PHP5を用いたプログラムを実行したと
> > ころ、下記のようなエラーが発生しました。
> > 
> > S2Dao_SQLRuntimeException
> > 
> > Description
> > SQLException occured, because [Warning]
> > PradoBase::include_once(S2Dao_MySQLDBMetaData.php)
> > [<a
> > href='function.PradoBase-include-once'>function.PradoBase-include-once
> > </a>]: failed to open stream: No such file or directory
> > (@line 98 in file
> > /private/var/www/public_html/prado/framework/PradoBase.php).
> > 
> > これは、S2Dao_DBMetaDataFactoryの下記の処理実行時に
> > class S2Dao_DBMetaDataFactory {
> > 
> >     const DBMetaData_Suffix = 'DBMetaData';
> > 
> >     public static function create(PDO $db, S2Dao_Dbms $dbms){
> >         $dbmd = get_class($dbms) . self::DBMetaData_Suffix;
> >         if(class_exists($dbmd)){
> >             return new $dbmd($db, $dbms);
> >         }
> >         return new S2Dao_StandardDBMetaData($db, $dbms);
> >     }
> > }
> > 
> > S2Dao_MySQLDBMetaDataクラスをロードする必要が出てきて、
> > 
> > PradoBaseクラスの下記メソッドが実行された際に
> >     public static function autoload($className)
> >     {
> >         include_once($className.self::CLASS_FILE_EXT);
> >         if(!class_exists($className,false) &&
> > !interface_exists($className,false))
> >             self::fatalError("Class file for '$className' cannot be
> > found.");
> >     }
> > 
> > S2Dao_MySQLDBMetaData.phpが存在していないために発生したと推測してい
> > ます。(あまり深くソースを追ってませんが・・)
> > 
> > 今は、S2Dao_MySQLDBMetaDataを継承しただけのS2Dao_MySQLDBMetaDataクラ
> > スが定義された S2Dao_MySQLDBMetaData.class.phpを作成し、エラーが発生
> > しないようにしましたが、本来はどのように対処すべきでしょうか?
> > 
> > 以上です。
> > 
> 
> 
> -- 
> Yusuke Hata <[E-MAIL ADDRESS DELETED]>
> blog: http://blog.xole.net/
> _______________________________________________
> S2Container-PHP5 mailing list
> [E-MAIL ADDRESS DELETED]
> https://ml.seasar.org/mailman/listinfo/s2container-php5


-- 
Yusuke Hata <[E-MAIL ADDRESS DELETED]>
blog: http://blog.xole.net/


S2Container-PHP5 メーリングリストの案内