Laravel Request::all() Should Not Be Called Statically - php

In Laravel, I'm trying to call $input = Request::all(); on a store() method in my controller, but I'm getting the following error:
Non-static method Illuminate\Http\Request::all() should not be called statically, assuming $this from incompatible context
Any help figuring out the best way to correct this? (I'm following a Laracast)

The error message is due to the call not going through the Request facade.
Change
use Illuminate\Http\Request;
To
use Request;
and it should start working.
In the config/app.php file, you can find a list of the class aliases. There, you will see that the base class Request has been aliased to the Illuminate\Support\Facades\Request class. Because of this, to use the Request facade in a namespaced file, you need to specify to use the base class: use Request;.
Edit
Since this question seems to get some traffic, I wanted to update the answer a little bit since Laravel 5 was officially released.
While the above is still technically correct and will work, the use Illuminate\Http\Request; statement is included in the new Controller template to help push developers in the direction of using dependency injection versus relying on the Facade.
When injecting the Request object into the constructor (or methods, as available in Laravel 5), it is the Illuminate\Http\Request object that should be injected, and not the Request facade.
So, instead of changing the Controller template to work with the Request facade, it is better recommended to work with the given Controller template and move towards using dependency injection (via constructor or methods).
Example via method
<?php namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class UserController extends Controller {
/**
* Store a newly created resource in storage.
*
* #param Illuminate\Http\Request $request
* #return Response
*/
public function store(Request $request) {
$name = $request->input('name');
}
}
Example via constructor
<?php namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class UserController extends Controller {
protected $request;
public function __construct(Request $request) {
$this->request = $request;
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store() {
$name = $this->request->input('name');
}
}

use the request() helper instead. You don't have to worry about use statements and thus this sort of problem wont happen again.
$input = request()->all();
simple

Inject the request object into the controller using Laravel's magic injection and then access the function non-statically. Laravel will automatically inject concrete dependencies into autoloaded classes
class MyController()
{
protected $request;
public function __construct(\Illuminate\Http\Request $request)
{
$this->request = $request;
}
public function myFunc()
{
$input = $this->request->all();
}
}

The facade is another Request class, access it with the full path:
$input = \Request::all();
From laravel 5 you can also access it through the request() function:
$input = request()->all();

I thought it would be useful for future visitors to provide a bit of an explanation on what is happening here.
The Illuminate\Http\Request class
Laravel's Illuminate\Http\Request class has a method named all (in fact the all method is defined in a trait that the Request class uses, called Illuminate\Http\Concerns\InteractsWithInput). The signature of the all method at the time of writing looks like this:
public function all($keys = null)
This method is not defined as static and so when you try to call the method in a static context, i.e. Illuminate\Http\Request::all() you will get the error displayed in OP's question. The all method is an instance method and deals with information that is present in an instance of the Request class, so calling it in this way makes no sense.
Facades
A facade in Laravel provides developers with a convenient way of accessing objects in the IoC container, and calling methods on those objects. A developer can call a method "statically" on a facade like Request::all(), but the actual method call on the real Illuminate\Http\Request object is not static.
A facade works like a proxy - it refers to an object in the IoC container and passes the static method call onto that object (non-statically). For instance, take the Illuminate\Support\Facades\Request facade, this is what it looks like:
class Request extends Facade
{
protected static function getFacadeAccessor()
{
return 'request';
}
}
Under the hood, the base Illuminate\Support\Facades\Facade class uses some PHP magic, namely the __callStatic method to:
Listen for a static method call, in this case all with no parameters
Grab the underlying object from the IoC container using the key returned by getFacadeAccessor, in this case a Illuminate\Http\Request object
Dynamically call the method that it received statically on the object it has retrieved, in this case all is called non-statically on an instance of Illuminate\Http\Request.
This is why, as #patricus pointed out in his answer above, by changing the use/import statement to refer to the facade, the error is no longer there, because as far as PHP is concerned, all has been correctly called on an instance of Illuminate\Http\Request.
Aliasing
Aliasing is another feature that Laravel provides for convenience. It works by effectively creating alias classes that point to facades in the root namespace. If you take a look at your config/app.php file, under the aliases key, you will find a long list of mappings of strings to facade classes. For example:
'aliases' => [
'App' => Illuminate\Support\Facades\App::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class,
'Auth' => Illuminate\Support\Facades\Auth::class,
// ...
'Request' => Illuminate\Support\Facades\Request::class,
Laravel creates these alias classes for you, based on your configuration and this allows you to utilise classes available in the root namespace (as referred to by the string keys of the aliases config) as if you're using the facade itself:
use Request:
class YourController extends Controller
{
public function yourMethod()
{
$input = Request::all();
// ...
}
}
A note on dependency injection
While facades and aliasing are still provided in Laravel, it is possible and usually encouraged to go down the dependency injection route. For example, using constructor injection to achieve the same result:
use Illuminate\Http\Request;
class YourController extends Controller
{
protected $request;
public function __construct(Request $request)
{
$this->request = $request;
}
public function yourMethod()
{
$input = $this->request->all();
// ...
}
}
There are a number of benefits to this approach but in my personal opinion the greatest pro for dependency injection is that it makes your code way easier to test. By declaring the dependencies of your classes as constructor or method arguments, it becomes very easy to mock out those dependencies and unit test your class in isolation.

also it happens when you import following library to api.php file.
this happens by some IDE's suggestion to import it for not finding the Route Class.
just remove it and everything going to work fine.
use Illuminate\Routing\Route;
update:
seems if you add this library it wont lead to error
use Illuminate\Support\Facades\Route;

use Illuminate\Http\Request;
public function store(Request $request){
dd($request->all());
}
is same in context saying
use Request;
public function store(){
dd(Request::all());
}

I was facing this problem even with use Illuminate\Http\Request; line at the top of my controller. Kept pulling my hair till I realized that I was doing $request::ip() instead of $request->ip(). Can happen to you if you didn't sleep all night and are looking at the code at 6am with half-opened eyes.
Hope this helps someone down the road.

i make it work with a scope definition
public function pagar(\Illuminate\Http\Request $request)
{
//

Related

How do I inject a request into a facade class in Laravel?

So I have the following class that's a facade:
namespace App\Helpers;
use App\Http\Requests\HomepageRequest;
class Params {
public function __construct(HomepageRequest $request) {
}
Then I have the ParamsServiceProvider class which instantiates the facade class on script startup:
public function register()
{
//
App::bind('params', function() {
return new Params();
});
}
edit: here is the actual facade for the Params class
use Illuminate\Support\Facades\Facade;
class Params extends Facade {
protected static function getFacadeAccessor() {
return 'params';
}
}
This all works fine, the class is instantiated properly, however, it doesn't seem to inject the request object in the constructor like it would in a controller class. Is there a way to inject the request into a facade class like you would in a controller? With the current code, I get the following error:
Too few arguments to function App\Helpers\Params::__construct(), 0
passed in /var/www/v4api/html/app/Providers/ParamsServiceProvider.php
on line 21 and exactly 1 expected
I want to avoid having to manually pass the request input into the class and just have it automatically be injected in the constructor. Any help that you guys can give would be appreciated!
Looks like this worked out:
In the ParamsServiceProvider, instead of using App::bind to instantiate the Params class, do this instead:
public function register()
{
App::alias(Params::class, 'params');
}
then the request object will be injected properly into the facade.
The class you've posted isn't actually a Facade - it's just a regular class.
Because you've type-hinted it's dependencies you don't need to tell Laravel how to create an instance of it - it can work it out all by itself.
You can either inject that class into a controller method (where Laravel will new it up for you), or you can call app(App\Helpers\Params::class) and it will return a new instance of the class for you.
Read more on creating facade classes if you want to create an actual facade. Alternatively you can create a realtime facade - where you instead reference Facades\App\Helpers\Params::foo() and Laravel will let you use the method as if you had an instance of that class.
You have a number options here - point the facade straight to the underlying class and let Laravel work out how to build it, explicitly bind it to the container, or use a realtime facade. Let's go through each.
class Params extends Facade
{
protected static function getFacadeAccessor()
{
return \App\Helpers\Params::class;
}
}
This option points the facade straight to the class you intend it to be a facade for and Laravel will work out the rest.
Alternatively, you can keep it as params and instead fix the binding in the container.
The first example use's Laravel's container to make an instance of the class and return it. Laravel can automatically reflect the class and inject it's dependencies.
App::bind('params', function ($app) {
return $app->make(Params::class);
});
The second example explicitly builds the instance the way you desire, which is just additional code for you to maintain.
App::bind('params', function() {
return new Params(new HomepageRequest);
});
The final option - as mentioned in the earlier answer - is to use a realtime facade and skip the manual binding entirely. You can learn more about realtime facades in the docs.

Laravel DI: call controller method without passing injected variable, is it possible?

class SomeController extends Controller {
public function doALot(Request $request) {
$this -> doOne($someOtherVariable);
// Type error: Argument 1 passed to App\Http\Controllers\SomeController::doOne() must be an instance of Illuminate\Http\Request
$this -> doOne($request, $someOtherVariable);
// Bad practice?
...
}
public function doOne(Request $request, $someOtherVariable) {}
...
}
So how do one call doOne() from doALot() without passing injected resource, yet having Request in doOne()? It feels like bad practice to pass $request all over the place.
Solution tl;dr not possible, but there are other ways – read short answer from Alexey Mezenin
Long version (probably not the best yet suffice).
$ php artisan make:provider SomeServiceProvider
Then in created provider edit register() call to something along the lines:
public
function register() {
$this -> app -> bind('App\Services\SomeService', function ($app) {
return new SomeService();
});
}
Then proceed to create service class which will have injected resource as attribute.
<?php
namespace App\Services;
use \Illuminate\Support\Facades\Request;
class SomeService {
private $request;
/**
* SomeService constructor.
*/
public
function __construct(Request $request) {
$this -> request = $request;
}
public function doOne($someOtherVariable) {}
}
Then move your methods from controller to service and inject service into controller instead.
Tradeoffs: (-) two useless files to perform basic functionality, (+) detaches logic implementation from controller, (~) probably cleaner code.
It's not a good idea to call controller actions manually. The business logic should be in the service class. You can see an example of that in my Laravel best practices repo. If you don't want to pass $request object every time, you can inject Request class in service class' or controller constructor.
Another way to use Request data is to use request() helper:
request('key')
request()->has('key')
Or Request facade:
Request::has('key')
Or you can manually inject it inside the method:
$request = app('Illuminate\Http\Request');

Binding type hinted interface to implementation

Im building Lumen application, and trying to build it with a very SOLID ethos, with small reusable and swappable packages.
So I have an interface for an abstract resource controller like
use Psr\Http\Message\ServerRequestInterface;
interface ResourceControllerContract
{
public function store(ServerRequestInterface $request);
}
In my user resource controller implementation
use GuzzleHttp\Psr7\ServerRequest;
final class UserController extends ResourceController
{
public function store(ServerRequest $request)
{
$request = $request->getParsedBody();
}
}
Since Guzzle Request already implements Psr\Http\Message\RequestInterface, I presumed this could be passed in, but my application kept throwing an exception saying attribute passed to store() should be declared as describe in the ResourceControllerContract
In my service provider in the register method I created a binding like so
$this->app->bind(
'Psr\Http\Message\ServerRequestInterface',
'GuzzleHttp\Psr7\ServerRequest'
);
But it still throws the same error, can someone suggest what's going wrong here? It's my first time building an application in this way so forgive me if I missed a simple oversight
So figured it out the UserController implementation should be like so
use Psr\Http\Message\ServerRequestInterface;
final class UserController extends ResourceController
{
public function store(ServerRequest $request)
{
$request = $request->getParsedBody();
}
}
And then just leave the binding to bind GuzzleHttp\Psr7\ServerRequest to Psr\Http\Message\ServerRequestInterface
Can someone explain why even though GuzzleHttp\Psr7\ServerRequest already implements Psr\Http\Message\ServerRequestInterface it has to be bound in the laravel service provider. Or does simply php not recognise it as an implementation when being type hinted in a function?

Inject other parameters to an action when using controllers in classes pattern?

I have a class called ApplicationDecorator, which inherits Application and adds some often used methods.
At the moment each controller action contains at the beginning a line like
$appDec = new ApplicationDecorator($app);
Is it possible to tell Silex to pass the instance as parameter to the action like it is done for Application and Request?
So it would look like the following:
public function switchAction(ApplicationDecorator $appDec, Request $request) {
I am already using Controllers in classes and want to inject an inherited class of Application.
You can use Request and Silex\Application type hints to get $request
and $app injected.
At the moment only Request and Application are supported.
Is there any possibility to extend the possible values?
You are looking for controllers in classes:
$app->get('/', 'Igorw\\Foo::bar');
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
namespace Igorw
{
class Foo
{
public function bar(Request $request, Application $app)
{
...
}
}
}

How does laravels IoC/Dependency Injector intsantiate to static instances?

So this is probably a rather simple question but I can't seems to find a very direct answer. I supposed to could keep reading the source until i figure it out but I was hoping to get a bit of understand of the process of doing so.
I understand IoC and Dependency injection, I am certainly not very experienced in either but I have a good understand of what they are trying to accomplish. So how does this Laravel instantiate to static instances? I know it uses PHP reflections but I'm still lost on the part of going from non-static to static methods. Also I know Laravel is not the only framework to implement such a design but its my preferred and most understood framework.
When you call a static method on a facade it is being handled by the magic __callStatic method on the Facade class. This method gets the underlying class that serves the facade and proxies the static call to it.
Let's look at an example facade:
<?php
class MyFacade extends Facade {
public function getFacadeAccessor() { return "MyFacade"; }
}
With this example when we make a call to the class in a static manner such as: MyFacade::doSomething() no static method exists on the class. The underlying Facade base class however contains a __callStatic method that will be called.
Facade Class Source Code
public static function __callStatic($method, $args)
{
$instance = static::resolveFacadeInstance(static::getFacadeAccessor());
switch (count($args))
{
case 0:
return $instance->$method();
// Snipped for brevity...
This method then looks up the underlying class to service the facade. If the getFacadeAccessor method on the facade returns a string then a matching entry in the application's IOC container is used (i.e. $app['MyFacade']). If we returned an object from the getFacadeAccessor method it would be used instead (i.e. public function getFacadeAccessor(){ return new MyClass(); }
Turns out that Laravel instantiate the classes under the hood! In this site, the guy makes you understanding a little more of the Laravel's core by using it to create a new facade. In the way, he explains how tit works!
It quite simple, actualy:
1 - You create a classe which extends from Laravel's Facade class with a single call like:
<?php namespace Name\Space;
use Illuminate\Support\Facades\Facade;
class MyClass extends Facade {
/**
* Get the registered name of the component.
*
* #return string
*/
protected static function getFacadeAccessor() { return 'myclass'; }
}
... that's make Laravel look for $app['myclass']. So, the ServiceProvider will bind the myclass to MyClass (according to Laravel's conventions).
2 - For that, of course, you'll have to create a Service Provider.
The Service Provider will be responsible for returning the namespace, in this case Name\Space, for the class(es) that you may want to 'turn into facades'.
3 - You'll have to register your Service Provider in the providers array in the app/config/app.php.
Now, if you look with more attention, you'll realise that what Laravel does is just import a namespace and understanding it as it was a class, as well. Under the hood, it will call a instance, but for user (programmer) it will looks like a static call.
I hope I had been clear about it! Look the link I gave to you up there and HAVE FUN! :D

Categories