Cannot get requested data from route - laravel

Laravel 8, PHP 7.4.3 Trying to get request ID from the route. In this case I want to get 52 from the routeBeing a basic problem, still creating issue for me. My Route   http://127.0.0.1:8000/user/expense/52/edit My Code
ExpenseController.php
// namespace App\Http\Controllers;
public function edit(Request $request, Expense $expense)
{
//I tried running each dd individually.
dd( $request->get('id') ); //returns null
dd( $request->id ); //returns null
dd( $request['id'] ); // returns null
}
For reference to this controller, check this
Please note that the route is generated by Route::resource function in web.php file. I want to know how to get the ID from the route. I also tried to use Custom Form Request but again that fails as the id is null,IDRequest.php
//namespace App\Http\Requests;
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'id' => 'required'
];
}
This approach also fails me. Please tell me what is it that I am missing. Link for IDRequest
Every help and hint is appreciated.

// namespace App\Http\Controllers;
public function edit(Request $request, Expense $expense)
{
}
$request->get('id') looks for the id param in your form data or params.
Expense $expense will load the resource with primary key id 52 as per route value. You can fetch the id from $expense variable.

Related

How to show custom messages in laravel 5.8?

I am using laravel 5.8 version, i have one api which is responsible for registering ,i create one Request file which contains rules() and messages() function to display error messages but it's not throwing any error messages if any validation fails ,why this is happening can somebody explain ?
UserController.php
<?php
namespace App\Http\Controllers;
use App\Http\Requests\userRequest;
use App\UserSection;
class UserController extends Controller
{
public function userRegister(userRequest $request){
//logic of my code
return response()->json($success);
}
}
userRequest.php
<?php
namespace App\Http\Requests;
use App\Rules\CustomRule;
use Illuminate\Foundation\Http\FormRequest;
class userRequest extends FormRequest
{
public function messages()
{
return [
'first_name.required' => 'A title is required',
];
}
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'first_name' => 'string|required|max:25',
'phone_number' => 'required|integer'
];
}
}
The error i am facing when i hit the route without first_name key it's showing 404 not found error
you might have missed headers part for taking the form-data
Accept = application/json
As laravel docs
If validation fails, a redirect response will be generated to send the
user back to their previous location. The errors will also be flashed
to the session so they are available for display. If the request was
an AJAX request, a HTTP response with a 422 status code will be
returned to the user including a JSON representation of the validation
errors.
So you need to specify the response type you expect, if you use postman for testing your api end point you have to add in request header Accept:application/json
<?php
namespace App\Http\Controllers;
use App\Http\Requests\userRequest;
use App\UserSection;
class UserController extends Controller
{
public function userRegister(userRequest $request){
//logic of my code
return response()->json($success);
}
}

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.

Controller Method not called with custom Form Request Method

For form validation I made a Request class via php artisan make:request UpdatePlanRequest.
However after using the UpdatePlanRequest class in store the method isn't called anymore.
The UpdatePlanRequest:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdatePlanRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{ //TODO: CHECK IF THE PROTOTYPE IDS ARE OWNED BY THE USER (https://stackoverflow.com/questions/42662579/validate-an-array-of-integers/42693970)
return [
'start_date' => 'required|date',
'end_date' => 'required|date|after:start_date',
'name' => 'required|string'
];
}
}
The controller method:
use App\Http\Requests\UpdatePlanRequest;
public function store(UpdatePlanRequest $request)
{
//
dd('hello');
}
If the function header is store(Request $request) hello is shown, in that example it isn't.
The custom Request class is necessary to call $request->validated(); later for validation purposes according to the docs.
Is there a reason you have your Request class as being abstract? The default class that is created when running php artisan make:request <name> doesn't define the class as being abstract. This seems to work for me, but not when declaring it as abstract.
$request->validated(); is used to retrieve the validated inputs, so just by calling the UpdatePlanRequest it should validate the request
//Try This
use App\Http\Requests\UpdatePlanRequest;
public function store(UpdatePlanRequest $request)
{
$validatedData = $request->validated();
dd('$validatedData');
$profile = new Profile([
'user_id' => $request->get('user_id'),
]);
$profile->save();
echo $request->session()->flash('alert-success', 'Profile details Succefully Added!');
return redirect('create')->with('success', 'Data saved!');
}
Your route will be.
Route::get('profile','ProfileController#store');
Route::post('profile/create','ProfileController#store')->name('create');
Well this works right!
When the method is called, it checks the request class (UpdatePlanRequest). If there is an error, it does not enter the method anymore and you can not see the output of dd() function.
If the data is correct after checking the rules, then dd() will be displayed.
You must manage errors

