laravel4: モデルでバリデーション

毎度、バリデーションのルールを書くの面倒だなーということで テーブルのスキーマに合わせて自動でバリデーションすればいいじゃん！ということで作ってみた。

```Dbwapper.php
use Illuminate\Database\Eloquent\Model as Eloquent;
use Illuminate\Config\Repository;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Validator;

abstract class Dbwapper extends Eloquent {
    public static function columns_info()
    {
        $instance = new static;
        $prefix = Config::get('database.connections.mysql.prefix');
        $table = $instance->table;
        if ( Cache::has( "$prefix$table" ) ){
            return unserialize( Cache::get( "$prefix$table" ) );
        } else {
            $info = DB::select("SHOW FULL COLUMNS FROM `$prefix$table`");
            $serialize = serialize($info);
            Cache::forever( "$prefix$table", $serialize ) ; 
            return $info ;
        }
    }
    /**
        Make validation rules
    **/
    public static function validate_rules()
    {
        $rules = array();
        $columns = static::columns_info();
        foreach ( $columns as $column ){
            $type       = $column->Type;
            $fieldname  = $column->Field;
            preg_match('/\(([0-9]{1,10})\)/', $type, $match);
            if ( $match ) $length     =  $match[1] ;
            $type       = mb_ereg_replace("\(.*?\)|（.*?）", "", $type);
            $required   = $column->Null == 'NO' 
　　　　　　　　　　　　　　　　&& strlen($column->Default) == 0 ? 'required|' : '';
            
            if ($column->Key == 'PRI' && $column->Extra == 'auto_increment'){
                // auto_increment の時は チェックしない
            } else {
                switch ($type){
                    case "int":
                        $rules[$fieldname] = "${required}integer";
                        break;
                    case "varchar":
                        switch ($fieldname) {
                            case "email" :
                                $rules[$fieldname] = "${required}email";
                                break;
                            // カラム名で何か特別なバリデーションルールがあればここに追加
                            //とりあえず Emailだけ
                            default:
                                $rules[$fieldname] = "${required}max:". $length;
                                break;
                        }
                        break;
                    case "datetime":
                        $rules[$fieldname] = "${required}match:/^\d{4}\-\d{2}\-\d{2} \d{2}\:\d{2}/";
                        break;
                    case "text":
                        $rules[$fieldname] = "${required}min:0";
                        break;
                    case "timestamp":
                        break;
                    case "longtext":
                        $rules[$fieldname] = "${required}min:0";
                        break;
                    case "tinyint":
                        $rules[$fieldname] = "${required}integer";
                        break;
                    case "float":
                        $rules[$fieldname] = "${required}numeric";
                        break;
                    case "date":
                        $rules[$fieldname] = "${required}match:/^\d{4}\-\d{2}\-\d{2}$/";
                        break;
                    default:
                        break;
                }
            }
        }
        return $rules;
    }

    /** 
        Auto Validate
    **/
    public static function validate($input=null,$rules=null)
    {
        // ルールが無い時は Schemaを元にrule作成
        if ( is_null($rules) )
        {
            $rules = static::validate_rules();
        }
        if ( is_null($input) ) $input = Input::all();
        
        // ルールにあるFIELD だけ Requestデータを取得
        $requests = array();
        foreach ($rules as $key => $val){
            if (array_key_exists($key,$input)){
                $requests[$key] = $input[$key];
            } else {
                $requests[$key] = null;
            }
        }
        return Validator::make($requests, $rules);
    }
}
```

そんで 以下の Eloquent　を

```app/models/User.php
class User extends Eloquent　{
    protected $table = 'user';
}
```

Dbwapper に変える。

```app/models/User.php
class User extends Dbwapper {
    protected $table = 'user';
}
```

Controllerで 以下の用にすれば ルールをいちいち作んなくていいかも。

```
$v = User::validate(Input::all());
if ($v->valid()) { 
// OK パターン
}
```