创建验证规则,可以停止laravel 5.3中的其他检查

I have following rules for field named user_id.

"rules" => ["zero_to_null", "integer", "min:1", "exists:app_users,id"],

user_id is nullable, so it can be null, or 1,2,3,etc.

When user selects '0' in the browser I want to set it as null in database.

Can I make it using only rules?

So that if zero_to_null rule passes (if value equals '0'), then all other rules are not checked.

    Validator::extend("zero_to_null", function($attribute, $value, $parameters, $validator) {
        if($value === "0") {} // do something
    });

P.S. User sends in POST request 0 value and it must be set as NULL in database. The question is only about rules, not about something like setUserIdAttribute($value). Field always exists in request, so sometimes rule can not help me.

Model is validated using universal function across application.

public static function createValidatorForModel($cls, $data) {
    $rules = $cls::getFieldsRules();

    $validator = Validator::make($data, $rules);
    $validator->setAttributeNames($cls::getFieldsLabels());

    return $validator;
}

getFieldsRules returns rules for $cls

Example call:

$validator = ModelValidationHelper::createValidatorForModel(User::class, $request->all());

You should not mix the concerns like that. The validation rule should only perform validation.

If you have nullable field you can either have a null passed from via something like this or let your controller mutate the necessary data. Of course it isn't always practical to force the underlying db structure into the external input, in such cases it should be the controller's responsibility of mutating the incoming data from the expected input format to the underlying model structure.

This also means that you should not be blindly passing the result of $request->all() to your database. While the data might be validated and query parameter binding will protect your application from sql injections it will do nothing against forged requests that include more fields than you expect to handle during the specific request. The unexpected fields will also avoid any kind of validation.

Instead, your route handler (closure, controller method, etc.) should be explicit about the fields that it intends to handle:

public function action(Request $request)
{
    /* Create Validator for this action */->validate();

    $data = $request->only('fields', 'that', 'you', 'expect', 'to', 'handle');

    /* Transform $data from input format to db format */

    Model::create($data);
}

It is also worth nothing that while it's tempting to let the model dictate its own validation rules like what you're doing with the createValidatorForModel method, such approach falls apart when different actions against the model have different restrictions (e.g. admin user can edit more fields than non-admin user). Additionally, the separation of validated and expected field lists makes it harder to spot gaps in validation.