Laravel, Lost data in Custom Request class - php

I store some data in a middleware as following:
public function handle($request, Closure $next)
{
//checking above..
if($this->authed()){
$request->token= $token; //here store the token in user request
return $next($request);
}
return response('Invalid credentials', 401);
}
then in controller I call a custom request class
//function in controller
public function upload(CoverageValueRequest $request){ //calling a custom request
dd($request->token);
dd($request->all());
}
the first dd will give null. However if I changed CoverageValueRequest to Request it will print the token.
P.S: the $request data coming from REST call as JSON format using Content-Type: application/json. I am not sure if this is relevant.
update
I have changed the following in the middleware still same behavior:
$request->merge(['token' => $token]);
can't get the token if CoverageValueRequest but if it is Request then it works.

I have found the answer by setting token as attribute to request, the middleware class:
public function handle($request, Closure $next)
{
//checking above..
if($this->authed()){
$request->attributes->add(['token' => $token]);
return $next($request);
}
return response('Invalid credentials', 401);
}
then retrieve it in the controller as following:
//function in controller
public function upload(CoverageValueRequest $request){ //calling a custom request
dd($request->attributes->get('token'));
dd($request->all());
}
I am not sure why the weird behavior of direct assigning or merge didn't work. Hope someone can clarify.

Related

is it better to create separate request class for each new method in controller, or edit existing request class in laravel or any better idea?

Is it better to create separate request class for each new method in controller or edit existing request class in laravel or any better idea ?
example
class fooBarController {
public function a(fooBarARequest $r) {
}
public function b(fooBarBrequest $r) {
}
public function c(fooBarCDRequest $r) {
}
public function d(fooBarCDRequest $r) {
}
}
Using extra request classes allows you to define validation rules which your request is checked against before it reaches your controller. You can also handle authorization in the request class. An example would be:
class UpdateAccountEmail extends FormRequest
{
public function authorize()
{
return true; // authorization is handled on route/middleware level
}
public function rules()
{
return [
'new_email' => 'required|email|confirmed',
'new_email_confirmation' => 'required',
];
}
}
So, to sum it up: it does not make sense to use a custom request class for requests which do not have payload that needs to be validated. This means, for a normal GET request we most likely (of course there are exceptions) want to use the normal Request class provided by laravel. A controller like this would be quite normal:
class AccountController
{
public function show(Request $request)
{
return view('account.show', ['user' => $request->user()]);
}
public function edit()
{
return view('account.edit', ['user' => \Auth::user()]);
}
public function updateEmail(UpdateAccountEmail $request)
{
$user = $request->user();
$user->email = $request->input('new_email');
$user->save();
return redirect()->route('account.index');
}
public function logins(Request $request)
{
$logins = $request->user()->logins()
->when($request->get('filter_from'), function ($query, $from) {
$query->where('created_at', '>=', $from);
})
->when($request->get('filter_until'), function ($query, $until) {
$query->where('created_at', '<=', $until);
})
->get();
return view('account.logins', ['logins' => $logins]);
}
}
As you can see, for the GET request that is handled by logins(Request $request), we do not use a custom request class because we don't need to validate anything (well, we could validate the filter parameters, but for simplicity we don't).
The example above also shows different methods of retrieving the current user. Even for that you don't need a request at all.
This is no actual production code, just something off the top of my head...

Lumen 5.4 Auth viaRequest $request-input returning null

For whatever reason, my AuthServiceProvider has stopped working. It looks like the $request parameter being passed to the closure for viaRequest is not seeing the request input. If I send JSON with a key of "access_token" to any of my endpoints and try and var_dump it in the closure - it only returns null. Here is the code for the boot method:
public function boot()
{
$this->app['auth']->viaRequest('api', function ($request) {
var_dump($request->input('access_token'));
});
}
And here is my auth middlewares handle method:
public function handle($request, Closure $next, $guard = null)
{
if ($this->auth->guard($guard)->guest()) {
return response('Unauthorized.', 401);
}
return $next($request);
}
Any help is greatly appreciated since I am pulling my hair out right now.
EDIT Looks like the issue is with Sentry and their user_context setting be set to true. As soon as I set it to false, the requests come through perfectly
Issue turned out to be Sentry's user_context setting being set to true. Setting it to false fixed the issue.

