php - Laravel 5 validation error

116

I have the following view:

@extends('layouts.admin')

@section('pagetitle')
  Edit Settings
@stop

@section('content')

{!! $message or '' !!}

@if (count($errors) > 0)
  <div >
    <strong>Whoops!</strong> There were some problems with your input.<br><br>
    <ul>
      @foreach ($errors->all() as $error)
        <li>{{ $error }}</li>
      @endforeach
    </ul>
  </div>
@endif

<div >

  <div >
    <div >
      <i ></i>
      <span >Discounts</span>
    </div>
  </div>

  <div >

    <div >

      <form role="form" method="POST" action="{!! URL::to('admin/discounts/update') !!}">
        <input type="hidden" name="_token" value="{{ csrf_token() }}">

        <table >
          <thead>
            <tr>
              <th width="30%">Minimum Credits</th>
              <th width="30%">Maximum Credits</th>
              <th width="30%">Discount %</th>
              <th width="100"></th>
              <th width="100"></th>
            </tr>
          </thead>
          <tbody>
            @if(count($discounts)==0)
              <tr>
                <td>
                  {!! Form::text('min_credits[]', null, array('class' => 'form-control')) !!}
                </td>
                <td>
                  {!! Form::text('max_credits[]', null, array('class' => 'form-control')) !!}
                </td>
                <td>
                  <div >
                    {!! Form::text('discount_percent[]', null, array('class' => 'form-control')) !!}
                    <span >%</span>
                  </div>
                </td>
                <td><button type="button" ><i ></i> Delete</td>
                <td><button type="button" ><i ></i> New Row</button></td>
              </tr>
            @else
              @foreach($discounts as $discount)
                <tr>
                  <td>
                    {!! Form::text('min_credits[]', $discount->min_credits, array('class' => 'form-control')) !!}
                  </td>
                  <td>
                    {!! Form::text('max_credits[]', $discount->max_credits, array('class' => 'form-control')) !!}
                  </td>
                  <td>
                    <div >
                      {!! Form::text('discount_percent[]', $discount->discount_percent, array('class' => 'form-control')) !!}
                      <span >%</span>
                    </div>
                  </td>
                  <td><button type="button" ><i ></i> Delete</td>
                  <td><button type="button" ><i ></i> New Row</button></td>
                </tr>
              @endforeach
            @endif
          </tbody>
        </table>

        <div >
          <div >
            {!! Form::submit('Update', array('class' => 'btn btn-primary')) !!}
          </div>
        </div>
      </form>
    </div>
  </div>
</div>

@stop

@section('scripts')
  <script type="text/javascript">
    $(document).ready(function() {

      $('.delete').click(function() {
        if(confirm("Are you sure you want to delete this row?")){
          $(this).closest('tr').remove();
        }
      });

      $('.newrow').click(function() {
        html = '<tr>\
              <td>\
                {!! Form::text('min_credits[]', "", array('class' => 'form-control')) !!}\
              </td>\
              <td>\
                {!! Form::text('max_credits[]', "", array('class' => 'form-control')) !!}\
              </td>\
              <td>\
                <div >\
                  {!! Form::text('discount_percent[]', "", array('class' => 'form-control')) !!}\
                  <span >%</span>\
                </div>\
              </td>\
              <td><button type="button" ><i ></i> Delete</td>\
              <td><button type="button" ><i ></i> New Row</button></td>\
            </tr>';
        $(this).closest('tr').after(html);
      });

    });
  </script>
@stop

The following request:

<?php namespace App\Http\Requests;

use App\Http\Requests\Request;
use Validator;
use Session;
use Auth;

class DiscountsEditRequest extends Request {

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Set up the validation rules
     */
    public function rules()
    {
        $rules = [
            'min_credits' => 'array',
            'max_credits' => 'array',
            'discount_percent' => 'array'
        ];

        $row_count = count($this->min_credits);
        for($i=0; $i<$row_count; $i++) {
            $rules['min_credits.'.$i] = 'required|integer';
            $rules['max_credits.'.$i] = 'integer';
            $rules['discount_percent.'.$i] = 'required|integer';
        }

        return $rules;
    }

    public function messages()
    {
        $messages = [
            'min_credits.array' => 'The minimum credits field must be an array.',
            'max_credits.array' => 'The maximum credits field must be an array.',
            'discount_percent.array' => 'The discount percent field must be an array.',
            'discount_percent.required' => 'The discount field is required.'
        ];

        $row_count = count($this->min_credits);
        for($i=0; $i<$row_count; $i++) {
            $messages['min_credits.'.$i.'required'] = 'The minimum credits field is required.';
            $messages['min_credits.'.$i.'integer'] = 'The minimum credits field must contain an integer.';
            $messages['max_credits.'.$i.'integer'] = 'The maximum credits field must contain an integer.';
            $messages['discount_percent.'.$i.'required'] = 'The discount field is required.';
            $messages['discount_percent.'.$i.'integer'] = 'The discount field must contain an integer.';
        }

        return $messages;
    }

}

The following controller:

<?php namespace App\Http\Controllers\Admin;

use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Http\Requests\DiscountsEditRequest;

use Illuminate\Http\Request;
use View;
use Session;
use Input;
use Response;
use Auth;
use App\Discount;

class DiscountsController extends Controller {

    public function __construct()
    {
        $this->data['admin_user'] = Session::get('admin_user');

        $this->data['message'] = Session::get('message');

        $this->data['admin_user'] = Auth::user();
    }

    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        $this->data['discounts'] = Discount::orderBy('min_credits', 'asc')->get();

