Laravel Request::all() 不应静态调用
Laravel Request::all() Should Not Be Called Statically
在 Laravel 中,我试图在控制器中的 store()
方法上调用 $input = Request::all();
,但出现以下错误:
Non-static method Illuminate\Http\Request::all()
should not be called statically, assuming $this
from incompatible context
您能帮忙找出解决此问题的最佳方法吗? (我正在关注 Laracast)
错误消息是由于调用未通过 Request
外观。
改变
use Illuminate\Http\Request;
至
use Request;
它应该开始工作了。
在 config/app.php 文件中,您可以找到 class 别名的列表。在那里,您会看到基 class Request
已别名为 Illuminate\Support\Facades\Request
class。因此,要在命名空间文件中使用 Request
外观,您需要指定使用基础 class:use Request;
.
编辑
因为这个问题好像有点流量,所以在Laravel 5正式发布后,我想稍微更新一下答案。
虽然以上在技术上仍然是正确的并且可以工作,但 use Illuminate\Http\Request;
语句包含在新的 Controller 模板中以帮助推动开发人员使用依赖注入而不是依赖 Facade。
将 Request 对象注入构造函数(或方法,如 Laravel 5 中可用)时,应注入 Illuminate\Http\Request
对象,而不是 Request
外观.
因此,与其更改 Controller 模板以使用 Request facade,不如使用给定的 Controller 模板并转向使用依赖项注入(通过构造函数或方法)。
示例方法
<?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');
}
}
通过构造函数的示例
<?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');
}
}
使用Laravel 的魔法注入将请求对象注入控制器,然后非静态地访问该函数。 Laravel 会自动将具体的依赖注入到自动加载的 类
class MyController()
{
protected $request;
public function __construct(\Illuminate\Http\Request $request)
{
$this->request = $request;
}
public function myFunc()
{
$input = $this->request->all();
}
}
use Illuminate\Http\Request;
public function store(Request $request){
dd($request->all());
}
在上下文中是相同的
use Request;
public function store(){
dd(Request::all());
}
改用 request()
助手。您不必担心 use
语句,因此此类问题不会再次发生。
$input = request()->all();
简单
门面是另一个Requestclass,使用全路径访问:
$input = \Request::all();
从 laravel 5 开始,您还可以通过 request()
函数访问它:
$input = request()->all();
即使我的控制器顶部有 use Illuminate\Http\Request;
行,我也遇到了这个问题。一直拉我的头发,直到我意识到我在做 $request::ip()
而不是 $request->ip()
。如果你整夜没睡并且在早上 6 点半睁着眼睛看代码,可能会发生在你身上。
希望这对以后的人有所帮助。
我认为对这里发生的事情提供一些解释对未来的访问者很有用。
Illuminate\Http\Request
class
Laravel 的 Illuminate\Http\Request
class 有一个名为 all
的方法(实际上 all
方法是在 Request
class使用,称为Illuminate\Http\Concerns\InteractsWithInput
)。在撰写本文时 all
方法的签名如下所示:
public function all($keys = null)
此方法未定义为 static
,因此当您尝试在静态上下文中调用该方法时,即 Illuminate\Http\Request::all()
您将在 OP 的问题中看到错误。 all
方法是一个实例方法,处理存在于 Request
class 实例中的信息,因此以这种方式调用它是没有意义的。
立面
Laravel 中的外观为开发人员提供了一种访问 IoC 容器中的对象并调用这些对象上的方法的便捷方式。开发人员可以在像 Request::all()
这样的外观上调用方法 "statically",但在 real Illuminate\Http\Request
对象上的实际方法调用是 不是静态的。
外观就像代理一样工作 - 它引用 IoC 容器中的对象并将静态方法调用传递到该对象(非静态)。例如,以 Illuminate\Support\Facades\Request
门面为例,它是这样的:
class Request extends Facade
{
protected static function getFacadeAccessor()
{
return 'request';
}
}
在底层,基础 Illuminate\Support\Facades\Facade
class 使用了一些 PHP 魔法,即 __callStatic
方法:
- 侦听静态方法调用,在本例中
all
没有参数
- 使用
getFacadeAccessor
返回的键从 IoC 容器中获取底层对象,在本例中是 Illuminate\Http\Request
对象
- 动态调用它在检索到的对象上静态接收的方法,在这种情况下,
all
在 Illuminate\Http\Request
的实例上非静态调用。
这就是为什么,正如@patricus 在他上面的回答中指出的那样,通过更改 use
/import 语句以引用外观,错误不再存在,因为就 PHP 而言,all
已在 Illuminate\Http\Request
.
的实例上正确调用
别名
别名是 Laravel 为方便起见而提供的另一个功能。它通过有效地创建别名 classes 来工作,这些别名指向根命名空间中的外观。如果你看一下你的 config/app.php
文件,在 aliases
键下,你会发现一长串字符串到外观 classes 的映射。例如:
'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 根据您的配置为您创建这些别名 classes,这允许您利用根命名空间中可用的 classes(由字符串引用aliases
配置的键)就好像你在使用外观本身:
use Request:
class YourController extends Controller
{
public function yourMethod()
{
$input = Request::all();
// ...
}
}
依赖注入注意事项
虽然在 Laravel 中仍然提供外观和别名,但可以并且通常鼓励沿着依赖注入路线走下去。例如,使用构造函数注入实现相同的结果:
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();
// ...
}
}
这种方法有很多好处,但在我个人看来,依赖注入的最大优点是它使您的代码更易于测试。通过将 classes 的依赖项声明为构造函数或方法参数,模拟这些依赖项并单独对 class 进行单元测试变得非常容易。
我让它与范围定义一起工作
public 函数 pagar(\Illuminate\Http\Request $request)
{
//
当您将以下库导入 api.php 文件时也会发生这种情况。
这是由于一些 IDE 的建议,因为没有找到 Route Class.
而导入它
只需删除它,一切都会正常工作。
use Illuminate\Routing\Route;
更新:
似乎如果你添加这个库它不会导致错误
use Illuminate\Support\Facades\Route;
在 Laravel 中,我试图在控制器中的 store()
方法上调用 $input = Request::all();
,但出现以下错误:
Non-static method
Illuminate\Http\Request::all()
should not be called statically, assuming$this
from incompatible context
您能帮忙找出解决此问题的最佳方法吗? (我正在关注 Laracast)
错误消息是由于调用未通过 Request
外观。
改变
use Illuminate\Http\Request;
至
use Request;
它应该开始工作了。
在 config/app.php 文件中,您可以找到 class 别名的列表。在那里,您会看到基 class Request
已别名为 Illuminate\Support\Facades\Request
class。因此,要在命名空间文件中使用 Request
外观,您需要指定使用基础 class:use Request;
.
编辑
因为这个问题好像有点流量,所以在Laravel 5正式发布后,我想稍微更新一下答案。
虽然以上在技术上仍然是正确的并且可以工作,但 use Illuminate\Http\Request;
语句包含在新的 Controller 模板中以帮助推动开发人员使用依赖注入而不是依赖 Facade。
将 Request 对象注入构造函数(或方法,如 Laravel 5 中可用)时,应注入 Illuminate\Http\Request
对象,而不是 Request
外观.
因此,与其更改 Controller 模板以使用 Request facade,不如使用给定的 Controller 模板并转向使用依赖项注入(通过构造函数或方法)。
示例方法
<?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');
}
}
通过构造函数的示例
<?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');
}
}
使用Laravel 的魔法注入将请求对象注入控制器,然后非静态地访问该函数。 Laravel 会自动将具体的依赖注入到自动加载的 类
class MyController()
{
protected $request;
public function __construct(\Illuminate\Http\Request $request)
{
$this->request = $request;
}
public function myFunc()
{
$input = $this->request->all();
}
}
use Illuminate\Http\Request;
public function store(Request $request){
dd($request->all());
}
在上下文中是相同的
use Request;
public function store(){
dd(Request::all());
}
改用 request()
助手。您不必担心 use
语句,因此此类问题不会再次发生。
$input = request()->all();
简单
门面是另一个Requestclass,使用全路径访问:
$input = \Request::all();
从 laravel 5 开始,您还可以通过 request()
函数访问它:
$input = request()->all();
即使我的控制器顶部有 use Illuminate\Http\Request;
行,我也遇到了这个问题。一直拉我的头发,直到我意识到我在做 $request::ip()
而不是 $request->ip()
。如果你整夜没睡并且在早上 6 点半睁着眼睛看代码,可能会发生在你身上。
希望这对以后的人有所帮助。
我认为对这里发生的事情提供一些解释对未来的访问者很有用。
Illuminate\Http\Request
class
Laravel 的 Illuminate\Http\Request
class 有一个名为 all
的方法(实际上 all
方法是在 Request
class使用,称为Illuminate\Http\Concerns\InteractsWithInput
)。在撰写本文时 all
方法的签名如下所示:
public function all($keys = null)
此方法未定义为 static
,因此当您尝试在静态上下文中调用该方法时,即 Illuminate\Http\Request::all()
您将在 OP 的问题中看到错误。 all
方法是一个实例方法,处理存在于 Request
class 实例中的信息,因此以这种方式调用它是没有意义的。
立面
Laravel 中的外观为开发人员提供了一种访问 IoC 容器中的对象并调用这些对象上的方法的便捷方式。开发人员可以在像 Request::all()
这样的外观上调用方法 "statically",但在 real Illuminate\Http\Request
对象上的实际方法调用是 不是静态的。
外观就像代理一样工作 - 它引用 IoC 容器中的对象并将静态方法调用传递到该对象(非静态)。例如,以 Illuminate\Support\Facades\Request
门面为例,它是这样的:
class Request extends Facade
{
protected static function getFacadeAccessor()
{
return 'request';
}
}
在底层,基础 Illuminate\Support\Facades\Facade
class 使用了一些 PHP 魔法,即 __callStatic
方法:
- 侦听静态方法调用,在本例中
all
没有参数 - 使用
getFacadeAccessor
返回的键从 IoC 容器中获取底层对象,在本例中是Illuminate\Http\Request
对象 - 动态调用它在检索到的对象上静态接收的方法,在这种情况下,
all
在Illuminate\Http\Request
的实例上非静态调用。
这就是为什么,正如@patricus 在他上面的回答中指出的那样,通过更改 use
/import 语句以引用外观,错误不再存在,因为就 PHP 而言,all
已在 Illuminate\Http\Request
.
别名
别名是 Laravel 为方便起见而提供的另一个功能。它通过有效地创建别名 classes 来工作,这些别名指向根命名空间中的外观。如果你看一下你的 config/app.php
文件,在 aliases
键下,你会发现一长串字符串到外观 classes 的映射。例如:
'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 根据您的配置为您创建这些别名 classes,这允许您利用根命名空间中可用的 classes(由字符串引用aliases
配置的键)就好像你在使用外观本身:
use Request:
class YourController extends Controller
{
public function yourMethod()
{
$input = Request::all();
// ...
}
}
依赖注入注意事项
虽然在 Laravel 中仍然提供外观和别名,但可以并且通常鼓励沿着依赖注入路线走下去。例如,使用构造函数注入实现相同的结果:
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();
// ...
}
}
这种方法有很多好处,但在我个人看来,依赖注入的最大优点是它使您的代码更易于测试。通过将 classes 的依赖项声明为构造函数或方法参数,模拟这些依赖项并单独对 class 进行单元测试变得非常容易。
我让它与范围定义一起工作
public 函数 pagar(\Illuminate\Http\Request $request) { //
当您将以下库导入 api.php 文件时也会发生这种情况。 这是由于一些 IDE 的建议,因为没有找到 Route Class.
而导入它只需删除它,一切都会正常工作。
use Illuminate\Routing\Route;
更新:
似乎如果你添加这个库它不会导致错误
use Illuminate\Support\Facades\Route;