Inquiry about Validation Laravel - php

I have a question about Laravel validation. I have two number <input> fields like:
I want to create a rule in the "Request" file from App\Requests\MyRequest.php that requires the value from the second input field to be greater than the first input field and that both fields must have a value greater than 0.
How should I code this? Does Laravel validation support this?

You can add validations in app/Http/Requests by running php artisan make:request MyRequest something like below:
<?php
namespace App\Http\Requests;
class MyRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'first_field' => 'min:0',
'second_field' => 'min:'.$this->first_field,
];
}
}
You can find more about validations here

Related

Laravel 'required' rule not working on Request

I'm using laravel 5.5
I have a Request that I've built but the required rule is not working correctly.
Route
Route::get('v1/learning_centre/user/{userId}/course/list', 'API\LearningCentre#userCourses');
Controller
public function userCourses(GetUserCourses $request)
{
$courses = User::findOrFail($request->userId)
->courses()
->get();
return new CourseResourceCollection($courses);
}
Request
namespace App\Http\Requests\LearningCentre;
use Illuminate\Foundation\Http\FormRequest;
class GetUserCourses extends FormRequest {
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'userId' => 'required|integer'
];
}
/**
* Get the error messages for the defined validation rules.
*
* #return array
*/
public function messages()
{
return [
'userId.required' => 'A User is required',
];
} }
If I turn off the required rule I can get to the controller. If I have the required rule in the request I get a 302. I am passing in a valid userId in phpunit. Without the request rules my code works as intended.
Any ideas?
You should be using route model binding to validate a required GET parameter in this situation, not a FormRequest class, which, as the name should indicate, are intended for form requests.
Your route:
Route::get('v1/learning_centre/user/{user}/course/list', 'API\LearningCentre#userCourses');
Your controller:
public function userCourses(User $user) {
If a user ID is missing (or an invalid one used), your controller will automatically throw a ModelNotFoundException, which Laravel by default returns as a 404.

How to (properly) use form requests + policies + resource routes with dependencies?

My use case is that an user is/owns a company, which has employees.
Using form controllers along with model policies i am trying to figure out what the best/proper way to do it should be.
routes:
Route::resource('company', \App\Http\Controllers\Api\v1\CompanyController::class);
Route::resource('employee', \App\Http\Controllers\Api\v1\EmployeeController::class);
employee store request:
namespace App\Http\Requests;
use App\Models\Employee;
use Illuminate\Foundation\Http\FormRequest;
class EmployeeStoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return $this->user()->can('create', Employee::class);
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'company_id' => 'required|integer|exists:companies,id'
];
}
}
employee policy:
...
/**
* Determine whether the user can create employees.
*
* #param \App\User $user
* #return mixed
*/
public function create(User $user)
{
return $user->can('update', Company::find(
app('request')->get('company_id')
));
}
...
So i am not particularly happy in how the policy checks if the user can edit the company the employee will belong to, since this only happens on http, for console/tests this will break.
Then the most logical way to add this check is in the form request's authorize() function, but then you are checking permissions outside the policies, which sounds illogical.
So in short, the question: how & why would you do this using form requests & model policies?
You only need to add the id of the company to the EmployeePolicy#create method, and you will be able to use it outside http
EmployeePolicy
public function create(User $user, $companyId)
{
return $user->can('update', $companyId);
}
EmployeeStoreRequest
public function authorize()
{
return $this->user()->can('create', Employee::class, $this->request->get('company_id'));
}
You can test it outside http with tinker
php artisan tinker
$user = User::find(2); // or whatever user you want to test with
$user->can('create', Employee::class, 3); // 3 = company_id

Laravel do not validate if field is not required

I've got the following request validation:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class OwnerEstate extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'firstname' => 'required_if:type,individual',
'secondname'=> 'required_if:type,individual',
'lastname' => 'required_if:type,individual',
'pin' => 'required_if:type,individual|digits:10',
'name' => 'required_if:type,legal-entity',
'eik' => 'required_if:type,legal-entity|digits:9'
];
}
}
And when the type is not individual it still checks for the 'digits:10' validation of the pin and returns an error. How do I disable the other validation if required_if validation does not require the field. (I'm using Laravel 5.5)
digits:10 is completely separate from required_if, so it will validate whether or not the field is required. However, if you want to also allow null or empty values (assuming the field is not required), you can add the rule nullable.
https://laravel.com/docs/5.5/validation#rule-nullable

Right Way to validate form input fields

I'm building an API, one of the db table Person have 52 columns and most of them are required t don't think the way I'm doing is right
public function store() {
if (! input::get('name') or ! input::get('age') or ! input::get('phone') or ! input::get('address') and so on till the 52 field) {
return "Unprocessable Entity";
}
return "Validated";
}
And how to properly validate all the required fields
Thank You
You can simply write your validation rules and messages within a Request file and can call directly within your store function like as
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
use Illuminate\Validation\Rule;
/**
* Class YourFileRequest
* #package App\Http\Requests
*/
class YourFileRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
/**
* Get the custom validation messages that apply to the request.
*
* #return array
*/
public function messages()
{
return [
'title.required' => 'Please enter title',
'title.max' => 'Please enter max value upto 255',
'body.required' => 'Please enter body',
];
}
}
within your controller
use App\Http\Requests\YourFileRequest;
......
public function store(YourFileRequest $request)
{
//Your storing logic
}
You can do it in two ways:
The first one is
$this->validate($request,['email'=>'required|email|unique']);
Secondly, you can create a separate ValidationRequest by using the following command:
php artisan make:request StoreRequest

