Laravel 5.3 - Custom validators - php

I have this validator for input called "name":
Regex:/^[A-Za-z0-9\\s\\-\\/,.]*$/|min:5|max:50
But, I want to use this validator in multiple forms in my website.
How can i do this without to copy this validator in all the forms validations?
My database contains table called "settings", every row presents setting of the website. Each setting contain Json code that save the setting data.
I want to create custom validator that check if the input value equals to one of the values in the Json code in my database.
I have Json code like this:
[{"US":"United States", "UK":"United Kingdom"}]
And I want to check if the value of the input equals to one of the values in the Json code. How can I do this?

I know you said, across your website. However, I would think that you're ensuring that the use of forms using the same validators are relatively within the same state.
Here's an example that helped me get to where I needed to be! I hope it serves as a good enough guide!:
MessageBag documentation here: http://laravel.com/docs/5.0/validation#error-messages-and-views
public function postLogin(Request $request)
public function postLogin(Request $request)
{
$validator = Validator::make($request->all(), [
'email' => 'required|email', 'password' => 'required',
]);
if ($validator->fails())
{
return redirect($this->loginPath())->withErrors($validator, 'loginErrors');
}
$credentials = $this->getCredentials($request);
if (Auth::attempt($credentials, $request->has('remember'))) {
return redirect()->intended($this->redirectPath());
}
return redirect($this->loginPath())
->withInput($request->only('email', 'remember'))
->withErrors([
'email' => $this->getFailedLoginMessage(),
], 'loginErrors');
}
Now you can look for errors inside of your view:
#if (!$errors->loginErrors->isEmpty())
<div class="form_error_login">
<strong>Whoops!</strong> There were some problems with your input.<br> <br>
<ul>
#foreach ($errors->loginErrors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
For the Modals (if you use them):
<script>
$findError = $('div').find ('div');
if ( $findError.hasClass('form_error_login')){
$('#modalLogin').foundation('reveal', 'open');
}
if ( $findError.hasClass('form_error_register')){
$('#modalRegister').foundation('reveal', 'open');
}
</script>
Reference:
https://laracasts.com/discuss/channels/laravel/authcontroller-loginregistration-on-same-page

Related

How to populate the fields from HTML form in Laravel?

