ちょっとちらっと考えたことをメモ。
例えばnot nullなcolumnを持つtableのEntity(S2DaoでいうところのEntity)があったとして、
このEntityに対してユーザが任意にデータ入力をするとします。
すると当然not nullなプロパティに値が入ってないなんてことはよくあることで
こういうところはUIのvalidatorとかで制御する・・・んでしょうね、きっと一般的に。
(前に使ったJSF+Spring+Hibernateではそうでした。)
とすると、たくさんUIがあると当然漏れとか、あるいはtableの仕様変更があったりすると、さぁ大変ですよね。
validationをすり抜けてnullのままinsertやupdateがかかったとしても、
実行時例外がでて、それはそれで終了ではありますけど。
こういうvalidationってインテグレーション層で行ったほうがいいんじゃないかな、と思ったわけです。
ここはZipCodeじゃないと、とかメールアドレスじゃないととかいうのは上位でvalidationすればいいわけですし
そういうことなら手を煩わせるのは仕方ないと思います。
S2Baseを使えばDaoやEntityは自動生成されます。
ここでEntityに対して、このプロパティはnot nullですよAnnotationを自動的に付加してあげれば
(仮にプロパティ名_REQUIREDというオブジェクト定数を自動生成するとします。)
こんなInterceptorを使えば、例外を投げることができますよね。
<?php /** * Validate required property of entity * */ class EntityValueValidatorInterceptor extends S2Container_AbstractInterceptor { /** * column annotation sufix * */ const COLUMN_ANNOTATION_SURFIX = "_COLUMN"; /** * value required surfix * @var string */ const REQUIRED_ANNOTATION_SURFIX = "_REQUIRED"; /** * Getter name prefix * @var string */ const GETTER_PREFIX = "get"; /** * invoke Interceptor * @param S2Container_MethodInvocation $methodInvocation * @return mixed Method result */ public function invoke(S2Container_MethodInvocation $methodInvocation) { $args = $methodInvocation->getArguments(); $className = null; $reflectionClass = null; $getterName = null; $getterMethod = null; $getterResult = null; foreach($args as $arg) { $className = get_class($arg); if ($className != false) { $reflectionClass = new ReflectionClass($className); //is entity? if(strpos($reflectionClass->getFileName(), S2BASE_PHP5_ENTITY_DIR) !== false) { //get props foreach($reflectionClass->getProperties() as $prop) { //is column of table? if($reflectionClass->hasConstant($prop->getName() . self::COLUMN_ANNOTATION_SURFIX)) { //getter exist? $getterName = self::GETTER_PREFIX . $prop->getName(); if($reflectionClass->hasMethod($getterName)) { $getterMethod = $reflectionClass->getMethod($getterName); if($getterMethod->isPublic()) { //value required? if($reflectionClass->hasConstant($prop->getName() . self::REQUIRED_ANNOTATION_SURFIX)) { $getterResult = $getterMethod->invoke($arg); //value exist? if($getterResult !== 0 && $getterResult == null) { throw new Exception($prop->getName() . "is required."); } } } } } } } } } $ret = $methodInvocation->proceed(); return $ret; } }後はUI側でS2BaseValueRequiredExceptionをcatchした場合にエラーメッセージなりを出すようにしてあげればよいですよね。
AOPの設定もS2Base2.0系のApplicationContextを使えば、楽ちんです。
S2ContainerApplicationContext::registerAspect('/Dao$/', 'EntityValueValidatorInterceptor', 'insert,update');こんなのがあれば、少なくともUIレベルでここで値がいりますよvalidationを書く手間は省けますよね。
varcharの長さとかそういうのも対称にすれば、もう少しちゃんとしたvalidationもできそうです。
・・・というか実際のnot nullチェックとかってみなさんどうしてるんでしょ?^^;