        return View::make('admin/discounts/index', $this->data);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  int  $id
     * @return Response
     */
    public function update(DiscountsEditRequest $request)
    {
        Discount::truncate();

        $row_count = count($request->min_credits);
        for($i=0; $i<$row_count; $i++) {
            Discount::create([
                'min_credits' => $request->min_credits[$i],
                'max_credits' => $request->max_credits[$i],
                'discount_percent' => $request->discount_percent[$i]
            ]);
        }

        Session::flash('message', '<div class="alert alert-success" role="alert">The settings have been updated.</div>');
        return redirect('admin/discounts');
    }

}

If I submit the form with all fields filled in correctly it works fine, but if I purposely do something to make the validation fail such as submit a min_credits field as blank I get the following error:

ErrorException in helpers.php line 455:
htmlentities() expects parameter 1 to be string, array given (View: C:\xampp\htdocs\clipitquick\resources\views\admin\discounts\index.blade.php)

This is the full stack trace:

in helpers.php line 455
at CompilerEngine->handleViewException(object(ErrorException), '1') in PhpEngine.php line 43
at PhpEngine->evaluatePath('C:\xampp\htdocs\clipitquick\storage\framework\views/b9d9b3d2ce2ab48a4dd7dd16ca46f5fe', array('__env' => object(Factory), 'app' => object(Application), 'errors' => object(ViewErrorBag), 'admin_user' => object(User), 'message' => null, 'discounts' => object(Collection))) in CompilerEngine.php line 57
at CompilerEngine->get('C:\xampp\htdocs\clipitquick\resources\views/admin/discounts/index.blade.php', array('__env' => object(Factory), 'app' => object(Application), 'errors' => object(ViewErrorBag), 'admin_user' => object(User), 'message' => null, 'discounts' => object(Collection))) in View.php line 136
at View->getContents() in View.php line 104
at View->renderContents() in View.php line 78
at View->render() in Response.php line 44
at Response->setContent(object(View)) in Response.php line 202
at Response->__construct(object(View)) in Router.php line 1188
at Router->prepareResponse(object(Request), object(View)) in Router.php line 692
at Router->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 141
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in AdminAuth.php line 30
at AdminAuth->handle(object(Request), object(Closure)) in Pipeline.php line 125
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 101
at Pipeline->then(object(Closure)) in Router.php line 693
at Router->runRouteWithinStack(object(Route), object(Request)) in Router.php line 660
at Router->dispatchToRoute(object(Request)) in Router.php line 618
at Router->dispatch(object(Request)) in Kernel.php line 210
at Kernel->Illuminate\Foundation\Http\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 141
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in ShareErrorsFromSession.php line 55
at ShareErrorsFromSession->handle(object(Request), object(Closure)) in Pipeline.php line 125
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in StartSession.php line 61
at StartSession->handle(object(Request), object(Closure)) in Pipeline.php line 125
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in AddQueuedCookiesToResponse.php line 36
at AddQueuedCookiesToResponse->handle(object(Request), object(Closure)) in Pipeline.php line 125
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in EncryptCookies.php line 40
at EncryptCookies->handle(object(Request), object(Closure)) in Pipeline.php line 125
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in CheckForMaintenanceMode.php line 42
at CheckForMaintenanceMode->handle(object(Request), object(Closure)) in Pipeline.php line 125
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 101
at Pipeline->then(object(Closure)) in Kernel.php line 111
at Kernel->sendRequestThroughRouter(object(Request)) in Kernel.php line 84
at Kernel->handle(object(Request)) in index.php line 51
355

Answer

Solution:

According to your validation rules, all your three properties are arrays. Later, you are passing them as a values forForm::text. Let's check the function declaration:

string text(string $name, string $value = null, array $options = array())

The problem is same as your exception message - you are trying to pass an array to $value argument, which accepts only strings.

It looks like you want to make many fields for every array value, so try something like this:

@foreach($discount->min_credits as $entry)
    <td>
        {!! Form::text('min_credits[]', $entry, array('class' => 'form-control')) !!}
    </td>
@endforeach
946

Answer

Solution:

I had to change it so that every array value had a key set like so:

@foreach($discounts as $key => $discount)
  <tr>
    <td>
      {!! Form::text('row['.$key.'][min_credits]', $discount->min_credits, array('class' => 'form-control')) !!}
    </td>
    <td>
      {!! Form::text('row['.$key.'][max_credits]', $discount->max_credits, array('class' => 'form-control')) !!}
    </td>
    <td>
      <div >
        {!! Form::text('row['.$key.'][discount_percent]', $discount->discount_percent, array('class' => 'form-control')) !!}
        <span >%</span>
      </div>
    </td>
    <td><button type="button" ><i ></i> Delete</td>
    <td><button type="button" ><i ></i> New Row</button></td>
  </tr>
@endforeach

And then change the validation rules like so:

public function rules()
{
    $rules = [
        'min_credits' => 'array',
        'max_credits' => 'array',
        'discount_percent' => 'array'
    ];

    $row_count = count($this->row);
    for($i=0; $i<$row_count; $i++) {
        $rules['row.'.$key.'.min_credits'] = 'required|integer';
        $rules['row.'.$key.'.max_credits'] = 'integer';
        $rules['row.'.$key.'.discount_percent'] = 'required|integer';
    }

    return $rules;
}

People are also looking for solutions to the problem: PHP: date "F" with setlocale not working

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.