Laravel Route Group Second Parameter? - php

I updated my project from laravel 5.5.* to 5.5.43... Before the update everything was ok. But after the update, I see a warning message in route/web.php.
It says: Required parameter $routes missing.
But everything is working fine. Then when I put an empty string in the second parameter warning message gone.
So my question is:
What should I put in the required second parameter?
If it's required then why everything is working fine? It should be optional.

This is actually pretty hard to follow in Laravel. Your IDE is pulling the group definition from Router instead of RouteRegistrar.
Inside Router.php:
public function group(array $attributes, $routes)
This supports the older style of route group definitions where middleware are defined in attributes and your routes closure would be the 2nd argument.
Inside RouteRegistrar.php:
public function group($callback)
This is the new style where group only accepts the closure.
I don't like the fact that they used a condition in __call instead of defining a method for middleware, but when you call Route::middleware, the facade forwards to Router and Router::__call is returning a RouteRegistrar instance because of this line:
if ($method == 'middleware') {
return (new RouteRegistrar($this))->attribute($method, is_array($parameters[0]) ? $parameters[0] : $parameters);
}

Related

Laravel Model data not available in Controller

I'm new to Laravel. I might be making a basic mistake here but I've been trying and researching for a while, need some guidance here.
I have 2 routes:
Route::get('ordercontents/{ordercontent}', 'App\Http\Controllers\OrderContentsController#edit');
Route::get('ordercontents/delete/{ordercontents}', 'App\Http\Controllers\OrderContentsController#destroy');
Inside OrderContentsController.php I have the 2 functions, one to edit a record and another to delete it.
public function edit(\App\Models\Order_content $ordercontents)
{
dd($ordercontents); //the attributes will come out empty
$orderContentId = $ordercontents->id;
$ocs = getOrderContentDetails($orderContentId);
return view('ordercontents.edit')->with('ordercontents', $ocs);
}
public function destroy(\App\Models\Order_content $ordercontents)
{
$orderId = $ordercontents->order_id;
$ordercontents->delete();
return redirect('/new-ordercontent/' . $orderId)->with('success', 'Material removido da ordem de serviço!');
}
The model exists and is called Order_content.
Everything works well for the destroy function.
However, I'm struggling with the edit function.
If I do a dd($ordercontents); the attributes array of the object comes empty inside the edit function.
What am I missing? Thanks!
You have to make sure the name of the variable that is type-hinted in your method signature matches the route parameter for Route Model Binding:
"Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name." - Laravel Docs
The method signature for edit can be adjusted to match the route parameter name:
public function edit(\App\Models\Order_content $ordercontent)
When these do not match you will have Dependency Injection happening so a new non-existing Model instance would be injected.
Laravel 8.x Docs - Routing- Route Model Binding - Implicit Binding

How to rename route key with model binding in PHP Laravel 8 (incorrect plurals)?

I have a Laravel 8 project where I have a model called FieldOfStudy, but the problem is that the plural of this class's name should be fields of study instead of field of studies. That causes a problem when creating an API endpoint with the following route:
Route::apiResource('fields-of-study', FieldOfStudyController::class);
The thing is, that I have a resource controller's method FieldOfStudyController::show() like this:
public function show(FieldOfStudy $fieldOfStudy)
{
dd($fieldOfStudy);
}
This will show me, that $fieldOfStudy contains a "blank" model, not the desired instance from the database. When I checked the route parameters, I found out, that the id of the model is stored as fields_of_study instead of field_of_study.
I tried to rename the parameter (didn't work - binding fails):
Route::apiResource('fields-of-study', FieldOfStudyController::class)->parameter('fields_of_study','field_of_study');
When I rename the parameter of the show() method, it works, but it's not really pretty:
public function show(FieldOfStudy $fieldsOfStudy) { }
How can I properly adjust my code to:
keep the URI in the correct plural (i.e. /fields-of-study),
keep the show() parameter name in the correct singular (i.e. $fieldOfStudy) and
don't mess the model-binding mechanism for typed parameters like show(FieldOfStudy $fieldOfStudy)?
Thank you :)
You can manipulate Laravel explicit binding:
RouteServiceProvider.php
public function boot()
{
Route::model('fields-of-study', FieldOfStudy::class);
}

Resource Controller methods with model as parameter not working

As in the basic Laracasts.com tutorial (Laracast 5.7 from scratch) I'm trying to use the following methods public function show(prototypes $prototypes) parameter to construct a view. However my view is created correctly but $prototypes is null.
The route works well(/prototypes/1/edit) and I ensured that a prototype object with the id 1 exists.
I found some older solution which stated to use something like (integer $id) as parameter but this leads to some more code. It should work like this:
Controller:
public function edit(prototypes $prototypes)
{
//
return view('prototypes.edit', compact('prototypes'));
}
According to Laracast From Scratch this should work.
Do you know how I could fix this?
What mechanism is behind this that the prototypes.edit method knows how to use the correct parameter?
For the Implicit Model Binding to works the injected variable name should match the route parameter name, in your case I think that your parameter name could be {prototype}, you can verify it by issuing the command php artisan route:list in the console.
If that is true you have to change the variable name to $prototype (please note the singular) in your controller function to match the parameter name {prototype}, like this:
public function edit(prototypes $prototype)
{
return view('prototypes.edit', compact('prototype'));
}
Update: BTW the laravel convention on Model's name is singular camel case, in your case your Model should be named Prototype not prototypes, i.e.:
public function edit(Prototype $prototype)
{
return view('prototypes.edit', compact('prototype'));
}
In order to inject the Prototypes model into the controller variable $prototypes, Laravel is expecting a matched name from the route to the input of the method. So in your routing, this:
/prototypes/1/edit
Needs to be
/prototypes/{prototypes}/edit
in order for the edit method to inject the correct instance of your prototypes model.

