How to make one validation error for 2 fields - laravel-5

I have 2 fields for postal code main and sub.
<input type="text" name="postal01">
<input type="text" name="postal02">
I would like to have validation for numeric and size of both fields added.
What I want to do is showing validation error for one field as postal_cd, not each field error.
I had tried in a request class extended FormRequest.
class MemberRequest extends FormRequest
{
public function all($keys = null)
{
$result = parent::all($keys);
if($this->filled('postal01') && $this->filled('postal02')) {
$results['postal_code'] = $this->input('postal01') . $this->input('postal02');
}
return $result;
}
However it did not work like I expected.
How can I handle this case?

You can use an After Validation Hook. Add the following to your Form Request:
/**
* Configure the validator instance.
*
* #param \Illuminate\Validation\Validator $validator
* #return void
*/
public function withValidator($validator)
{
$validator->after(function ($validator) {
if($validator->errors()->has('postal01') || $validator->errors()->has('postal02')) {
$validator->errors()->add('postal_cd', 'Please enter a postal code');
}
});
}
... and then to display it on your blade:
{{ $errors->first('postal_cd') }}

That was my typo.
class MemberRequest extends FormRequest
{
public function all($keys = null)
{
$result = parent::all($keys);
if($this->filled('postal01') && $this->filled('postal02')) {
$result['postal_code'] = $this->input('postal01') . $this->input('postal02');
// $results['postal_code'] = $this->input('postal01') . $this->input('postal02');
}
return $result;
}
Returned value should have been $result. But it was typo $results['postal_code'].
It works.

Related

Laravel validation between if checkbox checked

Laravel Version: 5.7
I want to set a validation. when checkbox is checked, then set a 'between' rule.
just like below.
required|integer|between:1,2
but when checkbox is not checked is not need between rule like below
required|integer
I try to use validation, But I don't know how to set.
Inputs
<input type="checkbox" name="checkbox">
<input type="number" name="number">
I don't know if you are using form request or not, so here is a solution for validation using a Form request
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class DepartmentRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
public function rules()
{
rules = [];
if ($this->attributes->has('checkbox')) {
$rules['key'] = 'required|integer|between:1,2',
} else {
$rules['key'] = 'required|integer',
}
// Your other validation rules here
return $rules;
}
public function messages()
{
return [
// Your custom validation messages here
];
}
}
Remember: You must change the key with the field name you want to validate.
Hope it helps.

Does Laravel support "typed" requests?

To transform a database entity to an API response Laravel support resources, eg. UserResource extends JsonResource. The resource allows me to cleanly define which fields from the entity should be included in the response, how to transform them etc.
Is there a similar functionality for requests? My requests typically look like this:
public function create(JsonRequest $request): UserResource
{
$data = $request->json()->all();
/* Remove, transform, add request fields etc. */
$user = User::create($data);
$user->save();
return new UserResource($user);
}
In our case we have a legacy database behind a modern API so there are a number of fields that need to transformed, renamed etc. before pushing them into the entity class. The fields differ from request to request but the steps are very similar. Is there a less boilerplate-y way to do this, something similar to how resources transform entities to responses?
Something like:
class UserRequest extends JsonRequest {
public function fromArray(JsonRequest $request) {
…
}
}
Then the request could look like this:
public function create(UserRequest $request): UserResource
{
$user = User::create($request);
$user->save();
return new UserResource($user);
}
I suppose, that most of your problems can solve form request. See example below
Form request class:
namespace App\Http\Requests;
use Carbon\Carbon;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
class TestRequest 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 [
'date' => 'required|date_format:Y-m-d H:i:s',
'name' => 'required|string',
];
}
// here you can specify custom error messages
public function messages()
{
return [
'date.required' => 'No date specified',
'date.date_format' => 'Invalid date format',
'name.required' => 'No name specified',
'name.string' => 'Invalid name format',
];
}
// here you can implement some data mapping before validation
protected function validationData()
{
return $this->transform($this->all());
}
// some data transformation logic
// You can place it anywhere in your applciation services
protected function transform($input)
{
$transformed = [];
foreach ($input as $field => $value) {
if ($field == 'name') {
$value = strtoupper($value);
} elseif ($field == 'date') {
$value = Carbon::parse($value)->toDateTimeString();
}
$transformed[$field] = $value;
}
return $transformed;
}
public function failedValidation(Validator $validator)
{
// here you can implement custom validation failure
parent::failedValidation($validator);
}
}
Here is my test route: Route::get('/test', 'TestController#index');
And controller:
use App\Http\Requests\TestRequest;
class TestController extends Controller
{
public function index(TestRequest $request)
{
return response()->json($request->validated());
}
}
So, then requesting route: curl -H 'Accept: application/json' 'http://localhost:8000/test?date=01.01.2019&name=petya'
And getting response: {"date":"2019-01-01 00:00:00","name":"PETYA"}
And dont be shy to see source code of request and form request, cause of not all methods you wish are described in docs. Hope this helps

Laravel 5 Sanitizing Required Field Behavior

