Laravel validation issue - php

I'm experiencing an issue when validator rules
return [
'features' => 'required|array',
'features.*' => 'required|string',
'link' => 'required|url',
'image' => 'nullable|file|image|mimes:jpeg,png,gif,webp|max:2048',
];
Return me an error that fields are required even if they are present.
I can't understand what causes the problem. I use identical validation for storing and it works perfectly.
Here is my controller's code
public function update(UpdateSite $request, Site $site)
{
$validatedData = $request->validated();
if ($validatedData['image']) {
Storage::delete($site->path);
$imagePath = $validatedData['image']->store('thumbnails');
$interventedImage = Image::make(Storage::url($imagePath));
$interventedImage->resize(500, null, function ($constraint) {
$constraint->aspectRatio();
});
$interventedImage->save('storage/'.$imagePath);
$site->update([
'path' => $imagePath,
]);
}
$site->update([
'site_link' => $validatedData['link'],
]);
$site->features()->delete();
if ($validatedData['features']) {
foreach ($validatedData['features'] as $feature) {
$site->features()->save(new SiteFeature(["feature" => $feature]));
}
}
return $this->response->item($site, new SiteTransformer);
}
Update #1
My route
$api->put('sites/{id}', 'SiteController#update')->where(['id' => '\d+']);

The problem lies in PHP which cannot work with multipart/form-data in PUT, PATCH request. Very curious that this problem is still present since there are in the Internet topics from about 2014.
Soulution
There is a solution in docs https://laravel.com/docs/5.6/routing#form-method-spoofing
So to update a record all I need is to use method post instead of put/patch and send an input field _method = PUT.
Just tried myself the put route was invoked.

I see the api method is PUT, but you are using Postman by form-data to request. Try to use x-www-form-urlencoded request you api.
This is about my test. Sorry for my english.

if features is an array so line two is correct but if you pass features as a string line two should be remove, this rules say validation that you have two parameter called features one of them is string and is required other also is array and required
'features' => 'required|array',
'features.*' => 'required|string',

Related

How to pass an error message without a bag in Laravel/Inertia?

I'm trying to validate some data this way:
public function update($user, array $input)
{
$v = Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
'photo' => ['nullable', 'mimes:jpg,jpeg,png', 'max:1024'],
]);
//MORE CODE
}
Then, in place of "//MORE CODE", I tried to do this:
$messagesArray = [];
foreach ($v->messages()->all() as $message) {
$messagesArray[] = $message;
}
if($v->fails()){
return redirect()->back()->withErrors($messagesArray, 'errors');
}
I tried other possibilities too (without success) like using the Request $request as a parameter but for some reason that I don't know, I'm not allowed to.
The Problem
My problem is that I'm working with a huge application where I can't work with the bag at the client-side. I need to deliver the error props as an single Object (like: {'errors' : {0:"error1", 1:"error2"...}}), but I'm delivering something like this at the moment: {'errors': {pagename:{0:"error1, 1:"error2"}}}, that is I can't pass the errors in bags.
Last Comment
I know that the Validator class has the validateWithBag() method and I wondered if there wasn't some option like validateWithoutBag()...
I already read the Laravel documentation and other questions, but... nothing
Thank you for reading it!
I solved it. the errorBags are set at the Vue Components.
For example:
this.form.post(route("user-profile-information.update"), {
errorBag: "updateProfileInformation",
preserveScroll: true,
onSuccess: () => this.clearPhotoFileInput(),
});
At this snippet, the client set the errorBag, not the server-side.
Validate Without Bag
To validate without the bag, you must change ->validateWithBag("BagName"); for ->validate(); and remove the errorBag: "BagName" at your Vue Component.

Getting the ErrorMessage Bag in Laravel Validation during Validation

As the question states. I am using the validation method where the Rules and Custom Messages are placed in the Http/Requests folder. However, I want to get the messageErrorBag in Laravel I don't have any problems if I am using the code below I can easily add my own variables to be passed together with the validator message bag.
$validatedData = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
However, if using the code below. I cannot do it since Laravel already handles the error return as per documentation.
public function store(StoreBlogPost $request)
{
// The incoming request is valid...
// Retrieve the validated input data...
$validated = $request->validated();
}
My question how can I do it? before it redirects back with the error message bag.? Is it possible
If you use StoreBlogPost in Controller , it automatically returns messages but if you want your messages in body of controller you should add validator to your controller body and use this code:
if ($validator->fails())
{
foreach ($validator->messages()->getMessages() as $field_name => $messages)
{
var_dump($messages); // messages are retrieved (publicly)
}
}
hope it helps