Laravel 5: update Controller in Middleware

Is there any way to access (modify) $request "protected proprieties" in the Middleware, to modify requested Controller:
public function handle($request, Closure $next)
{
// change $request parameter
// $request->server->parameters->REQUEST_URI = "something else";
return $next($request);
}
I want to override requested Controller if Cache is valid for the request,
thanks,
You can change the page in the middleware by returning a redirect.
public function handle($request, Closure $next)
{
// change $request parameter
// $request->server->parameters->REQUEST_URI = "something else";
if ($request->something === 'anything')
return redirect()->to("/something-else");
return $next($request);
}
Update:
If you do not wish for the url to update, you could invoke the controller directly using:
app(\App\Http\Controllers\MyController::class)->getMethod();
Where you update the Controller and the method to the ones you need.
However I would not recommend this.

Calling Custom request validation from resource controller

I need help to validate using Custom request class validation but since my controller is a resource controller I can't add the custom request class as parameter. Any ideas how to call custom request validation from resource controller?
This is the route to my Resource Controller
Route::resource('customers', 'CustomerController');
And this is my Customer Request class
class CustomerRequest extends Request
{
//...
public function rules()
{
return [
'customer_type'=>'required|',
'customer_vendor'=>'required|',
'customer_name'=>'required|',
'company_name'=>'required_if:customer_type,Company',
'job_position'=>'required|',
'street'=>'',
'city'=>'required|',
'country'=>'required|',
'website'=>'url',
'phone'=>'required_unless:mobile|',
'mobile'=>'required_unless:phone|',
'email'=>'email',
];
}
}
And this is my Resource controller:
class CustomerController extends Controller
{
// ....
// Add Customer
public function store()
{
//how do i call custom request validation here
return view('create_views/new_customer',['title' => 'New Customer','nav_links'=>CustomerController::$Links]);
}
}
SOLVED
When you create the custom request using php artisan the authorise function is returning false and we need to return true if we are logged in:
public function authorize()
{
return false;//should be return true;
}
You just need to type-hint the request (CustomerRequest) on your controller method (store()).
public function store(CustomerRequest $request)
{
return view('create_views/new_customer',['title' => 'New Customer','nav_links'=>CustomerController::$Links]);
}
SOLVED
When you create the custom request using php artisan the authorise function is returning false and we need to return true if we are logged in:
public function authorize()
{
return false;//should be return true;
}

Laravel 5 form request validation with ID - show

I am wanting to validate a resource controller in Laravel, so that the user can only access clinic.show if they're the owner of said clinic.
I correctly validated this using the following:
public function show($id)
{
if (Clinic::where('id', $id)->where('user_id', Auth::id())->exists()) {
return View::make('clinic.show', ['clinic' => Clinic::where('id', $id)
->first()]);
} else {
abort(401, 'Unauthorized action.');
}
}
However, I believe this is bad practice and I should be using the Form Request feature within Laravel.
I have created a ShowClinicFormRequest.php and added the following code:
public function authorize()
{
$clinicId = $this->route('clinic');
return Clinic::where('id', $clinicId)
->where('user_id', Auth::id())
->exists();
}
And within the show function -
public function show($id, ShowClinicFormRequest $request)
{
return View::make('clinic.show', ['clinic' => Clinic::where('id', $id)->first()]);
}
However, the error that I am getting is:
ReflectionException in RouteDependencyResolverTrait.php line 53: Class
App\Http\Controllers\ShowClinicFormRequest does not exist
It obviously doesn't exist within that directory because it isn't a controller.
Any help would be greatly appreciated.
I believe your form request is located in the App\Http\Requests namespace so you need to import the class or use explicitly:
use App\Http\Requests\ShowClinicFormRequest;
or just
public function show($id, \App\Http\Requests\ShowClinicFormRequest $request)
{}
You might also to take a look at filters or middlewares.

Categories