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 方法是在 Requestclass使用,称为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 对象
  • 动态调用它在检索到的对象上静态接收的方法,在这种情况下,allIlluminate\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;