【问题标题】:Laravel Request::all() Should Not Be Called StaticallyLaravel Request::all() 不应该被静态调用
【发布时间】:2015-04-18 21:04:54
【问题描述】:

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

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

任何帮助找出纠正此问题的最佳方法? (我正在关注 Laracast)

【问题讨论】:

  • 看起来你没有使用外观。你的控制器中有use Illuminate\Http\Request; 语句吗?
  • @patricus,我确实有`use Illuminate\Http\Request;我的控制器顶部的声明。
  • @patricus 我在 /vendor 中没有 Illuminate\Http\Request 包。我必须单独下载吗?
  • Illuminate 包包含在 laravel/framework 包中。如果你想查看任何 Laravel 源代码,你可以在 /vendor/laravel/framework/src/Illuminate/... 下找到它
  • 您应该使用构造函数注入或请求对象而不是静态调用。还设置了您的代码向 DI 的即时迁移:tomasvotruba.cz/blog/2019/03/04/…

标签: php laravel laravel-5


【解决方案1】:

错误消息是由于调用没有通过Request门面。

改变

use Illuminate\Http\Request;

use Request;

它应该开始工作了。

在 config/app.php 文件中,您可以找到类别名列表。在那里,您将看到基类 Request 已别名为 Illuminate\Support\Facades\Request 类。因此,要在命名空间文件中使用Request 外观,您需要指定使用基类: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');
    }
}

【讨论】:

  • 答案是正确的,但出于偏好,我会使用 Illuminate\Support\Facades\Request;因为我个人认为 Laravel 将所有内容都别名为根命名空间的习惯是与首先拥有命名空间的观点背道而驰的。它还使 API 文档更难生成,因为 apigen/phpdoc 将无法找到“Request”类。
  • 其实不需要修改工匠 make:controller 的 Boilerplate 。如果您想使用 Request 而不将其注入方法只需使用 $input = \Request::all() (注意 \ )。如果你想使用注入而不是使用 public myFunction(Request $request() { $input = $request->all() } 或者将其注入构造函数并将其分配给类变量
  • 为什么我不能使用Request::all(); 而我使用use Illuminate\Http\Request;
  • @SA__ Request::all() 是一种门面方式。所以你必须use Illuminate\Support\Facades\Request; 而不是use Illuminate\Http\Request;
  • @redA 有没有办法将 Request::all() 转换为使用直接方式(而不是通过外观类)?
【解决方案2】:

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

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

简单

【讨论】:

    【解决方案3】:

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

    class MyController() 
    {
    
       protected $request;
    
       public function __construct(\Illuminate\Http\Request $request)
       {
           $this->request = $request;
       }
    
       public function myFunc()
       {
           $input = $this->request->all();
       }
    
    }
    

    【讨论】:

      【解决方案4】:

      facade 是另一个 Request 类,使用完整路径访问它:

      $input = \Request::all();
      

      从 laravel 5 你也可以通过request() 函数访问它:

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

      【讨论】:

        【解决方案5】:

        我认为对未来的访问者提供一些关于这里发生的事情的解释会很有用。

        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() 这样的外观上“静态地”调用方法,但在 real 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,不带参数
        • 使用 getFacadeAccessor 返回的键从 IoC 容器中获取底层对象,在本例中为 Illuminate\Http\Request 对象
        • 在检索到的对象上动态调用它静态接收的方法,在这种情况下,allIlluminate\Http\Request 的实例上被非静态调用。

        这就是为什么正如@patricus 在上面的回答中指出的那样,通过将use/import 语句更改为引用外观,错误不再存在,因为就PHP而言,all已在 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 配置的字符串键引用),就像您使用外观一样本身:

        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();
        
                // ...
            }
        }
        

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

        【讨论】:

        • 感谢内部分享它的工作原理,这值得更多喜欢!
        【解决方案6】:

        当您将以下库导入 api.php 文件时也会发生这种情况。 这发生在一些 IDE 的建议中,因为找不到 Route 类而导入它。

        只需删除它,一切都会正常工作。

        use Illuminate\Routing\Route;
        

        更新:

        如果你添加这个库似乎不会导致错误

        use Illuminate\Support\Facades\Route;
        

        【讨论】:

        • 这对我有用,但我仍然不明白为什么 IDE 原因不适用于我,因为我生成项目的方式和我使用 vscode。
        【解决方案7】:
        use Illuminate\Http\Request;
        public function store(Request $request){
           dd($request->all());
        }
        

        在上下文中是相同的

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

        【讨论】:

          【解决方案8】:

          即使控制器顶部有use Illuminate\Http\Request; 行,我也遇到了这个问题。一直拉扯我的头发,直到我意识到我在做$request::ip()而不是$request-&gt;ip()。如果您整晚没睡,并且在早上 6 点半睁着眼睛看代码,可能会发生这种情况。

          希望这对未来的人有所帮助。

          【讨论】:

            【解决方案9】:

            我让它与范围定义一起工作

            公共函数pagar(\Illuminate\Http\Request $request) { //

            【讨论】:

            • 请不仅显示哪些代码有效,还要解释您为什么这样做。
            猜你喜欢
            • 2021-03-06
            • 2015-05-28
            • 2021-05-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-11-10
            • 1970-01-01
            • 2015-04-09
            相关资源
            最近更新 更多