Laravel Request :: all () sollte nicht statisch aufgerufen werden

88

In Laravel versuche ich, $input = Request::all();eine store()Methode in meinem Controller aufzurufen , erhalte jedoch den folgenden Fehler:

Nicht statische Methoden Illuminate\Http\Request::all()sollten nicht statisch aufgerufen werden, vorausgesetzt, sie stammen $thisaus einem inkompatiblen Kontext

Hilfe bei der Suche nach dem besten Weg, dies zu korrigieren? (Ich folge einem Laracast)

Elch
quelle
@patricus, sorry, ich hätte sagen sollen 5.
Elch
Es sieht so aus, als würden Sie die Fassade nicht benutzen. Haben Sie eine use Illuminate\Http\Request;Anweisung in Ihrem Controller?
Patrickus
@patricus, ich habe die `use Illuminate \ Http \ Request; Anweisung oben auf meinem Controller.
Elch
1
@patricus Ich habe das Illuminate\Http\RequestPaket jedoch nicht in / vendor. Muss ich das separat herunterladen?
Elch
Die IlluminatePakete sind Teil des Laravel / Framework-Pakets. Wenn Sie sich einen der Laravel-Quellcodes ansehen möchten, finden Sie ihn unter/vendor/laravel/framework/src/Illuminate/...
patricus

Antworten:

218

Die Fehlermeldung ist darauf zurückzuführen, dass der Anruf nicht durch die RequestFassade geht.

Veränderung

use Illuminate\Http\Request;

Zu

use Request;

und es sollte anfangen zu arbeiten.

In der Datei config / app.php finden Sie eine Liste der Klassenaliasnamen. Dort sehen Sie, dass die Basisklasse Requestauf die Illuminate\Support\Facades\RequestKlasse ausgerichtet ist. Um die RequestFassade in einer Datei mit Namespace zu verwenden, müssen Sie daher angeben, dass die Basisklasse verwendet werden soll : use Request;.

Bearbeiten

Da diese Frage etwas Verkehr zu bekommen scheint, wollte ich die Antwort ein wenig aktualisieren, da Laravel 5 offiziell veröffentlicht wurde.

Obwohl das oben Gesagte technisch immer noch korrekt ist und funktioniert, ist die use Illuminate\Http\Request;Anweisung in der neuen Controller-Vorlage enthalten, um Entwickler dabei zu unterstützen, die Abhängigkeitsinjektion zu verwenden, anstatt sich auf die Fassade zu verlassen.

Beim Injizieren des Request-Objekts in den Konstruktor (oder in die in Laravel 5 verfügbaren Methoden) sollte das Illuminate\Http\RequestObjekt injiziert werden und nicht die RequestFassade.

Anstatt die Controller-Vorlage so zu ändern, dass sie mit der Request-Fassade funktioniert, ist es besser, mit der angegebenen Controller-Vorlage zu arbeiten und die Abhängigkeitsinjektion (über Konstruktor oder Methoden) zu verwenden.

Beispiel über Methode

<?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');
    }
}

Beispiel über Konstruktor

<?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');
    }
}
patricus
quelle
3
Die Antwort ist richtig, aber aus Präferenz würde ich Illuminate \ Support \ Facades \ Request verwenden. weil ich persönlich denke, dass Laravels Gewohnheit, alles auf den Root-Namespace zu aliasen, gegen den Punkt ist, überhaupt Namespaces zu haben. Außerdem ist die Generierung der API-Dokumentation schwieriger, da apigen / phpdoc die Klasse "Request" nicht finden kann.
Delatbabel
4
Tatsächlich müssen Sie die Boilerplate des Handwerkers make: controller nicht ändern. Wenn Sie die Anforderung verwenden möchten, ohne sie in die Methode einzufügen, verwenden Sie einfach $ input = \ Request :: all () (Beachten Sie das \). Wenn Sie Injection verwenden möchten, verwenden Sie public myFunction (Request $ request () {$ input = $ request-> all ()}. Oder injizieren Sie es in den Konstruktor und weisen Sie es einer Klassenvariablen zu
schock_gone_wild
2
Warum kann ich nicht verwenden, Request::all();während ich benutze use Illuminate\Http\Request; ?
SA__
@SA__ Request :: all () ist ein Fassadenweg. use Illuminate\Support\Facades\Request;use Illuminate\Http\Request;
Also
@redA Gibt es eine Möglichkeit, Request :: all () so zu konvertieren, dass es den direkten Weg verwendet (und nicht über die Fassadenklasse)?
Cid
6

Injizieren Sie das Anforderungsobjekt mit Laravels magischer Injektion in den Controller und greifen Sie dann nicht statisch auf die Funktion zu. Laravel fügt automatisch geladene Abhängigkeiten in automatisch geladene Klassen ein

class MyController() 
{

   protected $request;

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

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

}
Jonathan Crowe
quelle
5

Verwenden Sie request()stattdessen den Helfer. Sie müssen sich keine Gedanken über useAussagen machen und daher wird diese Art von Problem nicht wieder auftreten.

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

einfach

lucidlogic
quelle
4

Die Fassade ist eine weitere Request-Klasse. Greifen Sie mit dem vollständigen Pfad darauf zu:

$input = \Request::all();

Von Laravel 5 aus können Sie auch über die request()Funktion darauf zugreifen :

$input = request()->all();
Luca C.
quelle
3

Ich dachte, es wäre nützlich für zukünftige Besucher, eine Erklärung zu geben, was hier passiert.

Die Illuminate\Http\RequestKlasse

Laravels Illuminate\Http\RequestKlasse hat eine Methode namens all(tatsächlich wird die allMethode in einem Merkmal definiert, das die RequestKlasse verwendet, genannt Illuminate\Http\Concerns\InteractsWithInput). Die Signatur der allMethode zum Zeitpunkt des Schreibens sieht folgendermaßen aus:

public function all($keys = null)

Diese Methode ist nicht definiert als staticund wenn Sie versuchen, die Methode in einem statischen Kontext aufzurufen, Illuminate\Http\Request::all()wird der Fehler in der Frage von OP angezeigt. Die allMethode ist eine Instanzmethode und behandelt Informationen, die in einer Instanz der RequestKlasse vorhanden sind. Daher macht es keinen Sinn, sie auf diese Weise aufzurufen.

Fassaden

Eine Fassade in Laravel bietet Entwicklern eine bequeme Möglichkeit, auf Objekte im IoC-Container zuzugreifen und Methoden für diese Objekte aufzurufen. Ein Entwickler kann eine Methode "statisch" an einer Fassade wie Request::all()aufrufen, aber der tatsächliche Methodenaufruf für das reale Illuminate\Http\Request Objekt ist nicht statisch.

Eine Fassade funktioniert wie ein Proxy - sie verweist auf ein Objekt im IoC-Container und übergibt den statischen Methodenaufruf an dieses Objekt (nicht statisch). Nehmen Illuminate\Support\Facades\Requestwir zum Beispiel die Fassade, so sieht sie aus:

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

Unter der Haube verwendet die Basisklasse Illuminate\Support\Facades\Facadeetwas PHP-Magie, nämlich die __callStaticMethode, um:

  • Warten Sie auf einen statischen Methodenaufruf, in diesem Fall allohne Parameter
  • Nehmen Sie das zugrunde liegende Objekt mit dem von getFacadeAccessor, in diesem Fall einem Illuminate\Http\RequestObjekt, zurückgegebenen Schlüssel aus dem IoC-Container
  • Rufen Sie die Methode, die sie statisch für das abgerufene Objekt empfangen hat, dynamisch auf. In diesem Fall allwird sie für eine Instanz von statisch nicht statisch aufgerufen Illuminate\Http\Request.

Aus diesem Grund ist, wie @patricus in seiner obigen Antwort ausgeführt hat use, der Fehler nicht mehr vorhanden, wenn die Anweisung / import geändert wird , um auf die Fassade zu verweisen, da PHP in Bezug allauf eine Instanz von korrekt aufgerufen wurde Illuminate\Http\Request.

Aliasing

Aliasing ist eine weitere Funktion, die Laravel für mehr Komfort bietet. Dabei werden effektiv Aliasklassen erstellt, die auf Fassaden im Stammnamensraum verweisen. Wenn Sie sich Ihre config/app.phpDatei ansehen , finden Sie unter dem aliasesSchlüssel eine lange Liste von Zuordnungen von Zeichenfolgen zu Fassadenklassen. Beispielsweise:

'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 erstellt diese Aliasklassen basierend auf Ihrer Konfiguration für Sie. Auf diese Weise können Sie Klassen verwenden, die im Root-Namespace verfügbar sind (wie in den Zeichenfolgenschlüsseln der aliasesKonfiguration angegeben), als ob Sie die Fassade selbst verwenden:

use Request:

class YourController extends Controller
{
    public function yourMethod()
    {
        $input = Request::all();

        // ...
    }
}

Ein Hinweis zur Abhängigkeitsinjektion

Während in Laravel noch Fassaden und Aliasing bereitgestellt werden, ist es möglich und wird normalerweise empfohlen, den Weg der Abhängigkeitsinjektion einzuschlagen. Verwenden Sie beispielsweise die Konstruktorinjektion, um das gleiche Ergebnis zu erzielen:

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

        // ...
    }
}

Dieser Ansatz bietet eine Reihe von Vorteilen, aber meiner persönlichen Meinung nach besteht der größte Vorteil für die Abhängigkeitsinjektion darin, dass Ihr Code einfacher zu testen ist. Indem Sie die Abhängigkeiten Ihrer Klassen als Konstruktor- oder Methodenargumente deklarieren, wird es sehr einfach, diese Abhängigkeiten zu verspotten und Ihre Klasse isoliert zu testen.

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

ist das gleiche im Zusammenhang zu sagen

use Request;
public function store(){
   dd(Request::all());
}
Ravi G.
quelle
1

Es passiert auch, wenn Sie die folgende Bibliothek in die Datei api.php importieren. Dies geschieht durch den Vorschlag einer IDE, sie zu importieren, um die Routenklasse nicht zu finden .

Entfernen Sie es einfach und alles wird gut funktionieren.

use Illuminate\Routing\Route;

aktualisieren:

Wenn Sie diese Bibliothek hinzufügen, führt dies anscheinend nicht zu Fehlern

use Illuminate\Support\Facades\Route;
ghazyy
quelle
Das hat bei mir funktioniert, aber ich verstehe immer noch nicht, warum der IDE-Grund für mich nicht zutreffen würde, weil ich das Projekt generiert und vscode verwendet habe.
Aldo Okware
0

Ich hatte dieses Problem sogar mit der use Illuminate\Http\Request;Leitung oben auf meinem Controller. Ich zog weiter an meinen Haaren, bis mir klar wurde, dass ich es $request::ip()stattdessen tat $request->ip(). Kann Ihnen passieren, wenn Sie die ganze Nacht nicht geschlafen haben und den Code um 6 Uhr morgens mit halb geöffneten Augen betrachten.

Hoffe, das hilft jemandem auf der Straße.

Punkt net
quelle
0

Ich lasse es mit einer Scope-Definition funktionieren

öffentliche Funktion pagar (\ Illuminate \ Http \ Request $ request) {//

Julian Lanfranco
quelle
2
Bitte zeigen Sie nicht nur, welcher Code funktioniert, sondern erklären Sie auch, warum Sie dies getan haben.
creyD