Proper Laravel routing with absence of URI parameters - php

I have a form which can be saved as draft. The initial route will not have the parameter with the submitted id -- since it has not been submitted. Once it's saved, the route will contain the submitted id to retrieve the data and show it to the user.
I am currently creating multiple routes to accommodate this, which is very messy and can see how this will be an issue to maintain.
How can I account for the absence of parameters in routes, especially the form routes or controllers which throw an error with missing variables?
Routes:
Route::get('/request/{unit}/{id}',
'RequestsController#showNewRequest')->name('request.show-new-request');
Route::get('/request/{unit}/{id}/{rid}',
'RequestsController#showRequest')->name('request.show-request');
Route::post('/request/{unit}/{id}',
'RequestsController#storeNew')->name('request.store-new');
Route::post('/request/{unit}/{id}/{rid}',
'RequestsController#store')->name('request.store');
Controllers
public function showNewRequest($unit, $id) { }
public function showRequest($unit, $id, $rid) { }
Form/Blade:
#if(isset($rid))
<form class="form-horizontal" method="POST" enctype="multipart/form-data"
action="{{ route('request.store', ['unit' => $unit, 'id' => $id, 'rid' => $rid]) }}">
#else
<form class="form-horizontal" method="POST" enctype="multipart/form-data"
action="{{ route('request.store-new', ['unit' => $unit, 'id' => $id]) }}">
#endif

You can use ? in the route parameters. This will let you ignore them. Then you can change the code to something like this:
Route::get('/request/{unit}/{id}/{rid?}',
'RequestsController#showRequest')->name('request.show-request');
Controller:
public function showRequest($unit, $id, $rid = null) {
if ($rid) {
//Do something with $rid
} else {
//Do something considering that this is a draft.
}
}
This also applies to post routes.

Related

Laravel 8 form to update database

I am creating a simple blog site with CRUD functionality in Laravel 8. I have done this before using the deprecated Laravel forms, but am now trying to do it using HTML forms.
However, I am having some problem with the update part of the website. I have a controller called BlogsController with this function to be called to update the blog in the database which should be called when the user submits the form to update.
BlogsController update function
public function update(Request $request, $id)
{
$this->validate($request, [
'title' => 'required',
'body' => 'required',
'category' => 'required',
'description' => 'required',
'read_time' => 'required'
]);
$blog = Blog::find($id);
$blog->title = $request->input('title');
$blog->body = $request->input('body');
$blog->category = $request->input('category');
$blog->description = $request->input('description');
$blog->read_time = $request->input('read_time');
$blog->user_id = auth()->user()->id;
$blog->save();
return redirect('/dashboard')->with('success', 'Blog Updated');
}
What action does the form need to direct to? Top of update form
<form method="POST" action="update">
Route in web.php
Route::resource('blog', 'App\Http\Controllers\BlogsController');
Implementation in Laravel forms
{!! Form::open(['action' => ['App\Http\Controllers\BlogsController#update', $blog->id], 'method' => 'POST']) !!}
You can get a list of all your application routes and names by running
$ php artisan route:list
For your blog update route you should use
<form method="POST" action="{{ route('blog.update', ['blog' => $blog]) }}">
#method('PATCH')
</form>
in your template.
Make sure you have you have your csrf token set correctly at your form by using the #csrf, see Laravel docs.
One thing that's cool with Laravel is Route model binding. So what's that mean? We can do something like this in your update method
// BlogController.php
public function update(Request $request, Blog $blog) {
$request->validate([
'title' => 'required',
'body' => 'required',
'category' => 'required',
'description' => 'required',
'read_time' => 'required'
]);
$blog->title = $request->title;
$blog->body = $request->body;
$blog->category = $request->category;
$blog->description = $request->description;
$blog->read_time = $request->read_time;
if ($blog->save()) {
return redirect('/dashboard')->with('success', 'Blog Updated');
} else {
// handle error.
}
}
In your template, you'll want to make sure you're using a PATCH method:
<form method="POST" action="{{ route('blog.update', ['blog' => $blog]) }}">
#csrf
#method('PATCH')
...
</form>
I assume you are using Resource route for your CRUD functionality. In that case, Update method in resource controller called via PUT method and not POST. So, in your form, just add this to change the Form submission method to PUT:
<input name="_method" type="hidden" value="PUT">
Also, in your form declaration, you have to add the destination route like this:
<form method="POST" action="{{ route('blog.update', $blog->id) }}">
You also have the option of using the action to get a URL to the registered route:
action('App\Http\Controllers\BlogsController#update', ['blog' => $blog])
Check all route list:
$ php artisan route:list
your route should be like:
<form method="POST" action="{{ route('blog.update', ['blog' => $blog]) }}">
{{csrf_field()}}
{{ method_field('PATCH') }}
</form>

How to call controller update method from blade laravel?

