Laravel FormRequest validation rules not working as expected - php

In my Laravel app, I am creating a dynamic search functionality using Eloquent and I have a customer search form which looks like this:
customers.search.blade.php Contrived Example
<form method="post" action="{{ route('customers.search') }}">
#csrf
<div class="form-group">
<label for="first_name" class="font-weight-bold">First Name</label>
<div class="input-group">
<div class="input-group-prepend">
<select name="first_name['operator']" class="custom-select">
<option value="%">%</option>
<option value="=">=</option>
<option value="!=">!=</option>
</select>
</div>
<input id="first_name" name="first_name['query']" type="text" class="form-control">
</div>
</div>
</form>
I have a SearchCustomerRequest (FormRequest) class which builds out the validation rules dynamically. I've dumped it, so you can see what the generated rules looks like:
In my CustomersController under search method, I did the following to see what the validated request array looks like:
class CustomersController extends Controller
{
// ...
public function search(SearchCustomerRequest $searchCustomerRequest)
{
dd($searchCustomerRequest->validated());
}
// ...
}
In order to test this, in the search form, I've selected the firstname['operator'] to % and typed the first_name['query'] to test and submitted the form.
I got the following response (i.e. empty array):
[]
So, I dumped the whole request object $searchCustomerRequest to see what was in the parameter bag and this is what I see:
As you can see, my request is valid and my rules also looks correct, yet the validation doesn't seem to be working as expected.
Any ideas what might be wrong here?

In your ParameterBag, the first_name properties operator and query are enclosed in single quotes. In your HTML, the name attribute should exclude the single quotes. Ex: name="first_name[query]"

Related

Laravel 8 - Request does not retrive input field

