How to find the parameter name expected in laravel model route binding - laravel

I have a route like this
Route::get('/vcs-integrations/{vcs-provider}/authenticate','VcsIntegrationsController#authenticate');
and the method to handle the route I am using the model route binding to happen is as follows
<?php
....
use App\Models\VcsProvider;
....
class VcsIntegrationsController extends Controller
{
public function authenticate(VcsProvider $vcsProvider, Request $request)
{
...
// some logic
...
}
}
when I try to access the route I am getting 404 due to the parameter name is not matching.
So, how do I know the parameter name expected by laravel in route model binding ?

From the route parameter docs:
"Route parameters are always encased within {} braces and should consist of alphabetic characters, and may not contain a - character. Instead of using the - character, use an underscore (_)." - Laravel 7.x Docs - Routing - Route Parameters - Required Parameters
You should be able to define the parameter as {vcs_provider} in the route definition and then use $vcs_provider for the parameter name in the method signature if you would like. You can also name it not using the _ if you prefer, but just avoid the -, hyphen, when naming.
Have fun and good luck.

Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name.
This means that if you want implicit binding to work, you need to name the route param same as your variable. Since your variable's name is vcsProvider, your route should be:
Route::get('/vcs-integrations/{vcsProvider}/authenticate','VcsIntegrationsController#authenticate');

Related

Laravel edit controller not having data

I am trying to make crud in laravel. While doing dd of data variable in edit function attributes array is getting null
Route
Route::resource('/gameSettings', GameSettingController::class);
Controller
public function edit(GameSetting $game_setting)
{
dd($game_settings);
return view('admin.game_setting.edit', compact('game_setting'));
}
Model
class GameSetting extends Model
{
use HasFactory;
protected $fillable = [
'coin_value',
'minimum_withdraw_amount'
];
}
Link
https://localhost:8000/admin/gameSettings/1/edit
dd($game_settings); giving null array attribute
I dont have enough rep to comment so I give an answer...
#lagbox is correct. Your route parameter should match exactly as the variable typehinted in the controller for your case change $game_setting to $gameSetting
if you want to use $game_setting change your route to
Route::resource('/gameSettings', GameSettingController::class, ['parameters' => ['gameSetting' => 'game_setting']]);
The variable that you have typehinted on the Controller method must match exactly the name of the route parameter you have defined. In this case the parameter would be named gameSetting most likely. If you don't match these then you have Dependency Injection happening which would give you a new, non-existing, instance of the model. If you match the name then you will get Route Model Binding and it will look up the model and give you that particular entity.
If you want to see what the route parameter is named, since you are using resource routing, you can run php artisan route:list from the command line and it will show you those 7 routes and how they are defined.

can we pass post parameter in route in laravel?

I want to pass static value in route in laravel, is it possible in laravel ? here is what i have in route,
Route::post('manage-package', 'Api\App\HomeController#store');
I want to pass static value in this route, like params_one = 1, can we pass such parameter in route ? it will be great if anyone have something idea like this
One way to pass arbitrary data is to treat it like a route parameter by setting a default parameter on the route. This will cause that data to be passed to the route action as an argument just like if it was a route parameter:
Route::post('manage-package', 'Api\App\HomeController#store')
->defaults('params_one', 1);
public function store($params_one)
You could also use the 'actions' array of the Route but then would have to pull it from the route as opposed to having it passed like a parameter.
You can do that by defining an Optional Parameters in your route
Route::post('manage-package/{params_one?}', 'Api\App\HomeController#store');
And in the controller you define a default value of that parameter as the controller function receive each URL parameter as argument
public function store($params_one = 1){}
You can learn more about Optional Parameters

How will I identify resource default url in laravel?