form method="put" action="{{URL::action('siteController#update')}}" accept-charset="UTF-8"></form>
Route::post('site/update/{id}', 'siteController#update');
public function update(Request $request, $id)
{
//
$this->validate($request,[
'Name' => 'required',
'Description' => 'required',
'Status' => 'required'
]);
$Data = site::find($id);
$Data->Name = $request->Name;
$Data->Description = $request->Description;
$Data->Status = $request->Status;
if($Data->save())
{
return $this->index();
}else{
return redirect()->back()->withErrors($errors,$this->errorBag());
}
}
By adding a name to your route such as
Route::post('site/update/{id}', 'siteController#update')->name('site-update');
It allows you to generate its URL without knowing it at all
<form method="post" action="{{ route('site-update', compact('id')) }}">
#csrf
add your form field here and use button type submit
</form>
Even if you decide to change the URL, the route helper does not care as long as the name stays the same (it's just an alias)
Try This,
<form method="post" action="{{ url('site/update/', ['id' => $id]) }}">
#csrf
add your form field here and use button type submit
</form>

How to encrypt id in URL laravel

I want to encrypt the id in URL I'll show my controller code and route. I've already used Crypt::encrypt($id); in my controller but it's not working properly so I've commented that line in my controller
this is my controller
public function update(TenderRequest $request,$id){
$tender = TenderMaster::findOrFail($id);
//Crypt::encrypt($id);
if($request->extend_date < $request->end_date || $request->bid_status > 0){
return 'unsuccess';
} else{
$transaction = DB::transaction(function () use($request,$tender,$id) {
$tender->extend_date = $request->extend_date;
$tender->remarks = $request->remarks;
$tender->update($request->all());
});
return 'BID '.$tender->ref_no.' Succesfully Updated';
}
}
}
this is my route
Route::post('tender/update/{id}','Tender\TenderMasterController#update')->name('bid.update');
this is my blade
<form action="{{route('bid.update' ,Crypt::encrypt('id'))}}" class="form-horizontal" id="bid-update" method="POST">
{{ csrf_field() }}
#method('POST')
#include ('tender.form', ['formMode' => 'edit'])
</form>
Put this in your form action tag
<form action="/tender/update/{{Crypt::encrypt('id')}}" class="form-horizontal" id="bid-update" method="POST">
{{ csrf_field() }}
#method('POST')
#include ('tender.form', ['formMode' => 'edit'])
</form>
And replace this line of your controller:
$tender = TenderMaster::findOrFail($id);
With this:
$tender = TenderMaster::findOrFail(Crypt::decrypt($id));
And don't forget to add this line above in your controller
use Illuminate\Support\Facades\Crypt;
Hopefully it'll work
there's function encrypt and decrypt
but, i would like to disagree with idea of encrypting user id, its far from best practice
i would like to recommend you to use policy, policy guide
Use laravel builtin encryption to achieve this:
While adding your route in frontend, encrypt id with encryption helper like this:
{{route('bid.update', encrypt($id))}}
Now, In your controller, decrypt the id you have passed.
public function update($id, Request $request){
$ID = decrypt($id);
$tender = TenderMaster::findOrFail($ID);
..
...
}
I hope you understand.
Here is the docs:
https://laravel.com/docs/6.x/helpers#method-encrypt
https://laravel.com/docs/6.x/helpers#method-decrypt

Laravel form route not defined

I am trying to send a route the old way, without using Blade's {{}} tags. I am encountering a problem, because the framework throws my route as not defined. Can someone help me?
This is my form tag:
<form method="POST" action="{{ route('companyStore') }}">
My route
Route::post('companyStore', 'CompanyController#store');
My controller (the function name might help you undertand)
public function store(Request $request){
$company_name = $request->input('companyname');
$company_sector = $request->input('companyname');
$company_address = $request->input('companyaddress');
$company_phone = $request->input('companyphone');
$company_website = $request->input('companywebsite');
$company_representative = Auth::user()->id;
Company::create([
'name' => $company_name,
'sector' => $company_sector,
'address' => $company_address,
'phone' => $company_phone,
'website' => $company_website,
'representative_id' => $company_representative
]);
$company = Company::where('representative_id', $company_representative)->first();
User::where('id', $company_representative)->update(array('company_id' => $company->id));
return redirect('/admin/home');
}
The error is always:
Route [companyStore] not defined. (View:
When you use the route helper, it expects a named route. So define your route as this:
Route::post('companyStore', 'CompanyController#store')->name('companyStore');
or use:
<form method="POST" action="{{ url('/companyStore') }}">
or use:
<form method="POST" {{ action('CompanyController#store') }}>
You can define a route.
Route::post('companyStore', 'CompanyController#store')->name('companyStore');
and use this one:
<form method="POST" action="{{ route('companyStore') }}">
I don't know why #nakov has propsed {{ url('/companyStore') }}
Just Change
FORM
Route::post('companyStore', 'CompanyController#store');
TO
Route::post('companyStore', 'CompanyController#store')->name('companyStore');
Will just work

Multiple forms in one page in Laravel 5.1

I have one blade page has one form to update and another one to save
my question How i can submit both according to method type
I tried to achieve that like the following example
public function postCompanyProfileSettings(Request $request)
{
if($request->isMethod('POST')) {
// do something to save
}
if($request->isMethod('PUT')) {
// do something to update
}
}
it's working well with POST method but with PUT return Route Exception MethodNotAllowedHttpException in RouteCollection.php line 219:
I think that the issue in routs.php but i don't know what exactly to do to handle one route for multiple forms (multiple methods)
My route in route.php file
//setting routes...
get('/home/settings', 'CompanyProfileController#getCompanyProfileSettings');
post('/home/settings','CompanyProfileController#postCompanyProfileSettings');
Do there is any way to achieve that?
Alternatively you could use a hidden input
public function postCompanyProfileSettings(Request $request)
{
if(isset($request->get('update')) {
// do something to update
}
// do something to save
}
And routes..
post('/home/settings','CompanyProfileController#postCompanyProfileSettings');
In my opinion i'll use the same method which is POST.
1st form:
<form method="POST" action={{ url('vault/{batch_centre_id}/candidates/{id}', ['form' => '1']) }}>
2nd form:
<form method="POST" action={{ url('vault/{batch_centre_id}/candidates/{id}', ['form' => '2']) }}>
in your action check form:
if ($request->get('form') == 1) {
return $request->get('form');
} else if ($request->get('form') == 2) {
return $request->get('form');
}
return result;
So from the above you can have unlimited forms on a single page so long you tag your forms and verify them from your controller.
Check this answer

Categories