Pass to the method as parameters - php

I have a method with a lot of code
public function createNewObject(Request $request)
{
// Code...
}
There is another method that I plan to call, but how to pass it to the createNewObject method as a Request argument?
public function deleteAndCreateObject()
{
$this->createNewObject(???);
}

Just type-hint it in your deleteAndCreateObject() method.
class YourController
{
public function createNewObject(Request $request)
{
// Code...
}
public function deleteAndCreateObject(Request $request)
{
$this->createNewObject($request);
}
}
If that—for some reason—doesn't work for you, you can always use request():
class YourController
{
public function createNewObject()
{
$request = request();
// Code...
}
public function deleteAndCreateObject()
{
$this->createNewObject();
}
}

Related

Why is the data lost in the parent constructor?

I have a class like this:
class BaseApiController extends Controller
{
protected $user;
function __construct()
{
$this->configHeaderRequest();
$this->validateToken();
}
protected function validateToken()
{
$this->middleware(function ($request, $next) {
if (Auth::guard('web')->user()) {
$this->user = Auth::guard('web')->user();
}
var_dump($this->user); //=> This is "user object" as well
return $next($request);
});
}
}
And another class that is extended from the class above:
class NewsController extends BaseApiController
{
public function __construct(Request $request)
{
parent::__construct($request);
$this->middleware(function ($request, $next) {
if (empty($this->user)) {
return $this->sendFailedResponse('Unauthorized Request', 401);
}
return $next($request);
});
}
public function search(Request $request): JsonResponse
{
var_dump($this->user); //=> but there is "null"
}
}
As you can see, $this->user will be null when I needed the user's object inside the search(Request $request) method while surprisingly the user's object exists inside the validateToken() method. Why? And how can I access the user's object there?

How to create a new request

I have a method that accepts a request
public function createUser(Request $request)
{
...
}
I want to call it from another method
public function someMethod(){
$array = [...];
return $this->createUser($array); <----
}
and how can I pass a new request to it with the array I need?
How about instead of trying to call a controller method, you move the logic to create a user to a service class and then use the service class in your createUser and someMethod methods?
UserService.php
class UserService
{
public function __construct() { }
public function createUser(array $userData)
{
// TODO use $userData to create a user here
return $newUser;
}
}
SomeController.php
public function createUser(Request $request)
{
$this->userService->createUser($request->all());
}
public function someMethod(){
$array = [...];
return $this->userService->createUser($array);
}

Laravel 5.8 send parameters to authorize method FormRequest Class

I have update and store method like this
public function update(ContactRequest $request)
{
if (Auth::user()->can('edit_contact'))
$request->update();
else
return $this->accessDenied();
}
public function store(ContactRequest $request)
{
if (Auth::user()->can('add_contact'))
$request->store();
else
return $this->accessDenied();
}
and authorize in FormRequest class
public function authorize()
{
return \Gate::allows('test', $this->route('contact'));
}
I want to pass permission name to authorize method like this:
public function authorize($permissionName)
{
if (Auth::user()->can($permissionName))
return \Gate::allows('test', $this->route('contact'));
}
and in controller like this
public function update(ContactRequest $request)
{
$request->update('edit_contact');
}
public function store(ContactRequest $request)
{
$request->store('add_contact');
}
You have 3 options:
Change your authorization method to this:
public function authorize()
{
return $this->user()->can(
$this->route()->getActionMethod() === 'store'
? 'add_contact'
: 'edit_contact'
)
&& \Gate::allows('test', $this->route('contact'));
}
Make your authorize method of request return true and check authorization by defining another gate an call it on your controller:
public function authorize()
{
return true;
}
Gate::define('modify_contact', function ($user, $permissionName) {
return $user->can($permissionName)
&& $user->can('test', $request->route('contact'));
});
public function update(ContactRequest $request)
{
Gate::authorize('modify_contact', 'edit_contact');
//...
}
public function store(ContactRequest $request)
{
Gate::authorize('modify_contact', 'add_contact');
//...
}
Define and use policy the same way and pass your arguments to it.
There is no direct way of passing argument to authorize method of form request, but you can do the implementation this way:
public function authorize()
{
$method = Request::method();
if($method == 'post') {
$permission = 'add_contact';
} elseif($method == 'put') {
$permission = 'edit_contact';
}
if (Auth::user()->can($permission))
return \Gate::allows('test', $this->route('contact'));
}
If you are using laravel's default post, put routes then this will help you out.
It is better to make two different Requests for store and update, anyway you need to check some values depended on action.
So you can user default laravel's policy approach for Resource controllers and not use Request::authorize for authorization logic.
Laravel policy controller helpers