I am using Laravel 8. I have the following search box in my blade file:
<form name="searchForm" class="col-12 col-lg-auto mb-3 mb-lg-0 me-lg-3" method="POST" action="{{ url('search') }}">
#csrf
<input name="searchField" type="search" class="form-control form-control-dark" style="width: 426px; " placeholder="Search for news, symbols, tickers or companies">
</form>
I route this to my SearchController:
public function showSearchPage(Request $request) {
$field = $request->searchField;
$name = Input::get('searchField');
.
.
.
However, $request->searchField is null. My $request object looks like the following:
Besides the token, my input field is not within the request.
Any suggestions on what I am doing wrong?
I appreciate your replies!
Change the form attribute of your form to id and try the form attribute on the input field.
Normally you shouldn't have to define either of those, you might try removing the id from your form and also the form from the input field.
It is possible that the initial form attribute on your form caused some trouble.
Let me know if the second approach also worked.
What I know is that, use form id when you need to perform a validation for a script or you have multiple forms in a single page, try changing your form attribute to id, or better if you completely remove it
for search form its better to use GET method instead of POST
and instead of
type="search"
used
type="text" (for test)
added id="searchField" to your input and changed type to text form search. should work
<form name="searchForm" class="col-12 col-lg-auto mb-3 mb-lg-0 me-lg-3" method="POST" action="{{ url('search') }}">
#csrf
<input name="searchField" id="searchField" type="text" class="form-control form-control-dark" style="width: 426px; " placeholder="Search for news, symbols, tickers or companies">
</form>

how to update database using laravel controller? MethodNotAllowedHttpException No message error message

I'm trying to update my database using a form on my
edit.blade.php page as shown below. The edit part works correctly as the fields are filled in in the form as expected, however when i try to save, an error message of
Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException
No message
is displayed. I have tried so many ways on how to fix it and I'm not sure where I'm going wrong. Hopefully it's something simple to fix?
edit.blade.php
#extends('layouts.app')
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
#section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<form method="post" action="{{ action('PostsController#update', $id) }}">
{{ csrf_field() }}
<input type="hidden" name="_method" value="PATCH" />
<h1>Edit Item</h1>
<div class="form-group">
<label for="item">Item:</label>
<input type="text" id="item" name="item" value="{{$post->item}}" class="form-control" required>
</div>
<div class="form-group">
<label for="weight">Weight (g):</label>
<input type="number" id="weight" value="{{$post->weight}}" name="weight" class="form-control">
</div>
<div class="form-group">
<label for="noofservings">No of Servings:</label>
<input type="number" id="noofservings" value="{{$post->noofservings}}" name="noofservings" class="form-control">
</div>
<div class="form-group">
<label for="calories">Calories (kcal):</label>
<input type="number" id="calories" name="calories" value="{{$post->calories}}" class="form-control">
</div>
<div class="form-group">
<label for="fat">Fat (g):</label>
<input type="number" id="fat" name="fat" value="{{$post->fat}}" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</div>
</div>
#endsection
PostsController.php
<?php
public function update(Request $request, $id)
{
$this->validate('$request', [
'item' => 'required'
]);
$post = Post::find($id);
$post->item = $request->input('item');
$post->weight = $request->input('weight');
$post->noofservings = $request->input('noofservings');
$post->calories = $request->input('calories');
$post->fat = $request->input('fat');
$post->save();
return redirect('/foodlog');
}
web.php
<?php
Route::get('edit/{id}', 'PostsController#edit');
Route::put('/edit', 'PostsController#update');
Post.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = [
'id',
'user_id',
'item',
'weight',
'noofservings',
'calories',
'fat',
'created_at'
];
}
My website is a food log application and this function is so that they can edit their log.
Any help is greatly appreciated!
Based on Michael Czechowski I edited my answer to make this answer better, The main problem is inside your routes:
Route::put('/edit/{id}', 'PostsController#update');
You have to add the id inside your route parameters either. Your update() function needs two parameters, first the form parameters from the formular and second the $id of the edited log entry.
The second problem is , the form method field is 'patch' and your route method is 'put'.
The difference between 'patch' and 'put' is:
put: gets the data and update the row and makes a new row in the database from the data that you want to update.
patch: just updates the row and it does not make a new row.
so if you want to just update the old row change the route method to patch.
or if you really want to put the data, just change the put method field in your form.
simply by : {{method_field('PUT')}}
Remember, the form's and the route's methods must be same. If the form's method is put, the route method must be put; and vice-versa.
The main problem is inside your routes:
Route::put('/edit/{id}', 'PostsController#update');
You have to add the id inside your route parameters either. Your update() function needs two parameters, first the form parameters from the formular and second the $id of the edited log entry.
The second one is inside your HTML template:
<input type="hidden" name="_method" value="PUT" />
To hit the right route you have to add the corresponding method to your route Route::put('/edit/{id}', 'PostsController#update');.
A possible last problem
<form method="post" action="{{ action('PostsController#update', $post->id) }}">
I am not sure how your template works, but $id is possible not set inside your template. Maybe try to specify the ID depending on your post. Just to make it sure the ID comes from the shown post.
Further suggestions
Best practice is to use the symfony built-in FormBuilder. This would make it easier to target those special requests like PUT, PATCH, OPTIONS, DELETE etc.

How to get value of input in blade.php

I need to get a value of input to use below, how to do that?
I tried to like this but error says
Undefined variable: name
<div class="col-md-10 col-md-offset-1">
<input id="name" type="text" name="name" />
</div>
<div class="col-md-10 col-md-offset-1">
#php
$nameValue=$_GET['name'];
#endphp
<input id="name2" type="text" name="name2" value="{{$nameValue}}" />
</div>
$nameValue=Request::input('name')
From the blade template you can access the request parameters with the Request facade, you can also print it directly:
{{Request::input('name')}}
In latest versions you can also use:
{{request()->input('name')}}
You have to be aware that your input-values (here "name") ist only available after submitting the form.
If you want to access the form-values before submitting you should take a look at VueJS or any other frontend-framework (React, Angular). Or simply use jQuery.
Therefor you have to use JavaScript if you want to use the input-value before submitting.
Like the others said in the comments, you can access your form-values within your controller and then pass it to your view.
For example (from the documentation):
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function formSubmit(Request $request)
{
$name = $request->input('name');
return view('form', ['name' => $name])
}
}
Now you can use the value within your view:
<input id="name2" type="text" name="name2" value="{{$name}}">
Another possibility would be to "by-pass" your controller and return your view directly from your routes.php:
Route::get('/form-submit', function(){
return view('form');
});
But I'm not sure if this is working and you could access $_GET/$_PSOT directly without using Laravels Request.
You can get inputs array from Request class:
Request::all()['your_input']
Also you can check if that input you want is exists not:
#isset(Request::all()['your_input'])
{{-- your input existed --}}
#else
{{-- your input does not existed --}}
#endisset

