Search code examples
phplaravelvalidationlaravel-validationlaravel-request

How to exclude all the data that fail validation laravel?


I only want the data that pass the validation. And do not want any errors or redirection using laravel-validation. So far I've been able to stop the redirection using a laravel-request but the validation does not seem to work properly if I leave the failedValidation method to not throw any exception.

I have array of data from user who can fill the rows or leave them empty. If they leave the required fields empty in a row then I want to exclude them from the final data after validation.

ExpenditureExtry.php

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;

class ExpenditureEntry 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',
        'description.*' => 'nullable',
        'account_head.*' => 'required',
        'amount.*' => 'required_with:account_head.*'
      ];
  }

  /**
   * Failed validation disable redirect
   *
   * @param Validator $validator
   */
  protected function failedValidation(Validator $validator)
  {
    //throw new HttpResponseException(response()->json($validator->errors(), 422));
  }

}

Inside a controller

public function store(ExpenditureEntry $req)
{
   return $req->validated();
}

I want this to return only those data that passed the validation. At the moment it returns all the data.

Expected output

// http://127.0.0.1:8000/expenditure/add
{
  "date": "03 Sep 2018",
  "description": {
    "1": null,
  },
  "account_head": {
    "1": "5",
  },
  "amount": {
    "1": "5000",
  }
}

Actual output

// http://127.0.0.1:8000/expenditure/add
{
  "date": "03 Sep 2018",
  "description": {
    "0": null,
    "1": null,
    "2": null,
    "3": "sas asd adas",
    "null": null
  },
  "account_head": {
    "0": "3",
    "1": "5",
    "2": null,
    "3": null,
    "null": null
  },
  "amount": {
    "0": null,
    "1": "5000",
    "2": "5000",
    "3": null,
    "null": null
  }
}

I also tried using a Validator::make in the controller but it also doesnot work as expected:

Inside Controller

public function store(Request $req)
{
  $validator = Validator::make($req->except(['account_head.null', 'description.null', 'amount.null']), [
    'date' => 'required',
    'account_head.*' => 'required',
    'description.*' => 'nullable',
    'amount.*' => 'required_with:account_head.*'
  ]);
  return $validator->valid();
}

Output

// http://127.0.0.1:8000/expenditure/add
{
  "_token": "EmiRpnXhPHUPl3HIzuYLrtuLaGj9Ruv8AySe11Bp",
  "date": "03 Sep 2018",
  "description": [
    null,
    null,
    null,
    "sas asd adas"
  ]
}

PS: I want a laravel based solution if possible. If no such solution are possible, I actually have a solution to just manually validate them.

My Solution Went through every data and manually validated them. My problem with this approach is now I can't use other validation functions from laravel and when my fields increases, I don't think writing if condition will help me.

public function store(Request $req)
{
  $datas = $req->except(['_token', 'account_head.null', 'description.null', 'amount.null']);

  $countR = count($datas['account_head']);
  $validated = [];
  $cv = 0;
  for ($i=0; $i < $countR; $i++) {
    if($datas['account_head'][$i] == null) continue;
    else if($datas['amount'][$i] == null) continue;

    $validated['account_head'][$cv] = $datas['account_head'][$i];
    $validated['description'][$cv] = $datas['description'][$i];
    $validated['amount'][$cv] = $datas['amount'][$i];
    $cv++;
  }

  return $validated;
}

Output

// http://127.0.0.1:8000/expenditure/add
{
  "account_head": [
    "5"
  ],
  "description": [
    null
  ],
  "amount": [
    "5000"
  ]
}

Solution

  • As far as i understand your problem, the following code will solve your issue.

    public function store(Request $req)
    {
      $validator = Validator::make($req->except(['account_head.null', 'description.null', 'amount.null']), [
        'date' => 'required',
        'account_head.*' => 'required',
        'description.*' => 'nullable',
        'amount.*' => 'required_with:account_head.*'
      ]);
    
      if ($validator->fails()) {
         // Do Whatever you wants here.
         // return redirect()->back()->withErrors($validator)->withInput();
      }
    }
    

    Instead of redirecting back with errors you can do whatever task you want, without any redirection.