3

我有一个这样的自定义验证器设置:

Validator::extend('valid_username', 'ProfileController@valid_username');

然后我有以下处理验证的方法。它会检查用户名是否已经存在,以及用户名是否包含有效字符。

public function valid_username($attribute, $value, $parameters)
{
    $u = User::where('username', $value)->get();

    if ($u->count())
    {
        // here I would like to return "Username already taken."
        return FALSE;
    }
    else if (preg_match("/^[A-Za-z0-9@\.\-_]+$/", $value))
    {
        return TRUE;
    }
    else
    {
        // here I would like to return "Username contains invalid characters."
        return FALSE;       
    }
}

我想根据哪个错误导致验证失败来更改此验证器返回的错误消息。但是,我不知道该怎么做。在我的语言文件中,我为验证器设置了以下行:

"valid_username" => "This username is already taken or contains invalid characters."

Laravel 是否可以返回特定的错误消息?还是我必须将此验证拆分为两个自定义验证规则?在这种情况下,这可能不是问题,但特别是如果涉及数据库访问,我更愿意在一个验证器中验证检索到的 Eloquent 模型,而不是两次实例化 Eloquent 对象。

4

3 回答 3

8

查阅代码后,答案是“不开箱即用”。但是,您可以扩展所有内容并使其工作。

这个过程,我目前没有时间完全完成(对不起!),将创建一个扩展 Validator 的类,使该功能正常工作,然后使用新的 ServiceProvider 将 Laravel 替换$app['validator']为您自己的。

这个过程,更具体一点,是这样的:

<?php namespace MyLib\Validation;

class Validator extends \Illuminate\Validation\Validator {

    // Fancy validation logic to be able to set custom messages

}

然后,您需要扩展工厂以返回您的新验证器:

<?php namespace MyLib\Validation;

class Factory extends \Illuminate\Validation\Factory {

    // Change this method
    /**
     * Resolve a new Validator instance.
     *
     * @param  array  $data
     * @param  array  $rules
     * @param  array  $messages
     * @return \MyLib\Validation\Validator
     */
    protected function resolve($data, $rules, $messages)
    {
        if (is_null($this->resolver))
        {
            // THIS WILL NOW RETURN YOUR NEW SERVICE PROVIDER SINCE YOU'RE
            // IN THE MyLib\Validation NAMESPACE
            return new Validator($this->translator, $data, $rules, $messages);
        }
        else
        {
            return call_user_func($this->resolver, $this->translator, $data, $rules, $messages);
        }
    }

}

...最后,扩展 Validation 服务提供者,使用你的新工厂,然后用你自己的替换默认的 ValidationServiceProvider。

<?php namespace MyLib\Validation;

class ValidationServiceProvider extends \Illuminate\Validation\ServiceProvider {

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->registerPresenceVerifier();

        $this->app['validator'] = $this->app->share(function($app)
        {
            // THIS WILL NOW RETURN YOUR FACTORY SINCE YOU'RE
            // IN THE MyLib\Validation NAMESPACE
            $validator = new Factory($app['translator'], $app);

            // The validation presence verifier is responsible for determining the existence
            // of values in a given data collection, typically a relational database or
            // other persistent data stores. And it is used to check for uniqueness.
            if (isset($app['validation.presence']))
            {
                $validator->setPresenceVerifier($app['validation.presence']);
            }

            return $validator;
        });
    }

}

所以无论如何,这是用您自己的代码扩展验证库的一种方法。我没有解决添加您自己的消息的问题,但是如果您可以阅读核心代码并了解如何添加该功能,这将向您展示如何使其在您的应用程序中工作。

最后一点:

您可能想看看 Laravel 如何在验证规则中使用数据库“东西”处理- 虽然这可能不会影响您的应用程序(除非它变得很大!)您可能需要考虑使用某种存储库模式并在您的Validator::extend()调用中使用它User直接上课。没有必要,只是一个要检查的东西的注释。

祝你好运,不要害怕RTFC

于 2013-08-17T00:05:54.893 回答
3

unique您可以使用该规则,然后制定自己的规则来验证用户名的字符,而不是制定自己的验证规则来验证两件事(您实际上不应该这样做,一次验证一件事) 。

例如:

$rules = ['username' => 'required|username|unique:users,username'];

其中username规则是您的自定义规则,可确保它包含正确的字符。

于 2013-08-17T01:09:43.017 回答
0

也许有点“脏”,但它有效:

控制器用某些东西验证输入

$rules = array(
    'title' => 'no_collision:'.$input['project_id']
);

在验证器函数中,在返回 false 之前将消息闪烁到 Session:

//...
public function validateNoCollision($attribute, $value, $parameters)
    {
        $project = Project::find($parameters[0]);
        if($value == $project->title){
            Session::flash('colliding_message','This collides with '.$project->title($).' created by '.$project->user->name;
            return false;
        }else{
            return true;
        }
    }

在视图中执行以下操作:

@if($errors->has('title'))
    <span class="help-block">{{ Session::get('colliding_message') }}</span>
@endif
于 2013-09-07T19:47:50.687 回答