Номер 1: Как я уже упоминал в своем комментарии под вопросом, то, что вы пытаетесь достичь, может быть сделано более простым способом.
Номер 2: Поскольку вы не хотите менять уже написанный код, где вы получили ->messages()
, вы можете сделать следующее. Я перечислю шаги и приведу пример кода.
- Нам нужно переопределить классы валидатора Laravel, фабрики (Validation) и провайдера ValidationService.
- В папке
App\Services
вы можетесоздайте два класса Validator
и ValidationFactory
- в
App\Providers
создайте класс ValidationServiceProvider
- Перейдите в файл
config/app.php
и в разделе providers
замените Illuminate\Validation\ValidationServiceProvider::class
на App\Providers\ValidationServiceProvider::class
Validator
Класс выглядит следующим образом:
namespace App\Services;
use Illuminate\Support\MessageBag;
use Illuminate\Validation\ValidationRuleParser;
use Illuminate\Contracts\Translation\Translator;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Illuminate\Contracts\Validation\Rule as RuleContract;
class Validator extends \Illuminate\Validation\Validator
{
/**
* @var MessageBag $all_messages
*/
protected $all_messages;
public function __construct(Translator $translator, array $data, array $rules, array $messages = [], array $customAttributes = [])
{
parent::__construct($translator, $data, $rules, $messages, $customAttributes);
$this->all_messages = new MessageBag;
$this->getAllFormattedMessages();
}
public function makeAllRulesMessages($attribute, $rule, $parameters)
{
$this->all_messages->add($attribute, $this->makeReplacements(
$this->getMessage($attribute, $rule), $attribute, $rule, $parameters
));
}
public function messages(bool $validated_rules_messages = false)
{
return $validated_rules_messages
? $this->validatedMessages()
: $this->all_messages;
}
/**
* This is here in case the true validated messages are needed
*
* @return MessageBag
*/
public function validatedMessages()
{
return parent::messages();
}
public function getAllFormattedMessages()
{
// We'll spin through each rule and add all messages to it.
foreach ($this->rules as $attribute => $rules) {
$attribute = str_replace('\.', '->', $attribute);
foreach ($rules as $rule) {
// First we will get the correct keys for the given attribute in case the field is nested in
// an array. Then we determine if the given rule accepts other field names as parameters.
// If so, we will replace any asterisks found in the parameters with the correct keys.
[$rule, $parameters] = ValidationRuleParser::parse($rule);
if (($keys = $this->getExplicitKeys($attribute)) &&
$this->dependsOnOtherFields($rule)) {
$parameters = $this->replaceAsterisksInParameters($parameters, $keys);
}
$value = $this->getValue($attribute);
if ($value instanceof UploadedFile && $this->hasRule($attribute, array_merge($this->fileRules, $this->implicitRules))
) {
$this->makeAllRulesMessages($attribute, 'uploaded', []);
} elseif ($rule instanceof RuleContract) {
$this->makeCustomRuleMessage($attribute, $rule);
} else {
$this->makeAllRulesMessages($attribute, $rule, $parameters);
}
}
}
}
/**
* @param $attribute
* @param \Illuminate\Contracts\Validation\Rule $rule $rule
*/
public function makeCustomRuleMessage($attribute, $rule)
{
$this->failedRules[$attribute][get_class($rule)] = [];
$messages = (array)$rule->message();
foreach ($messages as $message) {
$this->all_messages->add($attribute, $this->makeReplacements(
$message, $attribute, get_class($rule), []
));
}
}
}
Этот класс делает одну вещь в итоге, получить все сообщения переданных правил в$all_messages
свойство класса. Он расширяет и позволяет запустить базовый класс проверки и просто переопределяет метод messages()
, чтобы сделать все собранные правила доступными для использования.
ValidationFactory
переопределяет Illuminate\Validation\Factory
и выглядит так:
namespace App\Services;
use Illuminate\Validation\Factory;
class ValidationFactory extends Factory
{
/**
* Resolve a new Validator instance.
*
* @param array $data
* @param array $rules
* @param array $messages
* @param array $customAttributes
* @return \Illuminate\Validation\Validator
*/
protected function resolve(array $data, array $rules, array $messages, array $customAttributes)
{
if (is_null($this->resolver)) {
return new \App\Services\Validator($this->translator, $data, $rules, $messages, $customAttributes);
}
return call_user_func($this->resolver, $this->translator, $data, $rules, $messages, $customAttributes);
}
}
Этот класс делает только одну вещь, переопределяет resolve()
метод в этом классе, используя вместо этого экземпляр нашего пользовательского \App\Services\Validator
класса.
ValidationServiceProvider
расширяет Illuminate\Validation\ValidationServiceProvider
и переопределяет метод registerValidationFactory()
, и это выглядит так:
namespace App\Providers;
use App\Services\ValidationFactory;
use Illuminate\Validation\ValidationServiceProvider as BaseValidationServiceProvider;
class ValidationServiceProvider extends BaseValidationServiceProvider
{
protected function registerValidationFactory()
{
$this->app->singleton('validator', function ($app) {
$validator = new ValidationFactory($app['translator'], $app);
// The validation presence verifier is responsible for determining the existence of
// values in a given data collection which is typically a relational database or
// other persistent data stores. It is used to check for "uniqueness" as well.
if (isset($app['db'], $app['validation.presence'])) {
$validator->setPresenceVerifier($app['validation.presence']);
}
return $validator;
});
}
}
То, что делает вышеупомянутый класс, также инструктирует провайдера использовать наш App\Services\ValidationFactory
когда приложение требует одного.
И мы сделали. Все сообщения проверки будут отображаться, даже если одно из наших правил проверки не выполнено.
Предостережения
Чтобы достичь этого, нам нужно было сделать многоизменения и переопределения. За исключением действительно критических, это может свидетельствовать о том, что что-то в дизайне приложения выглядит неправильно.
Реализация проверки Laravel может измениться в будущем выпуске и, следовательно, может стать проблемой с сохранением этих изменений. другие побочные эффекты, которые могут возникнуть при переопределении реализации проверки по умолчанию в Laravel, или если все правила возвращают правильные сообщения.
Обычно вы хотите возвращать пользователю сообщения с ошибками, а не все возможные сбои.