So if you do something like
$ artisan make:model TurboClown
$ artisan make:controller TurboClownController -r --model=TurboClown
So at this point it's possible to add something like:
Route::resource('clowns','TurboClownController');
To your routes/web.php. Now I have routes like clowns/{clown} when I routes:list with artisan.
However, my show function is like:
public function show(TurboClown $turboClown)
Which when you return $turboClown will just give [] as a response when you request "/clowns/3/" for example. It took me a while to figure out that if I change $turboClown parameter to $clown, I get a JSON TurboClown as a response.
So in a sense, I solved my problem. But I'm curious about a couple points:
To me, https://laravel.com/docs/5.4/controllers#restful-naming-resource-route-parameters reads as if I could add ['parameters' => ['clown' => 'turboClown'] and then show() would work using "turboClown", but it does not.
According to https://laravel.com/docs/5.4/routing#route-parameters : " Route parameters are injected into route callbacks / controllers based on their order - the names of the callback / controller arguments do not matter." But it looks like the name of the parameter does matter in this case?
So I am looking for some kind of clarification on those two points, what am I missing?
You are doing it wrong. The documentation says:
The parameters array should be an associative array of resource names and parameter names
So in your case the resource name is "clowns" (and not "clown") and you want for this resource name the parameter to be "turboClown:
Route::resource('clowns', 'TurboClownController', ['parameters' => [
'clowns' => 'turboClown'
]]);
I agree that this point can be confusing. Maybe you already know that but what you are doing here is called implicit route model binding. And for it to be "implicit", there is one rule overruling the one you mentioned:
Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name.
Also for this pretty cool thing to work the parameter has to match an identifier for the corresponding model (in your case TurboClown).
So now combining those two points you should be able to do this:
In your routes file:
Route::resource('clowns', 'TurboClownController', ['parameters' => [
'clowns' => 'turboClown'
]]);
In TurboClownController:
public function show(TurboClown $turboClown)
{
return $turboClown;
}
Now let's say you want to retrieve the turbo clown with the identifier 5. You can cal the route http://example.dev/clowns/5.
Hope it helped.
Related
I'm just playing around with my code and notice that one of my controller is returning empty attributes but the other is returning my data fine.
I have two controllers, OneController and TwoController with both resource and same model in it. I use the php artisan make:controller OneController --model==MyModel
and php artisan make:controller TwoController --model==MyModel. two different controller with similar model.
Both have
public function show(MyModel $myModel)
{
dd($myModel);
}
But only theOneController#show is returning my data...
My links are like this
{{route('one.show', $myModel->id) }}
and
{{route('two.show', $myModel->id) }}
I also run php artisan route:clear
I change my TwoController#show to show($id) and it is working fine but I can't ignore that the same code is giving me different results and I want my code to be as clean as possible.
Is there any rule in Laravel 5.8 that you can only use One controller per model on a resource?
Am I missing something?
Thanks!
You're injecting the model you want into your controller action, instead of fetching the record yourself using the ID parameter. Because you're using this you need to adhere to certain rules - read the route model binding documentation for more information.
Long story short: the name of the parameter in the route definition and the name of the argument in the controller action need to match in order for route model binding to take place - otherwise a new model instance will be passed to the method.
Because you're using the Route::resource() method instead of defining routes yourself Laravel will automatically call the parameter by the path you pass in. You can verify this by running php artisan route:list.
To achieve this with a resource you'll need to manually name the resource parameters, which would effectively be something like Route::resource('two', 'TwoController')->parameters(['two' => 'myModel']) where myModel would be your model name.
I'm trying to generate a url with parameter using laravel route helper,
route('frontend.admin.categories.edit', $catRequest->id)
but this is the generated url
http://localhost:8000/admin/categories/edit?1
I need a URL like this
http://localhost:8000/admin/categories/edit/1
And this is my route
Route::get('admin/categories/edit/{id}', 'CategoryController#edit')
->name('admin.categories.edit');
What is the issue here?
You can specify the parameter(s) you are replacing by passing an associative array instead of a variable.
Change,
route('frontend.admin.categories.edit', $catRequest->id)
To
route('frontend.admin.categories.edit', [
'id' => $catRequest->id
]);
Edit #1
You are calling the wrong route, you named your route as admin.categories.edit in the definition yet you are calling frontend.admin.categories.edit within the helper function which is not the originally defined route. So your code should be:
route('admin.categories.edit', [
'id' => $catRequest->id
]);
Reading Material
Named Routes
You need to use an array for your params :
route('frontend.admin.categories.edit', ['id' => $catRequest->id])
If not, all params will be used as $_GET params.
Try to view your route list using php artisan route:list. If you found your route in list with correct Uri then see that you are not again specify that route with same Uri or same alias name in your route file.
Hope this helps :)
You may have another route with the same name right after this one in the code that may be overwriting the above route params, i had the same problem and in my case this is what was happening, i had two routes definitions using the same name but with different http methods like the example below.
Ex:
Route::get('/route1/{param1}');
Route::post('/route1');
redirect()->route('/route1', ['test']); // output: /route1?test
When i've changed it to:
Route::post('/route1');
Route::get('/route1/{param1}');
redirect()->route('/route1', ['test']); // output: /route1/test
then i got the desired result.
I'm currently using Laravel 5.3 and i have a number of routes similar to.
Route::get('/news/create/{product}', 'NewsController#create')->name('news::create');
So in my blade template im using the route() function like so:
{{route('news::create','car')}}
But the url generated is
/news/create?car
not the required
/news/create/car
The same thing happens if i put it in an array:
{{route('news::create',['car'])}}
And if i give it a key like so:
{{route('news::create',['product'=>'car'])}}
I get:
/news/create?product=car
How do I get the correct url so it is passed to the 'create' function as a parameter?
Firstly, take a look at your route naming. I don't think there's anything specifically wrong with naming a route like 'news::create' apart from it being ugly and quite probably considered bad practice. I like to go with camel casing, which means I'd use a name like createNews. It's much easier when going back to work on old sections of code and will stop other programmers from stabbing you if/when they work on a project with you.
The reason we can name routes is so that the name stays static even if we change the route URI or controller endpoint. We can pass variables to it using route parameters.
Route::get('/news/create/{product}', array('as' => 'createNews', 'uses' => 'NewsController#create'));
route('createNews', ['product' => 'car']);
{{route('news::create',['product => 'car'])}}
Should fix your problem. Laravel uses named routes and expects an array with the keys as names with values.
Read all about it here: https://laravel.com/docs/5.3/redirects#redirecting-named-routes
I've been reading everywhere but couldn't find a way to redirect and include parameters in the redirection.
This method is for flash messages only so I can't use this.
return redirect('user/login')->with('message', 'Login Failed');
This method is only for routes with aliases my routes.php doesn't currently use an alias.
return redirect()->route('profile', [1]);
Question 1
Is there a way to use the path without defining the route aliases?
return redirect('schools/edit', compact($id));
When I use this approach I get this error
InvalidArgumentException with message 'The HTTP status code "0" is not valid.'
I have this under my routes:
Route::get('schools/edit/{id}', 'SchoolController#edit');
Edit
Based on the documentation the 2nd parameter is used for http status code which is why I'm getting the error above. I thought it worked like the URL facade wherein URL::to('schools/edit', [$school->id]) works fine.
Question 2
What is the best way to approach this (without using route aliases)? Should I redirect to Controller action instead? Personally I don't like this approach seems too long for me.
I also don't like using aliases because I've already used paths in my entire application and I'm concerned it might affect the existing paths if I add an alias? No?
redirect("schools/edit/$id");
or (if you prefer)
redirect("schools/edit/{$id}");
Just build the path needed.
'Naming' routes isn't going to change any URI's. It will allow you to internally reference a route via its name as opposed to having to use paths everywhere.
Did you watch the class Illuminate\Routing\Redirector?
You can use:
public function route($route, $parameters = [], $status = 302, $headers = [])
It depends on the route you created. If you create in your app\Http\Routes.php like this:
get('schools/edit/{id}', 'SchoolController#edit');
then you can create the route by:
redirect()->action('SchoolController#edit', compact('id'));
If you want to use the route() method you need to name your route:
get('schools/edit/{id}', ['as' => 'schools.edit', 'uses' => 'SchoolController#edit']);
// based on CRUD it would be:
get('schools/{id}/edit', ['as' => 'schools.edit', 'uses' => 'SchoolController#edit']);
This is pretty basic.
PS. If your schools controller is a resource (CRUD) based you can create a resource() and it will create the basic routes:
Route::resource('schools', 'SchoolController');
// or
$router->resource('schools', 'SchoolController');
PS. Don't forget to watch in artisan the routes you created
I am new to Laravel 5 and I am trying to use the new Form Request to validate all forms in my application.
Now I am stuck at a point where I need to DELETE a resource and I created a DeleteResourceRequest for just to use the authorize method.
The problem is that I need to find what id is being requested in the route parameter but I cannot see how to get that in to the authorize method.
I can use the id in the controller method like so:
public function destroy($id, DeletePivotRequest $request)
{
Resource::findOrFail($id);
}
But how to get this to work in the authorize method of the Form Request?
That's very simple, just use the route() method. Assuming your route parameter is called id:
public function authorize(){
$id = $this->route('id');
}
You can accessing a Route parameter Value via Illuminate\Http\Request instance
public function destroy($id, DeletePivotRequest $request)
{
if ($request->route('id'))
{
//
}
Resource::findOrFail($id);
}
Depending on how you defined the parameter in your routes.
For my case below, it would be: 'user' not 'id'
$id = $this->route('user');
Laravel 5.2, from within a controller:
use Route;
...
Route::current()->getParameter('id');
I've found this useful if you want to use the same controller method for more than one route with more than one URL parameter, and perhaps all parameters aren't always present or may appear in a different order...
i.e. getParameter('id')will give you the correct answer, regardless of {id}'s position in the URL.
See Laravel Docs: Accessing the Current Route
After testing the other solutions, seems not to work for laravel 8, but this below works
Route::getCurrentRoute()->id
assuming your route is
Route::post('something/{id}', ...)
I came here looking for an answer and kind of found it in the comments, so wanted to clarify for others using a resource route trying to use this in a form request
as mentioned by lukas in his comment:
Given a resource controller Route::resource('post', ...) the parameter you can use will be named post
This was usefull to me but not quite complete. It appears that the parameter will be the singular version of the last part of the resource stub.
In my case, the route was defined as $router->resource('inventory/manufacturers', 'API\Inventory\ManufacturersController');
And the parameter available was manufacturer (the singular version of the last part of the stub inventory/manufacturers)
you will get parameter id if you call
request()->route('id')
OR
$this->route('id')
if you're using resource routing, you need to call with the resource name
// eg: resource
Route::resource('users', App\Http\Controllers\UserController::class);
$this->route('user')
in Terminal write
php artisan route:list
to see what is your param name
Then use
$this->route('sphere') to get param