How to access values of multiple parameters passed to Laravel controller

I am trying to figure out how to access two (or more) parameters passed to a Laravel controller. I know how to create the route, and the URL is created correctly, but then I can only access the first passed parameter in my controller.
Route:
Route::get('managers/{id}/{parameter2}', array('as'=>'dosomething', 'uses'=> 'ManagersController#dosomething'));
where the first parameter is obviously the $id for managers, and the second parameters is to be processed by the controller.
View:
Do Something
generates the URL:
http://domain/managers/1/2
where 1 is easily accessed as the $id for managers, but when I try to access the 2nd parameter "2" using $parameter2, e.g. using a simple return: "id=$id and parameter2=$parameter2" statement, I get an "unidentified variable: $parameter2" error.
What am I doing wrong?
Is there a better way to pass multiple parameters? I'm especially asking the "better way?" question because what I want to do is use the 2nd parameter to change a value in a database table, and using a 'get' method, somebody could change the parameter value in the URL and therefore cause mischief. Must I use a 'post' method? I'd love to be able to use a link, since that works much better with the design of my application.
Thanks!
I was asked to include the controller, which I'm happy to do. Initially, just for testing, as I mentioned, my controller was a simple return to display the values of the two passed parameters. But here is what I want to be able to do, including the actual name of the function ("update_group" rather than "dosomething") --
ManagersController:
public function update_group($id)
{
DB::table('groups')->where('id','=',$parameter2)->update(array('manager_id'=>$id));
return Redirect::route('managers.show', array('id'=>$id));
}
The update table works perfectly if I replace $parameter2 with an actual value, so that syntax is fine. The issue is that Laravel says that $parameter2 is an undefined variable, despite the fact that the URL contains the value of $parameter2 as you can see above.
And since it occurs to me that the answer to this may involve adding a function to the Manager model, here is the current
Manager.php
class Manager extends Eloquent {
protected $table = 'managers'; ... (mutator and error functions)
}
Just change
public function update_group($id)
to
public function update_group($id, $parameter2)
All looks ok in your route. Seeing the controller code would help, but likely, you may not have a second parameter in your controller's dosomething() method.
public function dosomething($id, $parameter2){
var_dump($id).'<br />';
var_dump($paremter2);
}
If that isn't the case, you can try dumping it from the route's callback to further diagnose.
Route::get('managers/{id}/{parameter2}', function($id, $parameter2)
{
var_dump($id).'<br />';
var_dump($paremter2);
});
Depending on your use case, you can pass them in a query string like so: but it isn't really the 'best way', unless you're doing something like building an API that won't use the same variables in the same order all the time.
/managers?id=1&paramter2=secondParameter
var_dump(Request::query('id')).'<br />';
var_dump(Request::query('paramter2'));

How to create optional REST parameter in Laravel

I'd like my API to handle calls of the such:
/teams/colors
/teams/1/colors
The first would return all colors of all teams, the second would return colors of team 1 only.
How would I write a route rule for this in Laravel?
This should be simple using a laravel route.
Route::pattern('teamid', '[0-9]+');
Route::get('/teams/{teamid}/colors', 'controller#method');
Route::get('/teams/colors', 'controller#method');
Using the pattern, it lets you specify that a route variable must match a specific pattern. This would be possible without the pattern also.
I noticed you mentioned REST in the title. Note that my response is not using Laravel's restful routes system, but its normal routes system, but I'm sure this could be adapted to be restul, or work with the restful system.
Hope this helps.
Edit:
After a bit of looking around, you may be able to use this if you are using Route::resource or Route::controller.
Route::resource('teams', 'TeamsController');
Route::any('teams/{teamid}/colors', 'TeamsController#Method');
// Or to use a different route for post, get and so on.
Route::get('teams/{teamid}/colors', 'TeamsController#getMethod');
Route::post('teams/{teamid}/colors', 'TeamsController#postMethod');
Note: the resource word above can be replaced with ::controller.
*Note 2: I have not tested this and am unable to guarantee it would work, but it does seem possible.*
You may try something like this:
class TeamsController extends BaseController {
// GET : http://example.com/teams
public function getIndex()
{
dd('Colors of all teams');
}
// GET : http://example.com/teams/1/colors
public function getColorsById($id)
{
dd("Colors of team $id");
}
// This method will call the "getColorsById" method
public function missingMethod($parameter = array())
{
if(count($parameter) == 2) {
return call_user_func_array(array($this, 'getColorsById'), $parameter);
}
// You may throw not found exception
}
}
Declare a single route for both methods:
Route::controller('/teams', 'TeamsController');

Categories