Laravel - Method Not Allowed HTTP Exception (RouteCollection.php line 218)

I'm currently new on Laravel and trying to develop my first project. I have this MethodNotAllowedHttpException in RouteCollection.php line 218 error during my development for inserting data into database. I have searched both Google & Stackoverflow for solutions but non are related to my current problem and some of them way too complex for this simple problem (I think so...).
I have my form in my checklist page:-
<form action="{{url('addchecklist')}}" method="POST">
{{ csrf_field() }}
<div class="row">
<div class="col-sm-12">
<div class="text-left">
<input type="hidden" name="schmFK" value="{{$id}}">
<div class="col-sm-6">
<h4>
<label>Section</label>
<select class="selectpicker form-control" data-live-search="true" name="sctionPK">
<option selected>Select the Section</option>
#foreach ($sction as $key=>$slct1)
<option value="{{$slct1->ssctionPK}}">{{strtoupper($slct1->ssctionName)}}</option>
#endforeach
</select>
</h4>
</div>
<div class="col-sm-2">
<button type="button" data-toggle="modal" data-target=".bs-example-modal-lg" class="btn btn-primary btn-sm" style="margin-top:33px; padding-top:7px; padding-bottom:7px;">Add Section</button>
</div>
<div class="col-sm-4">
<h4>
<label>Severity</label>
<select class="selectpicker form-control" name="svrityPK">
<option selected>Select the Severity</option>
#foreach ($svrity as $key=>$slct2)
<option value="{{$slct2->severityPK}}">{{strtoupper($slct2->severityName)}}</option>
#endforeach
</select>
</h4>
</div>
<div class="col-sm-12">
<h4>
<label>Question</label>
<input class="form-control" type="text" placeholder="Question" name="question">
</h4>
</div>
<div class="col-sm-6">
#include('widgets.button', array('class'=>'primary btnaddstd', 'size'=>'lg', 'type'=>'submit', 'value'=>'Add Checklist'))
</div>
</div>
</div>
</div>
</form>
Then I have this route for inserting data from the form into database:-
Route::post('/addchecklist', function (Request $request){
// Create instance to store record
$scheme = new App\checklists;
$scheme->schmFK = $request->schmFK;
$scheme->schSectionFK = $request->sctionPK;
$scheme->severityFK = $request->svrityPK;
$scheme->clQuestion = $request->question;
$scheme->save(); // save the input
// Sort all records descending to retrieve the newest added record
$input = App\checklists::orderBy('cklistPK','desc')->first();
// Set search field variable default value of null
$src = isset($src) ? $src : null;
// Get Checklist reference from cklists_stddetails with the designated ID
$chkstd = App\Cklists_stddetail::where('cklistFK', $input->cklistPK)
->join('stddetails', 'stdDtlFK', '=', 'stddetails.sdtlPK')
->get();
// Get the newest stored record
$chcklst = App\checklists::where('cklistPK', $input->cklistPK)->firstOrFail();
// Get all data from table 'stddetails'
$stddetail = App\stddetails::all();
// Get all data from table 'standards'
$stndrd = App\standard::all();
// Get all data from table 'sections'
$sction = App\Section::all();
// Redirect to 'addref.blade' page with the newest added record
return redirect('addref/'.$input->cklistPK)
->with('src', $src)
->with('chkstd', $chkstd)
->with('id',$input->cklistPK)
->with('schmid', $request->schmFK)
->with('chcklst', $chcklst)
->with('stddetail', $stddetail)
->with('stndrd', $stndrd)
->with('sction', $sction);
});
My scenario is this, I have a form for user to input data in it. Then when the data is saved, they will be redirected to the page of that data to do something there. The data is successfully saved in the database but the redirection to the designated page (addref.blade) with the newest record ID return error:-
But the URL goes where I wanted it to go (means the URL is right):-
As you can see, the usual solution from the net that I found are:-
Make sure both method from routes and the form is the same, and mine it is:-
method="POST"
Route::post
Make sure the URL routes can recognize the form's action URL, and mine it is:-
<form action="{{url('addchecklist')}}" method="POST">
Route::post('/addchecklist', function (Request $request)
Include CSRF token field in the form, and mine it have been included:-
<form action="{{url('addchecklist')}}" method="POST">
{{ csrf_field() }}
I have tried those simple solution provided on the net and nothing is helpful enough. I'm still wondering what else I have missed and hoped that anyone here can assist on solving my issue.
I think the error is that you have a redirect which you have not registered in your routes or web.php file.
Sample redirect:
Route::post('/addchecklist', function (Request $request){
//some post process here...
return redirect('addref/'.$input->cklistPK)
->with('src', $src)
->with('chkstd', $chkstd)
->with('id',$input->cklistPK)
->with('schmid', $request->schmFK)
->with('chcklst', $chcklst)
->with('stddetail', $stddetail)
->with('stndrd', $stndrd)
->with('sction', $sction);
});
Route::get('addref/{id}', function(Request $request){
//show the blade.php with data
});
Can you please write :
url('/addchecklist')
instead of :
url('addchecklist')
and then print_r('in');
and die; and check what you get.
Route::post('/addchecklist', function (Request $request){
print_r('in');
die;
});

How to show the old data in a form input in the Laravel

I write the form.blade.php like this:
<div class="form-group">
<label>Start at</label>
<div id="start_date" class="input-group date form_datetime col-md-4" data-date-format="yyyy-mm-dd hh:ii:ss">
<input class="form-control" name="start_at" size="16" type="text" value="{{ $activity->start_at }}">
<span class="input-group-addon"><span class="glyphicon glyphicon-remove"></span></span>
<span class="input-group-addon"><span class="glyphicon glyphicon-th"></span></span>
</div>
</div>
Both Create and Edit method use the view to display the form. In the Edit method, the $activity is used and everything is normal. But in the Create method, the $activity is null, so I have a error in {{ $activity->start_at }}.
I know I can use if(!empty($activity)) to prevent this error. but I do not want to use this anywhere.
What is the better way?
You could use this,
{{ $activity->start_at or '' }}
I also like to reuse code and use the same view to create or edit an object. What I do is to pass a brand new instance of the object to the create view. This way I have the object on its initial state including defaults (if any) and I am able to prefill those defaults (if any) on the displayed form. It gives me an additional benefit: if anything goes wrong with the validation at the server level the user doesn't lose any data, I just need to do something like this in the view:
<div class="form-group">
<label for="test_field" class="control-label">Fecha de firma</label>
<input type="text" value="{{ ( !empty($isabi) ? $isabi->fecha_firma : old('fecha_firma')) }}"
name="fecha_firma" id="isabi-fechafirma" class="form-control" placeholder="Este campo es obligatorio">
</div>
This is the create method with extra functionality removed for clarity (check if the user is authenticated, linking the created object with the company the user works for and other stuff):
public function create()
{
return view('isabis.create', [
"isabi" => new Isabi()
])->with($this->data);
}
I use $this->data for view configuration. Hope this helps.

Categories