Just as a learning exercise, I'm creating a REST API in Laravel 7.1. I'm having trouble figuring out how to parse the query string parameters in route methods. I've read over the documentation here, and it shows how to add parameters into the path:
Route::get('user/{id}', function ($id) {
return 'User '.$id;
});
However I don't see where you can get query parameters from the request URL. In my toy code, I want to add a route to add a new car to inventory:
Route::post('/inventory/add/{make}/{model}/{year}', function ($make, $model, $year) {
return \App\Inventory::create($model, $color, $trim, $accessories);
});
I want to specify parameters such as color, trim, and accessories through the query string, like so:
http://example.com/inventory/add/ford/focus/2020?color=red&trim=sport&accessories=chrome-wheels
How do I get the query parameters out of the Route::post method?
Edit I suppose this architecture may not be the optimal way of adding this extra information, but since I am trying to learn laravel, I am using it as an example. I am interested in learning how to get the query parameters moreso than how to improve the architecture of this learning example.
In Route::post you don't need set the parameters in route. Just use:
Route::post("your-route", "YourControllerController#doSomeThing");
So, in app/Http/Controllers/YourControllerController.php file:
class YourControllerController extends Controller {
public function doSomeThing(Request $request)
{
echo $request->input('param1');
echo $request->input('param2');
echo $request->input('param3');
}
You just need to inject the request instance into your handler (whatever a closure or controller method) and then ask for your parameters.
$color = $request->query('color', 'default-color');
//And so on...
https://laravel.com/docs/7.x/requests#retrieving-input
Related
May I know how can I make just a single route so I don't have to repeat it? Thanks in advance.
Route::get('/url', 'CtcFormController#index' )->name('CtcForm.ch');
Route::post('/url/submit', 'CtcFormController#submit')->name('CtcForm.submit');
Route::view('/url/submitted', 'form.submit')->name('CtcForm.submit');
Route::get('/url2','CtcFormController#store')->name('CtcForm.eng');
Route::post('/url2/submit', 'CtcFormController#submit')->name('CtcForm.submit');
Route::view('/url2/submitted', 'form.submit')->name('CtcForm.submit');
As per your given example, you want to handle the variable part of the route which is /url/ and /url12/. Yes! you can handle there both different route using a single route in ways:
Use route variable to handle dynamic url values i.e. url, url2,url3...url12 and so on.
Route::get('/{url}', 'CtcFormController#index' )->name('CtcForm.ch');
Route::post('/{url}/submit', 'CtcFormController#submit')->name('CtcForm.submit');
Route::view('/{url}/submitted', 'form.submit')->name('CtcForm.submit');
Now in your controller methods handing above routes receive extra parameter $url like:
In controller CtcFormController.php class:
public function index(Request $request, string $url) {
//$url will gives you value from which url request is submitted i.e. url or url12
//method logic goes here ...
}
Similarly, method handling /{url}/submit route will be like:
public function submit(Request $request, string $url) {
//method logic goes here ...
}
Let me know if you have any further query regarding this or you face any issue while implementing it.
I would like to now if there is some method I can use to directily inject a model in a controller in Laravel, without using the Illuminate\Http\Request, something like Springboot in Java.
I have something like:
public function update(Request $request){
$example = new Example();
$example->param1 = $request->input('param1');
$example->param2 = $request->input('param2');
$example->save();
}
I would like to know if I can have something like this:
public function update(Example $example)
And if Laravel have some kind of support to autommaticaly get the Example with the data set, without the need to manipulate de Request.
public function update(Example $example)
With this, you can get data set if the $example is equal to the id of Example model in your database. Laravel will return full dataset only if $example is equal to id, otherwise, you need to make ::where search on model
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.
I am new to Laravel so am uncertain of the notation. The Laravel documentation shows you can pass a parameter this way:
Route::get('user/{id}', function ($id) {
return 'User '.$id;
});
Which is very intuitive. Here is some existing coding in a project I'm undertaking, found in routes.php:
Route::get('geolocate', 'Api\CountriesController#geolocate');
# which of course will call geolocate() in that class
And here is the code I want to pass a variable to:
Route::get('feed/{identifier}', 'Api\FeedController#feed');
The question being, how do I pass $identifier to the class as:
feed($identifier)
Thanks!
Also one further sequitir question from this, how would I notate {identifier} so that it is optional, i.e. simply /feed/ would match this route?
You should first create a link which looks like:
/feed/123
Then, in your controller the method would look like this:
feed($identifier)
{
// Do something with $identifier
}
Laravel is smart enough to map router parameters to controller method arguments, which is nice!
Alternatively, you could use the Request object to return the identifier value like this:
feed()
{
Request::get('identifier');
}
Both methods have their merits, I'd personally use the first example for grabbing one or two router parameters and the second example for when I need to do more complicated things.
My current setup:
Controller:
public function showGeneralPage($id, ShowClinicFormRequest $request)
{
return View::make('clinic.general', ['clinic' => Clinic::where('id', $id)
->first()]);
}
ShowClinicFormRequest:
public function authorize()
{
$clinicId = $this->route('clinic');
return Clinic::where('id', $clinicId)
->where('user_id', Auth::id())
->exists();
}
Route:
Route::get('clinic/{id}/general', 'ClinicController#showGeneralPage
When trying to click through to the page - General, it presents a forbidden error.
To be honest, I'm not overly fussed on even having to show the ID based on the clinic, within the URL, but I can't see any other way around it? Any help would be hugely appreciated. Many thanks.
You may try this (I've found three problems tho):
$id = $this->route()->parameter('id'); // $this->route('id') works as well
Also you need to pass the id when generating the URI, for example:
{{ url("clinic/{$id}/general") }} // $id may have some value, i.e: 10
Also, you need to change the order of parameters here:
public function showGeneralPage($id, ShowClinicFormRequest $request)
Should be:
public function showGeneralPage(ShowClinicFormRequest $request, $id)
Note: When using Method Injection place your method parameters after the type hinted dependency injection parameters.
There are two problems here. First, you have to pass the id along when generating the URL. Assuming a variable $id:
url('clinic/'.$id.'/general')
Second, you are trying to retrieve the parameter clinic, however it is actually called id.
Change it to:
$clinicId = $this->route('id');