Request validation allways passes on Laravel using Dingo/Api

I'm using dingo/api package.
Controller:
public function register(RegisterUserRequest $request)
{
dd('a');
}
And for example the email field is required:
<?php namespace App\Http\Requests;
class RegisterUserRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'email' => 'required'
];
}
}
So I send a request without the email, and still getting the "a" response.
I also tried to extend Dingo\Api\Http\Request instead of App\Http\Request, but still the same.
For Dingo to work at all with the FormRequest, by experience (and from this Issue), you have to use Dingo's Form request i.e Dingo\Api\Http\FormRequest; , so you'll have something similar to:
<?
namespace App\Http\Requests;
use Dingo\Api\Http\FormRequest;
use Symfony\Component\HttpKernel\Exception\HttpException;
class RegisterUserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'email' => 'required'
];
}
// In case you need to customize the authorization response
// although it should give a general '403 Forbidden' error message
/**
* Handle a failed authorization attempt.
*
* #return mixed
*/
protected function failedAuthorization()
{
if ($this->container['request'] instanceof \Dingo\Api\Http\Request) {
throw new HttpException(403, 'You cannot access this resource'); //not a user?
}
}
}
PS: This is tested on Laravel 5.2.*
Hope it helps :)
According to the Wiki
you must overload the failedValidation and failedAuthorization methods.
These methods must throw one of the above mentioned exceptions and not the response HTTP exceptions that Laravel throws.
If you take a look at Dingo\Api\Http\FormRequest.php, you'll see:
class FormRequest extends IlluminateFormRequest
{
/**
* Handle a failed validation attempt.
*
* #param \Illuminate\Contracts\Validation\Validator $validator
*
* #return mixed
*/
protected function failedValidation(Validator $validator)
{
if ($this->container['request'] instanceof Request) {
throw new ValidationHttpException($validator->errors());
}
parent::failedValidation($validator);
}
/**
* Handle a failed authorization attempt.
*
* #return mixed
*/
protected function failedAuthorization()
{
if ($this->container['request'] instanceof Request) {
throw new HttpException(403);
}
parent::failedAuthorization();
}
}
Hence, you need to change the names of your methods appropriately, and have them throw the appropriate exceptions, instead of returning a boolean.
you need to call the validate function explicitly when you run it under an Dingo API setup, try something like this (for L5.2):
Probably a few extra providers
...
Illuminate\Validation\ValidationServiceProvider::class,
Dingo\Api\Provider\LaravelServiceProvider::class,
...
Aliases
...
'Validator' => Illuminate\Support\Facades\Validator::class,
...
I'm also pretty much sure that you really don't want to use this below as suggested here and there, It will expect form(encoded) input and will also probably fail on CSRF token as it expects it, so it will fail right after validating (form input). But make sure to test behavior with this on/off.
use Dingo\Api\Http\FormRequest;
Make your headers:
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Dingo\Api\Exception\ValidationHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/* This can be a tricky one, if you haven't split up your
dingo api from the http endpoint, there are plenty
of validators around in laravel package
*/
use Validator;
Then the actual code (if you adhere to cors standard,
this should be a POST and that commonly translates to a store request)
...
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function register(RegisterUserRequest $request) {
$validator = Validator::make($request->all(), $this->rules());
if ($validator->fails()) {
$reply = $validator->messages();
return response()->json($reply,428);
};
dd('OK!');
};
...
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'email' => 'required'
// or/and 'userid' => 'required'
];
}
That will give you back the response you expect from the validator. If you use this with pregenerated forms, it does not need this fix, there the validator will kick in automatically. (not under Dingo Api).
you probably also need these in composer.json
"dingo/api": "1.0.*#dev",
"barryvdh/laravel-cors": "^0.7.1",
This is untested, by heart, it took me 2 days to figure this out but I have a separate namespace for API specific and authenticated with middleware. success

Categories