I am working on building a form in which I want to populate the fields coming from form (which I have named posting.blade.php)
The controller which I have used for that is:
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required',
'email' => 'required|email',
'number' => 'required',
'city' => 'required',
'post' => 'required'
]);
Mail::send('emails.posting-message', [
'msg'=> $request->message
], function($mail) use($request) {
$mail->from($request->email, $request->name);
$mail->to('helloworld#gmail.com')->subject('Contact Message');
});
return redirect()->back()->with('flash_message', 'Thank you for your message');
}
Problem Statement:
The current controller doesn't return anything as in the line 'msg'=> $request->message there is no message in validate. But if I use
'msg'=> $request->name (It returns name)
I am wondering what changes I should make in the controller so that it return every field present in the validate.
I tried with this but its only returning the last value which is post.
'msg'=> $request->name,
'msg'=> $request->email,
'msg'=> $request->number,
'msg'=> $request->city,
'msg'=> $request->post
First, you need to add ->withInput() to your redirect:
return redirect()->back()->with('flash_message', 'Thank you for your message')->withInput();
This will flash all submitted form fields to the session.
After the redirect, to get the value of a form field with the name of title for example, you can use the old() helper, such as:
<input type="text" name="title" value="{{ old('title') }}">
You can also pass a second parameter to the helper:
<input type="text" name="title" value="{{ old('title', $post->title) }}">
You get the idea.
It sounds like what you are trying to do is take all of the inputs from a form submission and pass them to a Laravel blade template called posting-message that is being used to build an email.
If my understanding is correct, then you are almost there - this just requires you to pass more variables through to your email blade template. At the moment, you are just passing through one variable called msg.
So the Mail section of your controller becomes something like:
Mail::send('emails.posting-message', [
'name'=> $request->name,
'email'=> $request->email,
'number'=> $request->number,
'city'=> $request->city,
'post'=> $request->post
], function($mail) use($request) {
$mail->from($request->email, $request->name);
$mail->to('helloworld#gmail.com')->subject('Contact Message');
});
Then in your email blade template you have access to the variables like {{ $name }}, {{ $email }} and so on.
p.s.
If you wanted to get all the inputs and put them in an array in one go in your controller, Laravel provides some ways of retrieving inputs in bulk, e.g.:
$allInputs = $request->all();
p.p.s. Consider doing more validation than just required for each of your form inputs, to ensure the data supplied from your user is what you are expecting and not malicious or incorrect.
First thing you need to check the field name in your html that its exact message no spaces or sort of misspelled.
Second thing Check all the post fields using
$request->all(); And see whether you get the "message" index in the post array or not.
There is nothing like if you have not added the field in the validation so you will not get it in the POST.
But as you are working with contact form you should keep the "message" field mandatory and should add it in validation. That way you will always get some data in the message field.
Can you please post the html also in the question so everyone will get more idea about it.
For the other issue about sending the data you already getting to the mail template you can use the below approach
$msg = array('name' => $request->name,'email' => $request->email,'number' => $request->number,'city' => $request->city,'post' => $request->post,'message'=>$request->message);
You can than use the array like
Mail::send('emails.posting-message', [$msg
], function($mail) use($request) {
$mail->from($request->email, $request->name);
$mail->to('helloworld#gmail.com')->subject('Contact Message');
});
Then you can easily access all the variables in the mail template to make it dynamic.
The snippet you have provided as below:
'msg'=> $request->name,
'msg'=> $request->email,
'msg'=> $request->number,
'msg'=> $request->city,
'msg'=> $request->post
Indicates that the array key msg is being overwritten 4 times.
You would want the following approach instead:
$msg['name'] = $request->name;
$msg['email'] = $request->email;
$msg['number'] = $request->number;
$msg['city'] = $request->city;
$msg['post'] = $request->post;
First of all, you don't need to use the back method with redirect, back() function will redirect users anyway.
return back()->with('key','Val');
Check this out: Old Input
As others said, To send query strings/Inputs to the cookies use withInput() function according to the documantions it will flash all current inputs:
return back()->with('key','Val')->withInput();
If you had seen Laravel's default register and login blades, You would have known that you could use old() helper to get previous values based on cookies and sessions.
'msg'=> $request->name,
'msg'=> $request->email,
'msg'=> $request->number,
'msg'=> $request->city,
'msg'=> $request->post
To assign a value to an array there are some ways, But remember never override them like this!
You could use the auto indexing method, If you use $msg[] = $request->bar, It will index values from 0 to the length of your assignments
$data[] = $request->val1;
$data[] = $request->val2;
...
But also you could determine each element's key like this:
$data['name'] = $request->name;
$data['email'] = $request->email;
...
After all, if you want to send all Inputs as second paramter just use $request->all():
Mail::send('emails.posting-message', $request->all(), function($mail) use($request) {
$mail->from($request->email, $request->name);
$mail->to('helloworld#gmail.com')->subject('Contact Message');
});
I have face similar problem some time ago, and after several tries I changed fieldname from message to comments and it was the solution.
I suspect that message maybe a variable name used by the framework in sessions or something like that.
I hope it helps.
yo need to add the withInput() method in your returned response as
return redirect()->back()->with('flash_message', 'Thank you for your message')->withInput();
to keep input from one request during the next request you need to use old() helper. Check the documention here https://laravel.com/docs/5.6/requests#old-input
<input type="text" name="title" value="{{ old('username') }}">
Laravel will automatically redirect the user back to their previous location. In addition, all of the validation errors will automatically be flashed to the session.Check the docs here https://laravel.com/docs/5.6/validation#quick-displaying-the-validation-errors. To display validation error message you can use like this
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
or more specifically
<input type="text" name="title" value="{{ old('username') }}">
<span class="error">{{$error->title}}</span>
As i understand it, you're asking how to send the inputs to the mail template.
try this;
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required',
'email' => 'required|email',
'number' => 'required',
'city' => 'required',
'post' => 'required'
]);
Mail::send('emails.posting-message', $request->all(), function($mail) use($request) {
$mail->from($request->email, $request->name);
$mail->to('helloworld#gmail.com')->subject('Contact Message');
});
return redirect()->back()->with('flash_message', 'Thank you for your message');
}
now in the emails/posting-message.blade.php you will have access to $name, $email, $number, $city, $post and any other input you sent in the request.
now if you want to recover the errors of the validation. use this
$validator = Validator::make($request->all(), [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
if ($validator->fails()) {
//you can get the errors with $validator->errors. and redirect/mail as you want.
}
//here the inputs are valid.

Do you know why the named bag messages are not appearing?

I have a page that has a form with a select menu and if there are some validation errors in that form the validation errors are shown using "#include('includes.errors')". But in this same page I have a button that when the user clicks in it it shows a modal where the user can introduce a subject, a message to send an email. In this modal I also have "#include('includes.errors')".
Issue: So the issue is that if there are validation errors in the form in the modal because the subject or messare were not filled by the user that errors appear on the modal but also on the same page above the form that has the select menu. Also if there are some validation errors in the form that has the select menu and the user opens the modal that validation erros also appear in the modal.
To fix this issue using named bags is not working. For example in the storeQuantities() there is:
public function storeQuantities(Request $request, $id, $slug = null)
{
$validator = $request->validate([
'rtypes' => ['required', 'array', new RegistrationTypeQuantity],
]);
// dd('test'); dont shows
if ($validator->fails())
{
return redirect()->back()->withErrors($validator, 'quantitiesError');
}
...
}
In the contactOrganizer:
public function contactOrganizer($id, Request $request)
$validator = $this->validate($request, $rules, $customMessages);
// dd('test'); dont shows
if ($validator->fails())
{
return redirect()->back()->withErrors($validator, 'contactErrors');
}
}
And then use:
#include('includes.errors', ['errors' => $errors->quantitiesError])
And in the modal:
#include('includes.errors', ['errors' => $errors->contactErrors])
But its not working it appears always that the bag is empty in both cases with "{{dump($errors->contactErrors)}}" and "{{dump($errors->quantitiesError)}}" like:
"MessageBag {#336 ▼
#messages: []
#format: ":message"
}"
It seems that the issue is because there is some error in "$validator = $this->validate($request, $rules, $customMessages);", any code after this line like "dd('test);" dont appears.
Laravel will automatically redirect the user back to their previous location when $this->validate is used
You need to use Validator::make instead Manually Creating Validators
$validator = Validator::make($request->all(), [
'rtypes' => ['required', 'array', new RegistrationTypeQuantity],
]);
if ($validator->fails())
// redirect with errors
}
And don't forger to include use Validator;