I am running this command for model, migration, resource controller.
`php artisan make:model QuestionAnswer -mc -r` ..
Laravel give me in Resource Controller
public function show(QuestionAnswer $questionAnswer) {
// return $questionAnswer;
}
public function edit(QuestionAnswer $questionAnswer) {
// return $questionAnswer;
}
public function update(Request $request, QuestionAnswer $questionAnswer){
// return $questionAnswer;
}
if I write in web.php
Route::resource('question-answer','QuestionAnswerController'); or
Route::resource('questionAnswer','QuestionAnswerController'); or
Route::resource('question_answer','QuestionAnswerController'); laravel resolve route model binding...
that means....
Example as a
public function edit(QuestionAnswer $questionAnswer)
{
return $questionAnswer;
}
$questionAnswer return object for this url {{route('admin.question-answer.edit',$questionAnswer->id)}}
but if I write in web.php Route::resource('faq','QuestionAnswerController');
laravel can not resolve route model binding...
that means.. $questionAnswer return null for this url {{route('admin.faq.edit',$questionAnswer->id)}}
also in show and update function $questionAnswer; return null...
for working as a faq url.. i need change in edit function variable($faq) . or Route::resource('faq','QuestionAnswerController')->parameters(['faq' => 'questionAnswer']);I
But These three url questionAnswer,question-answer,question_answer by default work...
I check it on "laravel/framework": "^6.0" (LTS)
Question
is there possible way to find out what exact url I will write ? .. like question-answer.. or is there any command line ...
after running auth command .. php artisan route:list command give us all route list.. and when I make model Category laravel create table name categories and follow grammar rules
Actually Laravel has got Naming Convection Rules In its core.
These Convictions make it to default binding database_tables to model, model to controllers ....
if you want, you can tell your custom parameters but if you dont, The Laravel uses its own default and searching for them.
for example: if you have a model named bar, laravel look for a table named plural bars . and if you dont want this behave, you can change this default by overriding the *Models* $table_name` attribute for your custom parameter.
There are some Name Convection Rules Like :
tables are plural and models are singular : its not always adding s (es) in trailing.
sometimes it acts more complicate. like : model:person -> table: people
pivot table name are seperate with underline and should be alphabetic order: pivot between fooes and bars table should be bar_foo (not foo_bar)
table primary key for Eloquent find or other related fucntion suppose to be singular_name_id : for people table : person_id
if there are two-words name in model attribute, all of these are Alias :
oneTwo === one_two == one-two
check this out:
class Example extends Model{
public function getFooBarAttribute(){
return "hello";
}
}
all of this return "hello" :
$example = new Example();
$example->foo_bar();
$example->fooBar();
// $example->foo-bar() is not working because - could be result of lexical minus
there is a page listing laravel naming conventions :
https://webdevetc.com/blog/laravel-naming-conventions/
Name Conventions : is The Language Between The Laravel and Developer
it made it easy to not to explicitly mention everything
like Natural Language we can eliminate when we think its obvious.
or we can mention if its not (like ->parameter(...)).
How will I know I need to write question-answer this ? by default it works... when i write faq i need to change in edit function variable($faq) .
How will I know by default url (question-answer) will work ..when php
artisan route:list command give us all route list.. and when I make
model Category laravel create table name categories and follow grammar
rules
think about i will create 20 model ,migration & controller by cmd... i will not change edit,show and update function variable ...how i will know the default url for 20 model and controller ?
Laravel is an opinionated framework. It follows certain conventions
Let us understand a route parts
Route::match(
['PUT', 'PATCH'],
'/question-answer/{questionAnswer}',
[QuestionAnswerController::class, 'update']
)->name('question-answers.update')
In the above route:
1st argument: ['PUT', 'PATCH'] are the methods which the route will try to match for an incoming request
2nd argument: '/question-answer/{questionAnswer}' is the url wherein
/question-answer is say the resource name and
{questionAnswer} is the route parameter name
3rd argument: [QuestionAnswerController::class, 'update'] is the controller and the action/method which will be responsible to handle the request and provide a response
When you create a model via terminal using
php artisan make:model QuestionAnswer -mc -r
It will create a resource controller for the 7 restful actions and take the method parameter name for show, edit, update and delete routes as camel case of the model name i.e. $questionAnswer
class QuestionAnswerController extends Controller
{
public function show(QuestionAnswer $questionAnswer){}
public function edit(QuestionAnswer $questionAnswer){}
public function update(Request $request, QuestionAnswer $questionAnswer){}
public function delete(QuestionAnswer $questionAnswer){}
}
Which means if you don't intend to change the parameter name in the controller methods then you can define the routes as below to get the benefit of implicit route model binding
//Will generate routes with resource name as questionAnswer
//It would not be considered a good practice
Route::resource('questionAnswer', QuestionAnswerController::class);
//OR
Route::resource('question-answer', QuestionAnswerController::class)->parameters([
'question-answer' => 'questionAnswer'
]);
//OR
Route::resource('foo-bar', QuestionAnswerController::class)->parameters([
'foo-bar' => 'questionAnswer'
]);
RFC 3986 defines URLs as case-sensitive for different parts of the URL. Since URLs are case sensitive, keeping it low-key (lower cased) is always safe and considered a good standard.
As you can see, you can name the url resource anything like foo-bar or question-answer instead of questionAnswer and yet keep the route parameter name as questionAnswer to match the Laravel convention when generating controller via php artisan make:model QuestionAnswer -mc -r and without having to change the parameter name in controller methods.
Laravel is an opinionated framework which follows certain conventions:
Route parameter name ('questionAnswer') must match the parameter name in controller methods ($questionAnswer) for implicit route model binding to work
Controller generated via artisan commands, have parameter name as camelCase of the model name
Routes generated via Route::resource('posts', PostController::class) creates routes with resource name equal to the first argument of the method and route parameter name as the singular of the first argument
Route::resource() provides flexibility to use a different name for route resource name and route parameter name
Read more at Laravel docs:
https://laravel.com/docs/8.x/controllers#restful-naming-resource-route-parameters
https://laravel.com/docs/8.x/controllers
https://laravel.com/docs/8.x/routing#route-model-binding
If you want to know how the php artisan make:model works you can study the code in vendor/laravel/framework/src/Illuminate/Foundation/Console/ModelMakeCommand.php and have a look at the various stubs these commands use to generate the files.
For almost all artisan commands you will find the class files with code in
vendor/laravel/framework/src/Illuminate/Foundation/Console and the stubs used by the commands to generate files in vendor/laravel/framework/src/Illuminate/Foundation/Console/stubs folder.
If you study these command classes properly then you will get an idea of the various conventions Laravel follows when generating files via the artisan commands
I think its becuse of dependency injection which you used in youre method.
Try this
public function edit($id)
{
// return $questionAnswer;
return view('backend.faq.edit',get_defined_vars());
}

How to route an dynamic url?

I am new to laravel. I am defining this route to an edit button:
<button class="btn btn-primary">Edit task</button>
The url is generated fine but the page is not found. I am returning a view with my TaskController#edit with this route:
Route::get('/editTasks/{{ $task->id }}', 'TaskController#edit');
Can someone help me out figuring what i am doing wrong?
When defining routes, the route parameters should only have one { around them. Also, you should not use a variable in the declaration but a name for the variable.
In your example, this could be a valid declaration:
Route::get('/editTasks/{id}', 'TaskController#edit');
More information can be found in the docs: https://laravel.com/docs/5.7/routing#route-parameters
It is also recommended to use route names, so the url can be automatically generated.
For example:
// Route declaration
Route::get('/editTasks/{id}', 'TaskController#edit')->name('tasks.edit');
// In view
Edit task
no you have to define in your route just like this :
Route::get('/editTasks/{id}', 'TaskController#edit');
you don't have $task in your route and you dont need to write any other thing in your route. in your controller you can access to this id like this :
public function edit($taskId) {
}
and only you do this
You need to use single { instead of double, so it needs to be the following in your route:
Route::get('/editTasks/{taskId}', 'TaskController#edit');
And in your edit function:
public function edit($taskId) { }
The double { in the template is correct as this indicates to retrieve a variable
Extra information/recommendation:
It is recommended to let the variable name in the route match the variable in your function definition (as shown above), so you always get the expected variable in your function. If they do not match Laravel will use indexing to resolve the variable, i.e. if you have multiple variables in your route pattern and only use one variable in the function it will take your first route parameter even if you might want the second variable.
Example:
If you have a route with the pattern /something/{var1}/something/{var2} and your function is public function test($variable2) it would use var1 instead of var2. So it it better to let these names match so you always get the expected value in your function.
It's better to use "Route Model Binding". Your route should be like this:
Route::get('/editTasks/{task}', 'TaskController#edit');
And in Controller use something like this:
public function edit($task){
}

AttributeRouting conflicting parameter route with string route

I have two controllers, ItemsController and SingleItemController which both inherit from ApiController. Both have RoutePrefix items/inventory defined on the controllers, like so:
[RoutePrefix("items/inventory")]
I'm using AttributeRouting in Web API 2.2.
In SingleItemController I have the following route:
[Route("{itemReference}")]
[HttpGet]
public ItemDTO GetItem(string itemReference)
In ItemsController I have the following route:
[Route("all")]
[HttpGet]
public List<ItemDTO> GetAllItems(DateTime dateFrom, DateTime dateTo)
When I try to hit the /items/inventory/all?dateFrom=2015-09-06&dateTo=2015-09-12 route, I get the following error:
Multiple controller types were found that match the URL. This can
happen if attribute routes on multiple controllers match the requested
URL. The request has found the following matching controller types:
ItemAPI.Controllers.ItemsController
ItemAPI.Controllers.SingleItemController
So {itemReference} route is conflicting with all route. Why is this? I would think that it reserves first all route and then allows an optional string route.
This is because it can't decide whether "all" is an item reference.
I had a similar issue recently where I had a controller with an "admin" route prefix.
To get round the issue I put a constraint on the parameter to ignore the word "admin".
So in your case you could do the following to ignore the word "all":
[Route("{itemReference:regex(^(?!all))})]

Resources