how do we set menu list globally

Initially I have to attach with each action :-
Here we first fetch menu detail then pass in to view section.
Class ManageadministratorController extends Controller {
public $data_menu;
public function __construct() {
$this->middleware('auth');
$obj = new General;
$this->data_menu=$obj->displaymenu();
}
public function index()
{
$obj = new General;
$permission = $obj->checkViewPermission("manageadministrator");
$query= Adminlogin::get();
return View::Make('admin.manageadministrator.manage',array('record'=>$query,'menu_list'=>$this->data_menu));
}
function add()
{
return View::Make('admin.manageadministrator.add',array('menu_list'=>$this->data_menu));
}
}
You can register a custom service provider or use AppServiceProvider:
public function boot()
{
$obj = new General;
$data_menu = $obj->displaymenu();
view()->composer('admin.manageadministrator', function($view) {
$view->with('menu_list', $data_menu);
});
}
Or use a dedicated class:
// app/Providers/AppServiceProvider.php
public function boot()
{
view()->composer('admin.manageadministrator', 'App\Http\Composers\MasterComposer');
}
// app/Http/Composers/MasterComposer.php
use Illuminate\Contracts\View\View;
class MasterComposer {
public function compose(View $view)
{
$obj = new General;
$data_menu = $obj->displaymenu();
$view->with('menu_list', $data_menu);
}
}

In laravel view() function within a controller, can this detect an AJAX request

In my controller, I have something like the following:
public function index()
{
$questions = Question::all();
return view('questions.index', compact('questions'));
}
However, I would like this route to also be used by my ajax requests. In which case, I'd like to return JSON. I'm considering the following:
public function index()
{
$questions = Question::all();
return $this->render('questions.index', compact('questions'));
}
public function render($params)
{
if ($this->isAjax()) {
return Response::json($params);
} else {
return view('questions.index')->with($params);
}
}
..by the way, I haven't tested any of this yet, but hopefully you get the idea.
However, I was wondering if I can alter the built in view(...) functionality itself to keep things even lighter. So I just keep the following:
public function index()
{
$questions = Question::all();
// this function will detect the request and deal with it
// e.g. if header X-Requested-With=XMLHttpRequest/ isAjax()
return view('questions.index', compact('questions'));
}
Is this possible?
You probably want to make custom response:
add ResponseServiceProvider.php
namespace App\Providers;
use Request;
use Response;
use View;
use Illuminate\Support\ServiceProvider;
class ResponseServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*
* #return void
*/
public function boot()
{
Response::macro('smart', function($view, $data) {
if (Request::ajax()) {
return Response::json($data);
} else {
return View::make($view, $data);
}
});
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
}
Add 'App\Providers\ResponseServiceProvider' to providers list in config/app.php:
'providers' => [
'App\Providers\ResponseMacroServiceProvider',
];
Use new helper in controller:
return Response::smart('questions.index', $data);
Simply check if the Request is an Ajax request in your index method itself.
public method index() {
$questions = Question::all();
if(\Request::ajax())
return \Response::json($questions);
else
return view('questions.index', compact('questions'));
}
Use Request::ajax(), or inject the request object:
use Illuminate\Http\Request;
class Controller {
public function index(Request $request)
{
$data = ['questions' => Question::all()];
if ($request->ajax()) {
return response()->json($data);
} else {
return view('questions.index')->with($data);
}
}
}
Your view should never know anything about the HTTP request/response.
I guess the simple method is just to put a method inside the parent Controller class:
use Illuminate\Routing\Controller as BaseController;
abstract class Controller extends BaseController {
...
protected function render($view, $data)
{
if (Request::ajax()) {
return Response::json($data);
} else {
return view($view, $data);
}
}
}
and then instead of doing view('questions.index, $data);, do $this->render('questions.index', $data);

Categories