Stumpped trying to pass two parameters from view form to controller - laravel

I have a Laravel 6 app and am trying to pass two parameters from my view's form to my controller via a resource route. I can pass one, no problem, but passing two gives the same error:
Too few arguments to function App\Http\Controllers\Admin\SubscriptionsController::update(), 1 passed and exactly 2 expected
I've tried many different arrangements suggested from other posts but none bring the desired result.
Here's my route:
Route::resource('subscriptions', 'Admin\SubscriptionsController')
Here's my form in my view:
{{ Form::open(['route' => ['admin.subscriptions.update', $plan->id, $coupon_code], 'method' => 'PUT', 'id' => 'role-' . $plan->id, $coupon_code]) }}
Coupon Code: <input type="text" name="coupon_code">
{{ Form::close() }}
Here's my controller. It doesn't reach the dd() test.
public function update($id, $coupon_code)
{
dd($coupon_code);
...
In the error Whoops! page, I can see the POST DATA that $coupon_code is being sent over.
However, if I remove the $coupon_code parameter from the controller (leaving public function update($id) ) it functions fine passing $id from form to controller, but I don't get the $coupon_code data I need to process. Adding the second parameter bombs it.
Any suggestions are very welcome.

As you are using the resource controller, it won't allow you to pass additional fields directly to its update() route. Instead, you have to override the update route.
Here is how you can do it, Immediately below your resource.
You can add a new route as below:
// web.php
Route::resource('subscriptions', 'Admin\SubscriptionsController')
// Make sure you add name when you are overriding the route
Route::put('subscriptions/{subscription}/{coupon_code?}', 'Admin\SubscriptionsController#update'])->name('admin.subscriptions.update');
I believe you won't be sending the coupon code every time so you can add {coupon_code?} which becomes optional.
In you controller's update() method, make the coupon_code optional
public function update($id, $coupon_code = null)
{
...
}

You can not add a new param for Route::resource. If you really want to take 2 params, you should create a new route.
for an example:
Route::resource('subscriptions', 'Admin\SubscriptionsController')->except('update');
Route::put('/subscriptions/{id}/{coupon_code}', 'Admin\SubscriptionsController#update')->name('subscriptions.update');
But I think it's better not using method params. Why not just using input form?
so we can process the coupon code like this:
request()->coupon_code;

Related

Passing data from blade to blade in Laravel

I have a page where you can create your workout plan. Second page contains "pre-saved" workouts and I want them to load by passing parameters from second page to first. If you directly access first page, you create your workout plan from scratch.
// first page = https://prnt.sc/y4q77z
// second page = https://prnt.sc/y4qfem ; where you can check which one you want to pass to first page
// final step looks like this: https://prnt.sc/y4qh2q - but my URL looks like this:
www.example.com/training/plan?sabloni%5B%5D=84&sabloni%5B%5D=85&sabloni%5B%5D=86
this 84,85,86 are IDS
Can I pass params without changing URL ? Like having only /training/plan without anything after ?
public function plan(Request $request){
$workout = false;
if($request->workout){
$workout = $request->workout;
$workout = SablonTrening::find($sabloni); // $workout = array [1,3,4,5,6]
}
return view('trener.dodaj_trening', compact('workout'));
}
If you are getting to the /training/plan page with GET request, you could simply change it to POST. That way the parameters would be hidden in the URL but would be present in the request body. You would need a new post route:
Route::post('/training/plan', 'YourController#plan')->name('training.plan');
And then, in the form where you are selecting these plans, change the method on submit:
<form action="{{route('training.plan')}}">
//Your inputs
</form>
Your method should still work if your inputs stay the same.
Note: Not sure you would still keep the functionalities that you need, since I can't see all the logic you have.
If you have any questions, let me know.
To pass data from on blade to another blade.
At the end of first post before redirect()-route('myroute') add $request->session()->put('data', $mydata);
At the begining of the route 'myroute', just get back your data with $data = $request->old('data');

Not able to get Route parameter - Laravel 6

I have tried multiple solution but nothing worked yet, i am trying to get route Parameter in controller that was passed from a view.
Here is how i have created the route:
Route::get('addOptions/{questionId}', 'QuestionController#addOptions')->name('addOptions');
Here is how i am passing parameter to route from view:
Add Options
And here is what i am trying to get in controller but it's returning empty array:
public function addOptions(Request $request)
{
$allParameters = $request->input(); //not working
//$allParameters = $request->all(); //not working
//$allParameters = Input::all(); //not working
return $allParameters;
}
It returns empty array [] like this.
EDIT: But url at route addOptions look like this http://127.0.0.1:8000/admin/addOptions/4 in which 4 is questionId which means parameter is being passed but not retrieved.
What am I doing wrong here? Please guide, Thanks.
You should be passing the route like this:
Add Options
as for Laravel docs. the route params are passed an array with the key referencing the param
$url = route('profile', ['id' => 1]);
To retrieve the data in your controller, you should use:
$request->route()->paremeters()
or
$request->route('parameter_name')
If you want to pass the parameter
Add Options
I think your function parameters are wrong
You are passing question id from Route So your function should be like
public function addOptions($questionId)
{
$allParameters = $questionId; // you question ID passed throught Route
return $allParameters;
}

Laravel route difference between {id} vs {tag}

