I have a issue, Please take a look below.
I have a edit user profile section where we update user account, i want to check if no image exists in table & user too not provided image then we have to validate the image & show an error. if there is already a image exists in table then no image validation suppose to check. Everything works good except image validation.
i am using from request for validation. below is my validation rules in request file.
public function rules()
{
return [
'user_type' =>'required',
'first_name' =>'required|max:100',
'last_name' =>'required|max:100',
'email' =>'required|email|max:100',
'image' =>'required|image',
'zip_code' =>'required|numeric|min:5',
];
}
I am using Laravel 5.2, Thanks in advance.
Finally i figure out the solution using help of #Amir. below is the complete solutions of this issue.
//add this in user model
public function notHavingImageInDb(){
return (empty($this->image))?true:false;
//return true;
}
//import the User model & Auth class in request class.
use App\User;
use Auth;
//add this in from request
public function rules()
{
$user = User::find(Auth::id());
$rules = [
'user_type' =>'required',
'first_name' =>'required|max:100',
'last_name' =>'required|max:100',
'email' =>'required|email|max:100',
'image' =>'image',
'zip_code' =>'required|numeric|min:5',
];
if ($user->notHavingImageInDb()){
$rules['image'] = 'required|image';
}
return $rules;
}
Now all done.
In the above code we check if the column has some value or not in validation, if yes then model function return true, this make the if condition active in request class, else, if condition remain inactive. works like charm.
Thanks
take a look at Conditionally Adding Rules:
so something like:
$v->sometimes(['image'], 'required|image', function($input) use ($user) {
return $user->notHavingImageInDb();
});
you can also use plain logic like:
public function rules()
{
$roles = [
'user_type' =>'required',
'first_name' =>'required|max:100',
'last_name' =>'required|max:100',
'email' =>'required|email|max:100',
'image' =>'image',
'zip_code' =>'required|numeric|min:5',
];
if ($user->notHavingImageInDb())
$rules['image'] = 'required|image';
return $rules
}
You can create another request class and name it UserUpdateRequest with artisan
like
php artisan make:request UserUpdateRequest
in this request class you just have to remove 'required' it will be like that
'image' => 'image'
and set UserUpdateResuest as parameter to update method like
public function update(UserUpdateRequest $userUpdateRequest, $id){
//
}
Related
I have not so much practical experience with Laravel yet and I wondered what is the best way to deal with similar validation logic and where to put it.
Let's say I have an API resource Controller for Products with a store and an update method like so:
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:100',
'description' => 'nullable|string|max:1000',
'price' =>'required|decimal:0,2|lt:1000'
]);
return Product::create($request->all());
}
public function update(Request $request, Product $product)
{
$request->validate([
'name' => 'string|max:100',
'description' => 'nullable|string|max:1000',
'price' =>'decimal:0,2|lt:1000'
]);
return Product::update($request->all());
}
The only difference between the validation in store and update is that store adds the 'required' rule for 'name' and 'price'. My question is, if I can encapsulate both validations in one Form Request, or how can I avoid code duplication without adding unnecessary code?
With my understanding of Form Requests I would probably create two Form Request classes, StoreProductRequest and UpdateProductRequest, and maybe another helper class that defines the core validation rules. Then each Form request could call for example ProductHelper::getBaseValidationRules() and merge that with their extra requirements. Somehow I find that a bit overkill.
you can create a request for your validations and use them in your controllers
for example
php artisan make:request YOUR_REQUEST_NAME
then inside your request you can add your validations like this
public function rules()
{
return [
'name' => 'required|string|max:100',
'description' => 'nullable|string|max:1000',
'price' => 'required|decimal:0,2|lt:1000'
];
}
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
and in your method you can call it like this
public function update(YOUR_REQUEST_NAME $request, Product $product)
{
return Product::update($request->all());
}
for more information you can read this
https://laravel.com/docs/5.0/validation#form-request-validation
in case you want condition in the rules please check this video
https://www.youtube.com/watch?v=epMaClBOlw0&ab_channel=CodeWithDary
Okay based on the suggestions, I came up with the following solution:
I created a Form Request named ProductRequest and implemented the rules method as follows:
public function rules()
{
$rules = [
'name' => ['string', 'max:100'],
'description' => ['nullable', 'string', 'max:1000'],
'price' => ['decimal:0,2', 'lt:1000'],
];
// If the user wants to create a new Instance some fields are mandatory.
if ($this->method() === 'POST') {
$rules['name'][] = 'required';
$rules['price'][] = 'required';
}
return $rules;
}
This is fine for me. Although in a bigger project I probably would create two Form Requests, StoreProductRequest and UpdateProductRequest. They would share and update a base set of rules as I described in the question.
This will be a bit long question, I'm finishing my application, but there are few left things to be done before ending.
At first: I did few POST forms/functions. They works well, but in case I would not pass one of the $request data, it comes with SQL bug, I read that to manage that I need validation, so I made Request model with validation rules, but I dont know how to implement it into my Controller class.
This is how looks like my request model and create class inside of controller:
public function create(Request $request)
{
$id = Auth::id();
$event = new Event;
$event->name = $request->name;
$event->description = $request->description;
$event->address = $request->address;
$event->date_of_event = $request->date_of_event;
$event->displayed = 0;
$event->photo_patch = $request->photo_patch->store('images','public');
$event->club_id = $request->club_id;
$event->user_id = $id;
$event->save();
return redirect('events');
}
------------Request---------------------------
return [
'name' => 'required|max:50',
'description' => 'required|max:100',
'address' => 'required|max:63',
'date_of_event' =>'required',
'photo_patch' =>'required',
'club_id' =>'required',
];
Second thing to protect is to split views for admin and for user, Since I did authorization via Gate(admin-level) with column in db admin(boolean)
I'm thinking about doing validation like this:
public function index()
{
$id = Auth::id();
if (Gate::authorize('admin-level')){
$events = Event::get();
}
else{
$events = Event::where('user_id',$id)->get();
}
return view('backend/event/index', ['events' => $events]);
}
but then, comes error:
Non static method 'authorize' should not be called statically.
Is there any way to bypass that? Or, is there any better/easier way to authorize?
My third problem is to protect users from making changes by other users.
What do I mean by that.
Every user got acces only to his own club/events BUT if someone would put url for example other ID, he can edit every single club/event he want. How can I prevent it?
And my final question
I'm protecting my routes with middleware auth is there any better way to do it?
Route::middleware(['auth'])->group(function() {
Thank you in advance for anwsers.
Your gate should be called on the facade, which i do not believe you are doing. Please use the following gate class.
use Illuminate\Support\Facades\Gate;
Validation can be implemented by calling validate() on your request object. This will also automatically throw exceptions if failed.
$validated = $request->validate([
'name' => 'required|max:50',
'description' => 'required|max:100',
'address' => 'required|max:63',
'date_of_event' =>'required',
'photo_patch' =>'required',
'club_id' =>'required',
]);
Disallowing users from editing clubs. In general you control the access to objects, either with policies or with queries. This is an example with a policy.
public function find(Club $club) {
$this->authorize('view', $club);
}
class ClubPolicy {
public function view(User $user, Club $club)
{
return $club->user_id === $user->id;
}
}
I am working with Laravel 5.7 and do not go Auth command and make Login and Registration. but I have UserController and save data in users table as following.
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'address' => $data['address'],
]);
$verifyUser = VerifyUser::create([
'user_id' => $user->id,
'token' => str_random(40)
]);
Mail::to($user->email)->send(new VerifyMail($user));
return $user;
}
now how can I make Route in web.php file to save above data.
Make create method public and add fillable property in your models and try to make route like this:
Route::post('register', 'RegisterController#create');
Hope this helps :)
add the following to routes:
Route::post('url', 'ControllerName#MethodName');
which will be like below in your case:
Route::post('register', 'UserController#create');
You must change your method to public instead of protected.
In your web.php routes file set the route as post.
Example: Route::post('route_name', 'MethodController#method_name');
On your method create you can use Request $request to get the data.
Example:
public function create(Request $request) {
$name = $request->data[0];
$email = $request->data[1];
$address = $request->data[2];
(rest of your code)
}
Here i have two inputs field as name and age.
I wanna validate name but not age.
How can i send both value to store.
request()->validate([
'name' => 'required',
]);
//Here i wanna add 'age' along with 'name' in $request
//Then i must store.
Pastor::create($request->all());
The $request->all() already sends whatever is in your request. But if you like you can specifically pass request values to create method like this:
Pastor::create([
'name'=> $request->name,
'age' => $request->age
//any other fields
]);
I assume you have named your inputs like i have passed into create method and it should work.
use the Validator class Laravel has. lets say you have UserController
Use Validator;
Use App\User;
class UserController extends Controller
{
// Your Validator
protected function yourValidatorName(array $data)
{
$rules = ['name'=>'required'];
return Validator::make($data,$rules);;
}
// Your Main Function
public function yourFunctionName(Request $request)
{
$isValid = $this->yourValidatorName($request->all());
if(!isValid->fails())
{
// your code here (validation passed)
}
else
{
// your code here (validation failed)
}
}
}
You simply put a check on name field only
$this->validate($request,[
'name' => 'required|min:3|max:200',
],[
'name.required' => 'name is a required field.', // custom messages you can omit them
'name.min' => ' Name must be at least 3 characters.', // custom message for minimum characters
'name.max' => ' Name should not be greater than 200 characters.', // custom message for maximum characters
]);
Pastor::create($request->all());
Without custom messages
$this->validate($request,[
'name' => 'required|min:3|max:200',
]);
Pastor::create($request->all());
I have a table called Customer and with a Get Request I can already get all the Data (which I created with phpMyAdmin) on a HTML Template.
Now I want to create a new Customer with a Post Request.
This is the way I thought it would work:
In the Controller:
public function addNewCustomer(Request $request)
{
return \app\model\Customer::create($request->all());
}
The route:
Route::post('posttest', 'CustomerController#addNewCustomer');
How can I create a validation for it?
You can add validation of form like below in addNewCustomer,
public function addNewCustomer(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|max:255',
'body' => 'required',
]);
return \app\model\Customer::create($request->all());
}
For more information about input validation in Laravel Please readout Laravel Validation Documentation