"Get" route with query string and custom params - laravel

I am using Laravel 5.5.13.
My goal is to create an endpoint like this:
/api/items/{name}?kind={kind}
Where kind is optional parameter passed in by the query string.
My current routes in api.php looks like this:
Route::get('items', 'DisplaynameController#show');
My current controller is like this:
public function show(Request $request)
{
if ($request->input('kind') {
// TODO
} else {
return Item::where('name', '=', $request->input('name'))->firstOrFail();
}
}
I
I am currently using $request->input('name') but this means I need to provide ?name=blah in the query string. I am trying to make it part of the route.
May you please provide guidance.

The $name variable is a route param, not a query param, this means that you can pass it directly to the function as an argument.
So, if your route is like this:
Route::get('items/{name}', 'DisplaynameController#show');
Your function should be like this:
public function show(Request $request, $name) // <-- note function signature
{ // ^^^^^
if ($request->has('kind'))
{
// TODO
}
else
{
return Item::where('name', '=', $name)->firstOrFail(); // <-- using variable
} // ^^^^^
}
Another option is to get the variable as a Dynamic Property like this:
public function show(Request $request)
{
if ($request->has('kind'))
{
// TODO
}
else
{
return Item::where('name', '=', $request->name)->firstOrFail();
} // ^^^^^^^^^^^^^^
}
Notice that we access the name value as a dynamic property of the $request object like this:
$request->name
For more details, check the Routing > Route parameters and Request > Retrieving input sections of the documentation.

As stated in the documentation you should do:
public function show($name, Request $request)
Laravel will take care of the variable binding

Related

How to pass a parameter to a laravel controller from redirect within the same controller

How do I pass a true false value to the controller from the redirect in the class and to the router and back to another function in the same controller class if that makes sense
Like
public function 1() {
return redirect('route2');
}
public function2() {
I need to access the variable here that some how gets passed from the first function
}
Because these functions are both on my main controller and I need to pass a variable through the route
and back into the controller or is there a way to put a state variable on the class or something I just need to call a function on the controller with conditions from the previous controller function that called called the redirect route.
Also sorry if I am mixing up class and function I am new to laravel and MVC in general.
You can do something like this:
public function first() {
return redirect()->action(
[YourController::class, 'second'], ['value' => true]
);
}
public function second($value = null) {
// whatever you want
}
https://laravel.com/docs/9.x/redirects#redirecting-controller-actions
I think this code help you:
public function 1() {
return to_route('YOUR_ROUTE_NAME', ['value' => 'some things...']);
}
public function2(Request $request, $value) {
// Use the value passed as a route parameter
// $value is 'some things...'
}

Laravel authorization policy not working on Show page

I have a laravel app using Policies to assign roles and permissions, i cant seem to access the show page and im not sure what im doing wrong?
If i set return true it still shows a 403 error as well, so im unsure where im going wrong here. The index page is accessable but the show page is not?
UserPolicy
public function viewAny(User $user)
{
if ($user->isSuperAdmin() || $user->hasPermissionTo(44, 'web')) {
return true;
}
return false;
}
public function view(User $user, User $model)
{
if ($user->isSuperAdmin() || $user->hasPermissionTo(44, 'web')) {
return true;
}
return false;
}
UserController
public function __construct()
{
$this->authorizeResource(User::class, 'user');
}
public function index()
{
$page_title = 'Users';
$page_description = 'User Profiles';
$users = User::all();
return view('pages.users.users.index', compact('page_title', 'page_description', 'users'));
}
public function create()
{
//
}
public function store(Request $request)
{
//
}
public function show($id)
{
$user = User::findOrFail($id);
$user_roles = $user->getRoleNames()->toArray();
return view('pages.users.users.show', compact('user', 'user_roles'));
}
Base on Authorize Resource and Resource Controller documentation.
You should run php artisan make:policy UserPolicy --model=User. This allows the policy to navigate within the model.
When you use the authorizeResource() function you should implement your condition in the middleware like:
// For Index
Route::get('/users', [UserController::class, 'index'])->middleware('can:viewAny,user');
// For View
Route::get('/users/{user}', [UserController::class, 'view'])->middleware('can:view,user');
or you can also use one policy for both view and index on your controller.
I had an issue with authorizeResource function.
I stuck on failed auth policy error:
This action is unauthorized.
The problem was that I named controller resource/request param with different name than its model class name.
F. ex. my model class name is Acknowledge , but I named param as timelineAcknowledge
Laravel writes in its documentation that
The authorizeResource method accepts the model's class name as its first argument, and the name of the route / request parameter that will contain the model's ID as its second argument
So the second argument had to be request parameter name.
// Here request param name is timelineAcknowledge
public function show(Acknowledge $timelineAcknowledge)
{
return $timelineAcknowledge->toArray();
}
// So I used this naming here also
public function __construct()
{
$this->authorizeResource(Acknowledge::class, 'timelineAcknowledge');
}
Solution was to name request param to the same name as its model class name.
Fixed code example
// I changed param name to the same as its model name
public function show(Acknowledge $acknowledge)
{
return $acknowledge->toArray();
}
// Changed here also
public function __construct()
{
$this->authorizeResource(Acknowledge::class, 'acknowledge');
}
I looked over Laravel policy auth code and I saw that the code actually expects the name to be as the model class name, but I couldn't find it anywhere mentioned in Laravel docs.
Of course in most of the cases request param name is the same as model class name, but I had a different case.
Hope it might help for someone.

Pass variable from one method to another in same controller Laravel

I need to pass select option value from store method to show
i need to pass the $typeg value to show method
public function store(Request $request ) {
$typeg = $request->input('type');
}
public function show($id) {
dd($this->store($typeg));
}
i get
Undefined variable:
or
Too few arguments to function app\Http\Controllers\appController::show(), 1 passed and exactly 2 expected
Try this
on the first function you have some variable witch you want to pass it to another function\method
Than you need to use $this and the name of the other method you'd like to pass the var too something like this.
public function oneFunction(){
$variable = "this is pretty basic stuff in any language";
$this->anotherFunction($variable)
}
public function anotherFunction($variable){
dd($variable);
}
Store your data on session (or somewhere else like cookie, cache, database). So you can reach the data later.
class SomeController extends Controller {
public function store(Request $request ) {
session(["typeg"=>$request->input('type')])
}
public function show($id) {
dd(session("typeg"));
}

Laravel - Paramaters should be how when we use match route?

I want to use match method but I can't take $slug and $request in controller..
Here is my route
Route::match(['get','post] , 'category/{slug}' , ['as'=>'category.show' , 'uses'=>'CategoryController#categoryProducts'])
in Controller, our function will be how ? How we use that post and get data in the same function ? I tried like below, but dosen't work
public function categoryProducts($slug, $request) {
//codes
}
Please use Request::method();
public function categoryProducts(Request $request, $slug) {
//codes
}
to get request type GET/POST
$method = Request::method();
or
if (Request::isMethod('post'))
{
//
}
Since you're trying to inject Request object and not passing it, do this instead:
public function categoryProducts(Request $request, $slug)

Access #store arguments in "create policy"

I have a route like this in routes/api.php:
Route::group(['middleware' => 'auth:api'], function() {
Route::post('messages/{pet}', 'MessageController#store')->middleware('can:create,message');
});
We see here that it has implicit {pet}.
My controller accesses {pet} just fine like this:
app\Http\Controllers\MessageController.php:
public function store(Request $request, Pet $pet)
{
dd($pet);
}
I want to my ->middleware('can:create,message') to get the arguments of store seen here, so I want $request and $pet, is this possible?
Here is my current MessagePolicy#create but its not getting the arguments I expect:
app\Policies\MessagePolicy.php
public function create(User $user, Request $request, Pet $pet)
{
dd($request); // dd($pet);
return $user->can('view', $pet) && ($request->input('kind') == null|| $request->input('kind') == 'PLAIN');
}
Also dd is not working for some reason.
Assuming you want create a Pet for a given message, in this case the implicit model binding will not work here because the pet not yet created so finding a pet by the given id will always return null.
In this case laravel offer the possibility to use Actions That Don't Require Models (see documentation -> Via Middleware section)
Again, some actions like create may not require a model instance. In
these situations, you may pass a class name to the middleware. The
class name will be used to determine which policy to use when
authorizing the action
So in your case :
Route::group(['middleware' => 'auth:api'], function() {
Route::post('messages/{pet}', 'MessageController#store')->middleware('can:create,App\Pet');
});
And in the PetPolicy you can use the request() helper method :
public function create(User $user)
{
return request('kind') == null|| request('kind') == 'PLAIN';
}
You could use the request() helper method.
https://laravel.com/docs/5.5/helpers#method-request
The $request have a method has() for determining if a value is present (Link).
You can alter your method to check if the value exists or its equals to "PLAIN"
public function create(User $user, Request $request)
{
return !$request->has('kind') || $request->input('kind') == 'PLAIN';
}
use
return ( $request->has('kind') )? $request->has('kind') && $request->input('kind') === 'PLAIN': true;

Resources