I am new in Laravel pardon me if question is silly. I have seen a doc where they used
For get request
Route::get("tags/{id}","TagsController#show");
For put request
Route::put("tags/{tag}","TagsController#update");
What is the difference and benefit between this ? I understood 1st one, confusion on put route.
There’s no real difference as it’s just a parameter name, but you’d need some way to differential parameters if you had more than one in a route, i.e. a nested resource controller:
Route::get('articles/{article}/comments/{comment}', 'ArticleCommentController#show');
Obviously you couldn’t use just {id} for both the article and comment parameters. For this reason, it’s best to use the “slug” version of a model for a parameter name, even if there’s just one in your route:
Route::get('articles/{article}', 'ArticleController#show');
You can also use route model binding. If you add a type-hint to your controller action for the parameter name, Laravel will attempt to look up an instance of the given class with the primary key in the URL.
Given the route in the second code example, if you had a controller that looked like this…
class ArticleController extends Controller
{
public function show(Article $article)
{
//
}
}
…and you requested /articles/123, then Laravel would attempt to look for an Article instance with the primary key of 123.
Route model binding is great as it removes a lot of find / findOrFail method calls in your controller. In most instances, you can reduce your controller actions to be one-liners:
class ArticleController extends Controller
{
public function show(Article $article)
{
return view('article.show', compact('article'));
}
}
Generally there's no practical difference unless you define a custom binding for a route parameter. Typically these bindings are defined in RouteServiceProvider as shown in the example in the docs
public function boot()
{
parent::boot();
Route::model('tag', App\Tag::class);
}
When you bind tag this way then your controller action can use the variable via model resultion:
public function update(Tag $tag) {
// $tag is resolved based on the identifier passed in the url
}
Usually models are automatically bound so doing it manually doesn't really need to be done however you can customise resolution logic if you do it manually
Normal way
Route::get("tags/{id}","TagsController#show");
function($id)
{
$tag = Tag::find($id);
dd($tag); // tag
}
With route model bindings
Route::put("tags/{tag}","TagsController#update");
function(Tag $tag) // Tag model binding
{
dd($tag); // tags
}
ref link https://laravel.com/docs/5.8/routing#implicit-binding
It's just a convention. You can call it all you want. Usually, and {id} refers to the id in your table. A tag, or similarly, a slug, is a string value. A tag could be 'entertainment' for video categories, while 'my-trip-to-spain' is a slug for the description of a video.
You have to chose the words what you are comfortable with. The value will be used to find in your database what record is needed to show the correct request in the view. Likewise you can use video/view/{id}/{slug} or any combination thereof.
Just make sure your URLs don't get too long. Because search engines won't show your website nicely in search results if you do. Find the balance between the unambiguous (for your database) and logic (for your visitors).
Check this out: Route model bindings
Use id, Laravel will get the id from route, and it will be the tag's id, it is integer.
function show($id) {
$tag = Tag::find($id);
}
Use tag, Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name.
In URL, your tag parameter is integer, however in your controller action $tag will be a model object:
function action(Tag $tag) {
$tag->name;
}
So you don't need to get the $tag by eloquent in your controller action. You just need to specify it is From model Tag $tag
It will do it automatically.

How to catch get parameter and cast it to int in Laravel?

I have the following controller:
class CustomerController extends Controller
{
public function index(int $customerId = 0) : Renderable
{
dd($customerId);
...
And I'm requesting it by the following url http://localhost/customers?customerId=123. I would like to catch customerId as int. But It always gives 0 (default value the for method's signature). Ok, I can do something like:
$customerId = $request->input('customerId');
But the approach with getting parameter from the method's signature is more attractive for me.
I have seen this answer. It looks like very nice! But it does not work for my case. Why? Where is the mistake? Thank you for attention!
Update
Here I will show my routes definitions:
Auth::routes(['register' => false, 'reset' => false]);
Route::middleware('auth')->group(function () {
Route::resource('customers', 'CustomerController');
});
If you want to use the Resource Route you have to pass the customerID parameter like below. And also you have to use one of these methods: show, edit,update or destroy in your controller.
Route::resource('customers', 'CustomerController')->parameters([
'customers' => 'customerId'
]);
For more details: https://laravel.com/docs/5.7/controllers#resource-controllers
AFAIK Laravel doesn't inject parameters this way.
If such URI is really needed - you should manually inspect request input for your variables.
If you want to use controller as written, you should use route parameters (e.g. /customers/{id}) instead of parameters after ?.
By default resource controllers use index() for displaying all entities and show() for displaying only one entity.
If you use Eloquent, you can also inject Customer model, e.g.
public function index(Customer $customer) : Renderable
Customer will be automatically found by id and injected in controller method.

How to use the rule validation in FormRequest class?

I have a Company, where I like to validate the update request. Until now I validated the request inside the update() action but I like to move this to its own CompanyUpdateRequest.
In the validation I check of the uniqueness of the tax number but of course I like to allow the same tax number for the very company.
'tax_number' => [
'required',
'string',
Rule::unique('companies')->ignore($company->tax_number),
],
This works as long it is placed inside the action, where I have $company already:
public function update(Request $request, Company $company)
{
}
My question is now, how I get the company inside the CompanyUpdateRequest?
I know that I could put the ID of the company inside a hidden field in the form, send it along with the request, pull the company from DB ... but this feels kind of wrong. Does anybody have a better / another approach or idea?
Thanks a lot.
use route() method. Assume your route parameter name is company-
$this->route('company');
Note: parameter method inside route method needs to exactly same as url route parameter. In this case-
Route::post('yourUrl/{company}','SomeController#method');
You can pass any data through a form:
<input name="company_id" value="{{ $company->tax_number }}" type="hidden">
Then in the CompanyUpdateRequest class:
Rule::unique('companies')->ignore($request->company_id),
You can also change this rule to:
'companies' => 'unique:companies,company_id,' . $request->company_id,
You can get it with $this->route('paramName');
Rule::unique('companies')->ignore($this->route('company')),

Resources