在写入数据库之前,需要对数据进行验证,比如type-check的每个模型列的定义('type'这一列必须是enum('card','loan')),在这里使用模型事件来完成。在EventServiceProvider中写入(或者自定义一个ValidationServiceProvider):publicfunctionboot(){/***Inspiredby@see\Illuminate\Foundation\Providers\FormRequestServiceProvider::boot()**注意:保存事件总是在创建和更新之前触发事件*/$this->app['events']->listen('eloquent.saving:*',function(string$event_name,array$data):void{/**@var\App\Extensions\Illuminate\Database\Eloquent\Model$object*/$object=$data[0];$object->validate();});}'eloquent.saving:*'为listen所有模型的保存,即任意模型的写操作将触发此事件。然后写一个抽象模型扩展EloquentModel://\App\Extensions\Illuminate\Database\Eloquent\ModeluseIlluminate\Database\Eloquent\ModelasEloquentModel;useIlluminate\Validation\ValidationException;abstractclassModelextendsEloquentModel{publicfunctionvalidate():void{//1.验证类型规则(类型检查)$validator=$this->getTypeValidator();如果($validator->fails()){thrownewValidationException($validator);}//$validator=$this->getConstraintValidator();//2.验证约束规则(完整性检查)}protectedfunctiongetTypeValidator(){return$this->getValidationFactory()->make($this->attributes,static::COLUMN_TYPE_RULES);}protectedfunctiongetValidationFactory(){returnapp(Factory::class);}protectedfunctiongetConstraintValidator(){//返回$this->getValidationFactory()->make($attributes,static::COLUMN_CONSTRAINT_RULES);这样,在每个继承抽象模型的子类中,定义constCOLUMN_TYPE_RULES即可,如:classAccountextendsModel{publicconstCOLUMN_TYPE_RULES=['id'=>'integer|between:0,4294967295','source'=>'nullable|in:schwab,orion,yodlee','type'=>'required|in:bank,card,loan',];}在写入操作期间,类型检查每个的模式定义提前建模以避免无效碰撞。数据库特性的目的是从模型模式中验证输入数据的字段定义是否合法。此外,除了类型检查模式定义外,还必须根据业务需要对完整性检查约束规则进行逻辑检查。比如创建账号时,输入框的person_id不能是未成年儿童等等。这里的业务不同,约束规则也不同,就不过多解释了。此功能的目的是从逻辑上验证输入数据的有效性。OK,一般情况下,写入数据库前需要进行模型校验,避免无效命中db。