I am trying to sanitize the user input in my application following this article
Below is my request
class TestRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
$this->sanitize();
return [
'title'=>'required|max:100'
];
}
public function sanitize()
{
$input = $this->all();
if(!empty($input))
{
$input['title'] = trim(strip_tags($input['title']));
$this->replace($input);
}
}
}
Tough the title is required field, if I try to put <h1></h1> as input in the title field, as per the logic in sanitize() function the tags are stripped away, but an empty string is saved in the database. The required field validation in the rules in not taking any effect.
How to handle this?
Update:
Below is the controller method for saving the request.
public function save(TestRequest $request)
{
$input = $request->all();
...
}
First option is to use merge() instead of replace() in your code, i.e.:
$this->merge( ['title' => trim(strip_tags($input['title']))] );
Second option is to override the all() function, i.e.:
public function all()
{
$input = parent::all();
if( !empty($input) )
{
$input['title'] = trim(strip_tags($input['title']));
}
return $input;
}
In the last code example you dont have to use the sanitize() function.

Laravel validation request class return model with errors

When validating a form with a request class you can manually validate the data using the validate() method but what do you return back I've tried return $this and return $this->errors but it just shows SQL integrity constraint duplicate entry which is correct but it doesn't show my form with the errors. When doing validation inside the controller you return the model and the errors but what do I return and set errors on validate method in the request class.
Request Class:
namespace App\Http\Requests;
use App\Http\Requests\Request;
use Auth;
class ProductRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
protected $action;
public function authorize()
{
if(Auth::check()) {
return true;
}
}
public function validate() {
$v = \Validator::make(parent::all(), $this->rules());
if ($v->passes()) return true;
$this->errors = $v->messages();
// tried returning $this; and $this->errors
return false;
}
public function all()
{
$data = parent::all();
if( $data['slug'] === '') {
// if the slug is blank, create one from title data
$data['slug'] = str_slug( $data['title'], '-' );
}
return $data;
}
public function messages()
{
}
public function rules() {
}
}
your rule method is empty your not validating any thing the error you got is an SQL exception not a validation error.

Silex , mongo DB and updating a Document , Unique Constraint validation doesnt work properly

I'm testing silex, mongodb and Form validation. And I run into a validation issue when using MongoDB ODM and a before middelware , wether it is security related or not.
I'm given a document and have added an Unique constraint on a field of the document.
If the document is not requested before the validation actually executes, everything works fine.
Let's say I have a before middleware that requests the document before the controller with validation is executed. In that case the unique constraint does not work properly and displays an error message saying This value is already used. But it should not since the value used is unique to the object that is validated.
To sum up, the issue is, when validating a document with an Unique Constraint on a field, if the document is requested through the document manager (with no modification performed on the document) before the validation code is actually executed, it seems the Unique constraint does not work properly.
I'm going to set up a test case but in the mean time, here is an example of how I set up the validation on the document; if anybody has come across the issue please let me know.
namespace Document;
//use Doctrine\Bundle\MongoDBBundle\Validator\Constraints\Unique as MongoDBUnique;
use Doctrine\Bundle\MongoDBBundle\Validator\Constraints\Unique;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Mapping\ClassMetadata;
/**
* #ODM\Document(collection="blog_post")
*/
class Post
{
/**
* #ODM\Id
*
*/
protected $id;
/**
* #ODM\String
* #ODM\UniqueIndex
*/
protected $title;
/**
* #ODM\String
*/
protected $body;
/**
* #ODM\Date
*/
protected $createdAt;
/**
* #ODM\ReferenceOne(targetDocument="Document\User",cascade="update,merge",inversedBy="posts")
*/
protected $user;
function __construct() {
}
public function getTitle() {
return $this->title;
}
public function setTitle($title) {
$this->title = $title;
}
public function getBody() {
return $this->body;
}
public function setBody($body) {
$this->body = $body;
}
public function getCreatedAt() {
return $this->createdAt;
}
public function setCreatedAt($createdAt) {
$this->createdAt = $createdAt;
}
public function getId() {
return $this->id;
}
function getUser() {
return $this->user;
}
function setUser(User $user) {
$this->user = $user;
$this->user->addPost($this);
}
function __toString() {
return $this->title;
}
static function loadValidatorMetadata(ClassMetadata $metadatas) {
$metadatas->addPropertyConstraint("body", new Length(array('min'=>10,'max'=>1000)));
$metadatas->addPropertyConstraint("title", new Length(array('min'=>5,'max'=>255)));
$metadatas->addConstraint(new Unique(array('fields' => 'title')));
}
}
The app is in this Github repository. (work in progress):
Edit 1: An example of a before middleware that would trigger the erratic behavior of the Unique Constraint (in demo/mongoddb/blog/app/Config.php file in the repo linked) :
$app['must_be_post_owner'] = $app->protect(function(Request $req)use($app) {
$postId = $req->attributes->get('id');
$user = $app['security']->getToken()->getUser();
$post = $app['odm.dm']->getRepository('Document\Post')->findOneBy(array('id' => $postId));
if ($post->getUser() !== $user) {
$app['logger']->alert("Access denied for user $user to post with id $postId ");
$app->abort(500, 'You cant access this resource !');
}
}
);
Edit 2: I tried to debug the Symfony/Doctrine-Bridge UniqueEntityValidator class with XDebug but I get socket errors every time there is a MongoDB related function executed during step debugging.

Resources