Laravel 5 - sanitize certain inputs on validation

Is it possible to sanitize certain inputs on (or before validation)?
I have this rules for now (as example):
public function rules()
{
return [
'name' => 'required|min:3|max:255|string',
'description' => 'string',
'hours.*' => ['required', new Hours],
];
}
I want to sanitize name and description, but I don't to sanitize hours. Is this possible to do on validation, or I have to sanitize after validation and before insert?
I don't recommend to do sanitization after validation.
Suppose we have a blog system and guests/users can comment on posts, and the minimum characters in a comment is 10
If someone comments with thank you (there's a trailing space), it will be passed at the validation level because it's a 10 chars comment, but when we sanitize the comment, say we trim it, it will be left with 9 chars. This is a silly example but can be something very important in your business logic somewhere.
Sanitize then validate.
To do request inputs sanitization, this article has a good pattern to do it https://medium.com/#melihovv/how-to-sanitize-input-data-in-declarative-manner-in-laravel-e4486068f751
To cannot do this before validation as the original value will still be there in request. It can be easily dealt with mutators.
You can use Eloquent's Mutators to format attribute values in Eloquent Model before insert or update.
To define mutator, add set prefix and attribute suffix with the attribute's name. Like following
// Name mutator
public function setNameAttribute($name)
{
$this->attributes['name'] = strtolower($name); // used strtolower just to show the mutation
}
// Description mutator
public function setDescriptinAttribute($description)
{
$this->attributes['description'] = strtolower($description); // used strtolower just to show the mutation
}
Check documentation for more info https://laravel.com/docs/5.6/eloquent-mutators#defining-a-mutator
The only way I could think of validating the input like that would be validating it on the client side. So basically using Javascript to validate it. If the user for some reason disables Javascript your server site validation would work. What you could try as well would be to post the data asynchronous using Ajax for instance and immidietly return an error message if the validation fails, this approach would be server side.
test this :
web.php
Route::get('test/', 'TestController#test');
TestController class :
<?php
namespace App\Http\Controllers;
use App\Http\Requests\PostRequest;
use App\Post;
class PostController extends Controller
{
public function test(PostRequest $request)
{
dd($request->get('name'));
}
}
PostRequest class :
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PostRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
$this->sanitize();
return [
'name'=>'required',
'description'=>'required',
'description'=>'required',
];
}
public function sanitize()
{
$input = $this->all();
$input['name'] = $input['name'].'some change';
$input['description'] = $input['description'].'another change';
$this->replace($input);
}
}
As you can see, I defined a method called sanitize in PostRequest
Now when I set the value of the name to the ‍‍ali in URL, but the ali some change value will be printed.
You can also use the daylerees / sanitizer package.

How to pass Request object from route in Laravel?

Following is my routes where I am calling my Controller directly in route.
How can I pass Request $request to my getBlog Function.. Or is there any way to directly get $request object in my getblog function of controller ???
$artObj = App::make('App\Http\Controllers\Front\ArticleController');
return $artObj->getBlog($id);
Code in Routes:
Route::get('/{slug}', function($slug) {
// Get Id and Type depending on url
$resultarray = App\Model\UrlAlias::getTypefromUrl($slug);
if(!empty($resultarray)) {
if($resultarray[0]['type'] == 'article') {
$id = $resultarray[0]['ref_id'] ;
$artObj = App::make('App\Http\Controllers\Front\ArticleController');
return $artObj->getBlog($id);
} else {
return Response::view("errors.404", $msg, 400);
}
} else {
return Response::view("errors.404", array(), 400);
}
});
You can do in the head of the routes.php file:
use Illuminate\Http\Request;
And then in the beginning of your route:
Route::get('/{slug}', function($slug, Request $request) {
And the $request will be available to you. But that is extremely bad practice. What you should do - is move the whole logic into the controller like that:
Route::group(['namespace' => 'Front'], function(){
Route::get('/{slug}', 'ArticleController#methodName');
});
and then you can use the Request class in your controller class and the controller method:
<?php
namespace App\Http\Controllers\Front
use Illuminate\Http\Request;
class ArticleController
{ ...
public function methodName(Request $request){
...function implementation...
}
...
}
The Request is a global variable, you can access it anywhere with either php code or even some helper Laravel functions.
Just use request() and it's the same as passing the request as an object inside a variable through a function. (It's equivalent to the Request $request variable received).
It improved readability also. Just remember you can't change request objects directly, you'd better use request()->merge(['key' => 'newValue']);

Resources