Laravel Request :: all()不应被静态调用


90

在Laravel中,我试图在控制器中调用$input = Request::all();一个store()方法,但是出现以下错误:

从不兼容的上下文中Illuminate\Http\Request::all()假设$this,非静态方法不应静态调用

是否有帮助找出纠正此问题的最佳方法?(我正在观看Laracast)


@patricus,对不起,我应该说5。–
Moose

看来您没有使用外观。use Illuminate\Http\Request;您的控制人中有陈述吗?
patricus

@patricus,我确实有`use Illuminate \ Http \ Request; 控制器顶部的语句。
驼鹿

1
@patricus我Illuminate\Http\Request在/ vendor中没有软件包。我需要单独下载吗?
驼鹿

这些Illuminate软件包是laravel / framework软件包的一部分。如果您想查看任何Laravel源代码,可以在/vendor/laravel/framework/src/Illuminate/...
patricus

Answers:


222

该错误消息是由于呼叫未通过Request立面而导致的。

更改

use Illuminate\Http\Request;

use Request;

它应该开始工作。

在config / app.php文件中,您可以找到类别名的列表。在那里,您将看到基类Request已被别名为Illuminate\Support\Facades\Request该类。因此,要Request在命名空间文件中使用Facade,需要指定使用基类:use Request;

编辑

由于这个问题似乎吸引了一些人,自Laravel 5正式发布以来,我想对答案进行一些更新。

尽管以上内容在技术上仍然正确并且可以正常使用,但是 use Illuminate\Http\Request;语句包含在新的Controller模板中,以帮助开发人员朝着使用依赖项注入而不是依赖Facade的方向发展。

当将Request对象注入构造函数(或方法,如Laravel 5中可用)时,Illuminate\Http\Request应该注入的是对象,而不是Request立面。

因此,最好不要将Controller模板更改为与Request门面配合使用,而是建议使用给定的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');
    }
}

3
答案是正确的,但是出于偏爱,我会使用Illuminate \ Support \ Facades \ Request; 因为我个人认为Laravel将所有内容都别名为根名称空间的习惯与首先拥有名称空间的观点背道而驰。由于apigen / phpdoc无法找到“ Request”类,这也使API文档更难生成。
delatbabel

4
实际上,您不需要更改工匠make:controller的样板。如果要使用请求而不将其注入到方法中,则只需使用$ input = \ Request :: all()(注意\)。如果要使用注入方法而不是使用公共myFunction(Request $ request(){$ input = $ request-> all()}或将其注入到构造函数中并将其分配给类变量
shock_gone_wild 2015年

2
为什么我在使用Request::all();时不能使用use Illuminate\Http\Request;
SA__ 2015年

@SA__ Request :: all()是一种外观方法。因此,您必须 use Illuminate\Support\Facades\Request; 代替use Illuminate\Http\Request;
Thabung

@redA是否可以将Request :: all()转换为使用直接方式(而不是通过facade类)?
cid

6

使用Laravel的魔术注入将请求对象注入控制器,然后以非静态方式访问该函数。Laravel将自动将具体依赖项注入自动加载的类中

class MyController() 
{

   protected $request;

   public function __construct(\Illuminate\Http\Request $request)
   {
       $this->request = $request;
   }

   public function myFunc()
   {
       $input = $this->request->all();
   }

}

5

改用request()助手。您不必担心use语句,因此不会再次发生这种问题。

$input = request()->all();

简单


4

Facade是另一个Request类,使用完整路径进行访问:

$input = \Request::all();

在laravel 5中,您还可以通过request()函数访问它:

$input = request()->all();

3

我认为这对将来的访问者提供一些有关此处发生情况的解释会很有用。

Illuminate\Http\Request

Laravel的Illuminate\Http\Request类有一个名为的方法all(实际上,该all方法是在Request该类使用的特征中定义的,称为Illuminate\Http\Concerns\InteractsWithInput)。all在编写本文时,方法的签名如下所示:

public function all($keys = null)

未定义此方法static,因此当您尝试在静态上下文中调用该方法时,即Illuminate\Http\Request::all()会在OP的问题中显示错误。该all方法是一个实例方法,它处理Request类实例中存在的信息,因此以这种方式调用它是没有意义的。

外墙

Laravel中的外观为开发人员提供了一种方便的方法,可以访问IoC容器中的对象,并在这些对象上调用方法。开发人员可以调用就像一个立面的方法“静态” Request::all(),但在实际的方法调用真正的 Illuminate\Http\Request对象是不是静态的。

外观就像代理一样工作-它引用IoC容器中的对象,并将静态方法调用传递给该对象(非静态)。例如,以Illuminate\Support\Facades\Request外观为例:

class Request extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'request';
    }
}

在底层,基Illuminate\Support\Facades\Facade类使用了一些PHP魔术,即__callStatic

  • 侦听静态方法调用,在这种情况下all没有参数
  • 使用返回的键从IoC容器中获取基础对象getFacadeAccessor,在本例中为Illuminate\Http\Requestobject
  • 在检索到的对象上动态调用它静态接收的方法,在这种情况下,在all的实例上非静态调用该方法Illuminate\Http\Request

这就是为什么,正如@patricus在上面的回答中指出的那样,通过更改use/ import语句以引用外观,该错误不再存在,因为就PHP而言,all已正确地调用了PHP的实例Illuminate\Http\Request

混叠

别名是Laravel提供的另一个便利功能。它通过有效地创建指向根名称空间中的外立面的别名类来工作。如果您查看config/app.php文件,则在该aliases键下,您会找到一长串字符串到立面类的映射。例如:

'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根据您的配置为您创建这些别名类,这使您可以利用根名称空间中可用的类(由aliases配置的字符串键指代),就像您使用的是Facade本身一样:

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();

        // ...
    }
}

这种方法有很多好处,但我个人认为,依赖注入的最大优点是它使您的代码更易于测试。通过将类的依赖关系声明为构造函数或方法参数,可以很容易地模拟出这些依赖关系并单独对类进行单元测试。


1
use Illuminate\Http\Request;
public function store(Request $request){
   dd($request->all());
}

在上下文中是相同的

use Request;
public function store(){
   dd(Request::all());
}

1

当您将以下库导入api.php文件时,也会发生这种情况。这是由于某些IDE的建议而导致的,即由于找不到路由类而导入它。

只需将其删除,一切都会正常进行。

use Illuminate\Routing\Route;

更新:

如果您添加此库,似乎不会导致错误

use Illuminate\Support\Facades\Route;

这对我有用,但是我仍然不明白为什么IDE原因不适用于我,因为我生成项目的方式和使用vscode的方式。
Aldo Okware

0

即使use Illuminate\Http\Request;在控制器顶部有一行,我也面临着这个问题。一直拉着头发,直到我意识到我在做$request::ip()而不是在做$request->ip()。如果您整夜没有睡着,半睁着眼睛看着代码,可能会发生在您身上。

希望这可以帮助某人。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.