Api validation in laravel 5.4

Hi guys I'm working on API but I need to validate some data at backend, in this case, we only need a postman to send parameters and headers.
All is working fine now but I need more useful data in each request, Laravel has by default a Validator Form Request Validation, but I donĀ“t know how to use at API side.
I need to send the error message in JSON to Postman.
I found two options, one, make validations into a controller but seems to much code and the other make a php artisan make:request StoreObjectPost and then import the request into the controller and change the request of the store method, which one do you recommend, Ty!
You could instantiate the validator yourself like this:
$validator = Validator::make($request->all(), [
'name' => 'min:5'
]);
// then, if it fails, return the error messages in JSON format
if ($validator->fails()) {
return response()->json($validator->messages(), 200);
}
$PostData = Input::all();
$Validator = Validator::make(array(
'name' => $PostData['name']
), array(
'name' => 'required'
));
if ($Validator->fails()) { //if validator is failed
return false;
} else {
// do some thing here
}
Hope this may help you
You should override response(array $errors) method of FormRequest.
public function response(array $errors)
{
//Format your error message
if ($this->expectsJson()) {
return new JsonResponse($errors, 422);
}
return $this->redirector->to($this->getRedirectUrl())
->withInput($this->except($this->dontFlash))
->withErrors($errors, $this->errorBag);
}
I prefer the second option. We will be able to keep our controller clean that way, even when we use many validations for the data or using custom error message in the validation

Laravel 5 - Validate Multiple Request - do all Requests at the same time

Continuing discussion from here
If we have two Requests like:
public function store(FirstRequest $request, SecondRequest $request)
{ ... }
is it possible to run both Requests and not one after another. This way if validation doesn't pass for FirstRequest, SecondRequest won't start and it will create error messages only after FirstRequest passes without any errors.
I think that you can "manually creating validators"
http://laravel.com/docs/5.1/validation#other-validation-approaches
Basically in your method instead of use a a Request injection, use the rules directly in the method and call the $validator->fails() method for every set of rules.
Something like this:
public function store(Request $request){
$rulesFirstRequest = ['field1' => 'required', 'field2' => 'required'];
$rulesSecondRequest = ['field12' => 'required', 'field22' => 'required'];
$validator1 = Validator::make($request->all(), $rulesFirstRequest);
$validator2 = Validator::make($request->all(), $rulesSecondRequest);
if ($validator1->fails() && $validator2->fails()) {
//Do stuff and return with errors
}
// return with success
}
Hope it helps

How to use Laravel Input::replace() in testing POST requests

I'm having some trouble using Laravel's Input::replace() method to simulate a POST request during unit testing.
According to Jeffrey Way here and here, you can do something like this:
# app/tests/controllers/PostsControllerTest.php
public function testStore()
{
Input::replace($input = ['title' => 'My Title']);</p>
$this->mock
->shouldReceive('create')
->once()
->with($input);
$this->app->instance('Post', $this->mock);
$this->call('POST', 'posts');
$this->assertRedirectedToRoute('posts.index');
}
However, I can't get this to work. Input::all() and all Input::get() calls still return an empty array or null after Input::replace() is used.
This is my test function:
public function test_invalid_login()
{
// Make login attempt with invalid credentials
Input::replace($input = [
'email' => 'bad#email.com',
'password' => 'badpassword',
'remember' => true
]);
$this->mock->shouldReceive('logAttempt')
->once()
->with($input)
->andReturn(false);
$this->action('POST', 'SessionsController#postLogin');
// Should redirect back to login form with old input
$this->assertHasOldInput();
$this->assertRedirectedToAction('SessionsController#getLogin');
}
The $this->mock->shouldReceive() doesn't get called with $input though - it only gets an empty array. I've confirmed this in the debugger by looking at Input::all() and Input::get() for each value, and they're all empty.
TL/DR: How do I send a request with POST data in a Laravel unit test?
You should use Request::replace(), not Input::replace in order to replace input data for the current request.

Categories