Laravel validation with Bootstrap Modal

I've included this Github script to make a validation form with Bootstrap Modal everything is set up correctly but when I included this script the form don't submit because there are some errors which is good but it doesn't show them in the view
Controller
$this->validate($request, [
'nom' => 'required|unique:filieres'
]);
View
#if($errors->get('nom'))
#foreach($errors->get('nom') as $error)
<li class="has-error">{{$error}}</li>
#endforeach
#endif
can you just type this code in your view file
#include('includes.form_error')
second type this in your controller
public function store(UsersRequest $request)
{
}
and you create UserRequest file in Requests folder and type this
public function rules()
{
return [
'name' => 'required',
];
}
after you got proper error

How to get validated data from Validator instance in Laravel?

I manually created a Validator, but i can't find a method to get the validated data.
For Request, validated data return from $request->validate([...])
For FormRequest, it's return from $formRequest->validated()
But with Validator, i don't see a method like those 2 above.
Assuming that you're using Validator facade:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), $rules, $messages, $attributes);
if ($validator->fails()) {
return $validator->errors();
}
//If validation passes, return valid fields
return $validator->valid();
https://laravel.com/api/5.5/Illuminate/Validation/Validator.html#method_valid
If you use the Validator facade with make it will return a validator instance. This validator instance has methods like validate(), fails() and so on. You can look those methods up in the validator class or in the laravel api-documentation.
Writing The Validation Logic
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// The blog post is valid...
}
Displaying The Validation Errors
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
<!-- Create Post Form -->

laravel validate with user function

blade.php
......
<tr>
<td>{{ Form::label('cameraMac', 'Mac: ') }}</td>
<td>{{ Form::text('cameraMac')}}</td>
</tr>
......
controller.php
$data = Input::all();
function transform($cameraMac) {
return strtoupper($cameraMac);
}
//validation here
$user = User::find($data['user_id']);
if($data["cameraMac"])
{
$user->camera_id = transform($data["cameraMac"]);
Cloud_camera::create(['id' => transform($data["cameraMac"]), 'user_id' => $user->id]);
}
$user->save();
I need to transform the cameraMac to primary key to store in db. How can I use function transform() in the validation rule 'nullable|unique:cloud_cameras,id|size:6'. That's to say, how can I call this function in the validation process.
If you need to somehow transform the input data you can use the merge method:
Input::merge(['cameraMac' => transform(Input::get('cameraMac')]);
$this->validate(Input::getFacadeRoot(), [
'cameraMac' => 'nullable|unique:cloud_cameras,id|size:6'
]);
As a personal preference I would instead type-hint Illuminate\Http\Request $request in the controller method and then
$request->merge(['cameraMac' => transform($request->cameraMac)]);
$this->validate($request, ['cameraMac' => 'nullable|unique:cloud_cameras,id|size:6'
]);
I'd consider defining a middleware.
The middleware will perform the transformation and merge the result back to the request before hitting the controller.
class TransformId {
public function handle(Request $request, Closure $next) {
// shout out to #alepeino
$request->merge(['cameraMac' => transform($request->cameraMac)]);
return $next($request);
}
}
Are you shure, that you want the field cameraMac be nullable as a (more or less) primary key?
You should also use the int validation for using the size validation.
The third parameter of unique validation is the except which will ignore the given ID.
Your validation in the controller could look like this
$except_id = $request->input('cameraMac', null);
$this->validate($request, [
'cameraMac' => 'nullable|unique:cloud_cameras,id,'.$except_id.'|int|size:6'
]);
One example how you can show errors of your validation in the views will be this
#if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
For now I trans the input data first, then validate it in the below way.
But I'm looking a way to call this funciton in the validation.
$data = Input::all();
$data['cameraMac'] = transform($data['cameraMac']);
$rules = array(
'id' => 'required|unique:cloud_printers,id|size:6',
'cameraMac' => 'unique:cloud_cameras,id|size:6',
);
$validator = Validator::make($data, $rules);
if ($validator->fails())
return Redirect::back()->withInput()->withErrors($validator);
You can define a custom validation rule:
Validator::extend('transformUpper', function ($attribute, $value, $parameters, $validator) {
return strtoupper($value);
});
Then use the new rule in the Request as usual:
$this->validate($request, [
'cameraMac' => 'required|transformUpper'
]);

Categories