2013-08-02 1 views
3

У меня есть валидатор настройка так:Возможно ли изменить сообщение об ошибке в обратном вызове Laravel's Validator?

Validator::extend('valid_username', '[email protected]_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("/^[[email protected]\.\-_]+$/", $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 дважды.

+0

У меня такая же проблема. У меня есть специальный валидатор, который использует некоторую сложную логику разбора, чтобы определить, действителен ли вход. Сообщение об ошибке должно быть конкретно, что было неправильно, потому что «Анализ не удалось» бесполезен. Я хочу, чтобы валидатор мог вернуть строку вместо true/false. – takteek

+0

Да, именно то, что мне тоже хотелось бы. Это можно было сделать в CodeIgniter. Но я еще не нашел способ сделать это в Laravel :( – santacruz

ответ

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); 
     } 
    } 

} 

... и, наконец, распространите поставщика услуг проверки, используйте свой новый завод и замените его 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 ручки с помощью Database "stuff" within validation rules Хотя это не может повлиять на ваше приложение, вы можете рассмотреть возможность использования Repository pattern какой-то и используя это в вашем вызове Validator::extend() вместо класса User. Не нужно, просто записка, чтобы что-то проверить.

Удачи и не бойтесь RTFC!

+0

Я должен упомянуть, что это хорошо, если вам нужно создать правило проверки, которое может возвращать различные сообщения проверки в зависимости от значения, которое вы не можете сделать из окна теперь. Пользовательские сообщения о проверке - это то, что вы можете получить из коробки, но оно ограничено и не может быть выполнено в вашем вызове 'Validator :: extend()'. – fideloper

+0

hey @fideloper, это действительно похоже на вас знать, о чем вы говорите;) спасибо за подробный ответ! я совсем не боюсь RTFC, но я думаю, что это может быть излишним и слишком трудоемким в это время и размером приложения. поэтому я пока займусь решением KISSable. если мне когда-либо понадобится масштабировать и настроить валидатор, это, безусловно, будет полезно. еще раз спасибо! – santacruz

3

Вместо того, чтобы создавать собственное правило проверки, которое проверяет две вещи (которые вы не должны делать, проверяйте одну вещь за раз), вы можете использовать правило unique, а затем создать собственное правило, которое проверяет символы Имя пользователя.

Например:

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

Где username правило пользовательское правило, которое гарантирует, что он содержит правильные символы.

+1

+1, для решения [KISSable] (http://en.wikipedia.org/wiki/KISS_principle). – fideloper

+0

он не совсем решает мою проблему с чередованием вывода сообщения, но я согласен с тем, что имеет смысл разделить его и использовать в этом случае уникальное правило валидации. спасибо, Джейсон! – santacruz

0

Может быть, немного «грязный», но это работает:

Контроллер проверяет вход с чем-то

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

В функции валидатор вспышки сообщение на сессии перед возвращением ложным:

//... 
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 

 Смежные вопросы

  • Нет связанных вопросов^_^