所以我有一个Laravel应用程序,其中有许多控制器可以处理应用程序的各个方面。
现在每个控制器都有各种方法。大多数方法都定义了验证规则,例如:
$validationArray = [
'id'=>'required|integer',
'status'=>'required|string'
];
$validator = Validator::make($request->all(),$validationArray);
if ($validator->fails()){
return Response::json(['response'=>implode(', ',$validator->messages()->all())],422);
}
现在以下行:
return Response::json(['response'=>implode(', ',$validator->messages()->all())],422);
实际上会返回验证规则的任何错误。
我的问题是:有没有办法以编程方式获取所有可能的错误消息?
当然,一种方法是按规则进行操作并手动创建列表,但是有数百种方法分散在各个控制器上。
因此,如果有人能指出我以更轻松的方式处理所有错误消息的方向,将不胜感激。
提前谢谢!
因此,为了进一步清除,我需要列出所有可能的错误,例如上面的代码,该列表将是:
['id is required', 'id must be an integer', 'status is required', 'status must be an string']
请记住,有数百种方法,而且我不想更改该方法的最终响应,而是希望拥有某种外部脚本,这些脚本可以帮助我获取错误消息而又不会过多地干扰控制器。
答案 0 :(得分:3)
为此,您必须扩展sklearn
类并编写一个将迭代所有规则并显式添加错误消息的方法,就像它们失败一样。
首先,创建一个新文件Validator
:
app\Http\Custom\Validator.php
接下来,让我们在验证工厂中注册此类:
<?php
namespace App\Http\Custom;
use Illuminate\Contracts\Validation\Rule as RuleContract;
use Illuminate\Support\MessageBag;
use Illuminate\Validation\ValidationRuleParser;
use Illuminate\Validation\Validator as BaseValidator;
class Validator extends BaseValidator {
/** @var MessageBag */
protected $errorMessages;
/** @var array */
protected $hasExplicitFileErrorMessage;
protected $explicitFileRules = [
'File', 'Image', 'Mimes', 'Mimetypes', 'Dimensions',
];
function availableErrors()
{
$this->errorMessages = new MessageBag();
$this->hasExplicitFileErrorMessage = [];
foreach($this->rules as $attribute => $rules) {
$attribute = str_replace('\.', '->', $attribute);
foreach($rules as $rule) {
[$rule, $parameters] = ValidationRuleParser::parse($rule);
if($rule == '') {
continue;
}
if(($keys = $this->getExplicitKeys($attribute)) &&
$this->dependsOnOtherFields($rule)) {
$parameters = $this->replaceAsterisksInParameters($parameters, $keys);
}
// explicitly add "failed to upload" error
if($this->hasRule($attribute, $this->explicitFileRules) && !in_array($attribute, $this->hasExplicitFileErrorMessage)) {
$this->addFailureMessage($attribute, 'uploaded', []);
$this->hasExplicitFileErrorMessage[] = $attribute;
}
if($rule instanceof RuleContract) {
$messages = $rule->message() ? (array)$rule->message() : [get_class($rule)];
foreach($messages as $message) {
$this->addFailureMessage($attribute, get_class($rule), [], $message);
}
} else {
$this->addFailureMessage($attribute, $rule, $parameters);
}
}
}
return $this->errorMessages->all();
}
function addFailureMessage($attribute, $rule, $parameters = [], $rawMessage = null)
{
$this->errorMessages->add($attribute, $this->makeReplacements(
$rawMessage ?? $this->getMessage($attribute, $rule), $attribute, $rule, $parameters
));
}
// we have to override this method since file-type errors depends on data value rather than rule type
protected function getAttributeType($attribute)
{
if($this->hasRule($attribute, $this->explicitFileRules)) {
return 'file';
}
return parent::getAttributeType($attribute);
}
}
然后...仅此而已。让我们测试一下:
<?php
namespace App\Providers;
use App\Http\Custom\Validator; // <-- our custom validator
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider {
public function boot()
{
app('validator')->resolver(function ($translator, $data, $rules, $messages) {
return new Validator($translator, $data, $rules, $messages);
});
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class HomeController extends Controller {
function index(Request $request)
{
$rules = [
'id' => 'required|int|between:2,10',
'status' => 'required_with:nonexisting|string|email',
'avatar' => 'required|file|mimes:png|max:1000',
'company' => 'required_without:id|unique:companies,id'
];
$validator = Validator::make([], $rules);
dump($validator->availableErrors());
}
}
答案 1 :(得分:1)
虽然不漂亮,但这是我的镜头:
$validationArray = [
'id'=>'required|integer',
'status'=>'required|string'
];
$validator = Validator::make($request->all(), $validationArray);
if ($validator->fails()) {
$messages = [];
$invalid_fields = array_keys($validator->messages()->toArray());
$rules = $v->getRules();
foreach($invalid_fields as $invalid_field) {
foreach($rules[$invalid_field] as $rule) {
if(str_contains($rule, ':') {
// complex rules that have parameters (min, between, size, format)
// are more difficult to work with. I haven't figured out how to do them yet
// but you should get the idea.
continue;
} else {
$messages[] = str_replace(':attribute', $invalid_field, $validator->getTranslator()->get("validation.$rule"));
}
}
}
return Response::json(['response' => implode(', ', $messages)], 422);
}
答案 2 :(得分:1)
数字1:就像我在问题下的评论中提到的那样,您要实现的目标可以通过更简单的方式完成。
数字2:由于您不想更改已获得->messages()
的已编写代码,因此可以执行以下操作。我将列出这些步骤并提供示例代码。
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的默认验证实现,或者所有规则是否返回正确的消息。
通常,您只想将失败的验证消息返回给用户,而不是所有可能的失败。
答案 3 :(得分:0)
我认为,您应该实现https://laravel.com/docs/5.8/validation#form-request-validation。
这将帮助您更好地实施投注。
答案 4 :(得分:0)
我认为函数failed()
(获取失败的验证规则)或errors()
(获取验证者的消息容器)可能会对您有所帮助。如果没有,请转到apply_async
,希望您找到所需的功能。
答案 5 :(得分:0)
我认为您正在寻找一种具有自定义错误消息的方法。如果是这种情况,那么答案是这样的:
$messages = [
'id.required' => 'id is required',
'id.integer' => 'id must be an integer',
'status.required' => 'status is required',
'status.string'=> 'status must be an string'
];
$validationArray = [
'id'=>'required|integer',
'status'=>'required|string'
];
$validator = Validator::make($request->all(),$validationArray, $messages);
更多信息,您可以找到here。
我希望这是您正在寻找的东西,我的回答会为您提供帮助:)
答案 6 :(得分:0)
根据Laravel表单验证程序,您可以通过以下方式编写语句:
$validationArray = [
'id'=>'required|integer',
'status'=>'required|string'
];
$validator = Validator::make($request->all(),$validationArray);
if ($validator->fails()){
return Response::json(['response'=> validator->errors())],422);
}
errors()方法将所有错误作为关联数组返回,在该数组中,消息将与字段名称相应地关联,这就是获取错误的方式。