Laravel Request :: all () nie powinno być wywoływane statycznie

90

W Laravel próbuję wywołać metodę w moim kontrolerze, ale $input = Request::all();pojawia store()się następujący błąd:

Metoda niestatyczna Illuminate\Http\Request::all()nie powinna być wywoływana statycznie, przyjmując $thisz niezgodnego kontekstu

Czy jest jakaś pomoc w znalezieniu najlepszego sposobu, aby to naprawić? (Podążam za Laracastem)

Łoś
źródło
@patricus, przepraszam, powinienem był powiedzieć 5.
Moose
Wygląda na to, że nie używasz fasady. Czy masz use Illuminate\Http\Request;oświadczenie w swoim kontrolerze?
patricus
@patricus, mam polecenie ʻuse Illuminate \ Http \ Request; oświadczenie u góry mojego kontrolera.
Łoś
1
@patricus Nie mam Illuminate\Http\Requestpakietu w / vendor. Czy muszę to pobrać osobno?
Łoś
Te Illuminatepakiety zostały włączone jako część pakietu laravel / ramowej. Jeśli chcesz spojrzeć na jakikolwiek kod źródłowy Laravel, znajdziesz go pod/vendor/laravel/framework/src/Illuminate/...
patricus

Odpowiedzi:

222

Komunikat o błędzie wynika z tego, że połączenie nie przechodzi przez Requestfasadę.

Zmiana

use Illuminate\Http\Request;

Do

use Request;

i powinno zacząć działać.

W pliku config / app.php można znaleźć listę aliasów klas. Tam zobaczysz, że klasa bazowa Requestzostała przypisana do Illuminate\Support\Facades\Requestklasy. Ze względu na to, aby korzystać z Requestfasadą w przestrzeni nazw pliku, musisz podać użyć klasy bazowej: use Request;.

Edytować

Ponieważ wydaje się, że to pytanie ma pewien ruch, chciałem trochę zaktualizować odpowiedź, odkąd oficjalnie wydano Laravel 5.

Chociaż powyższe jest nadal poprawne technicznie i będzie działać, use Illuminate\Http\Request;oświadczenie jest zawarte w nowym szablonie kontrolera, aby pomóc programistom popchnąć programistów w kierunku używania wstrzykiwania zależności w porównaniu z poleganiem na elewacji.

Podczas wstrzykiwania obiektu Request do konstruktora (lub metod dostępnych w Laravel 5), to Illuminate\Http\Requestobiekt powinien zostać wstrzyknięty, a nie Requestfasada.

Dlatego zamiast zmieniać szablon kontrolera tak, aby działał z fasadą żądania, lepiej jest pracować z danym szablonem kontrolera i przejść do stosowania wstrzykiwania zależności (za pomocą konstruktora lub metod).

Przykład metodą

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

Przykład za pomocą konstruktora

<?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
źródło
3
Odpowiedź jest prawidłowa, ale poza preferencjami użyłbym Illuminate \ Support \ Facades \ Request; ponieważ osobiście uważam, że nawyk Laravela do aliasowania wszystkiego do głównej przestrzeni nazw jest sprzeczny z celem posiadania przestrzeni nazw w pierwszej kolejności. Utrudnia również generowanie dokumentacji API, ponieważ apigen / phpdoc nie będzie w stanie znaleźć klasy „Request”.
delatbabel
4
W rzeczywistości nie musisz zmieniać Boilerplate producenta rzemieślniczego: kontroler. Jeśli chcesz użyć Request bez wstrzykiwania go do metody, po prostu użyj $ input = \ Request :: all () (zwróć uwagę na \). Jeśli chcesz użyć iniekcji, użyj public myFunction (Request $ request () {$ input = $ request-> all ()} Lub wstrzyknij go w konstruktorze i przypisz do zmiennej klasy
shock_gone_wild
2
Dlaczego nie mogę używać, Request::all();gdy używam use Illuminate\Http\Request; ?
SA__
@SA__ Request :: all () to fasadowy sposób. więc musisz use Illuminate\Support\Facades\Request; zamiastuse Illuminate\Http\Request;
Thabung
@redA Czy istnieje sposób na przekonwertowanie Request :: all () na sposób bezpośredni (a nie przez klasę fasady)?
cid
6

Wstrzyknij obiekt żądania do kontrolera za pomocą magicznego wstrzyknięcia Laravela, a następnie uzyskaj dostęp do funkcji w sposób niestatyczny. Laravel automatycznie wprowadzi konkretne zależności do automatycznie ładowanych klas

class MyController() 
{

   protected $request;

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

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

}
Jonathan Crowe
źródło
5

request()zamiast tego użyj pomocnika. Nie musisz martwić się usestwierdzeniami, a zatem tego rodzaju problem nie powtórzy się.

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

prosty

lucidlogic
źródło
4

Fasada jest kolejną klasą Request, wejdź do niej pełną ścieżką:

$input = \Request::all();

Z poziomu laravel 5 możesz również uzyskać do niego dostęp za pomocą request()funkcji:

$input = request()->all();
Luca C.
źródło
3

Pomyślałem, że przyszłym odwiedzającym przyda się trochę wyjaśnienia tego, co się tutaj dzieje.

Illuminate\Http\Requestklasa

Illuminate\Http\RequestKlasa Laravela ma metodę o nazwie all(w rzeczywistości allmetoda jest zdefiniowana w funkcji, której Requestużywa klasa, zwana Illuminate\Http\Concerns\InteractsWithInput). Podpis allmetody w momencie pisania wygląda następująco:

public function all($keys = null)

Ta metoda nie jest zdefiniowana jako statici tak, gdy spróbujesz wywołać metodę w kontekście statycznym, tj. Illuminate\Http\Request::all()Otrzymasz błąd wyświetlany w pytaniu OP. allMetodą jest metoda instancji i dotyczy informacji, które są obecne w instancji Requestklasy, więc nazywając go w ten sposób nie ma sensu.

Fasady

Fasada w Laravel zapewnia programistom wygodny sposób uzyskiwania dostępu do obiektów w kontenerze IoC i wywoływania metod na tych obiektach. Deweloper może wywołać metodę „statycznie” na elewacji, jak na przykład Request::all(), ale rzeczywiste wywołanie metody w rzeczywistym Illuminate\Http\Request obiekcie nie jest statyczne.

Fasada działa jak proxy - odwołuje się do obiektu w kontenerze IoC i przekazuje wywołanie metody statycznej do tego obiektu (niestatycznie). Weźmy na przykład Illuminate\Support\Facades\Requestfasadę, tak to wygląda:

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

W gruncie rzeczy Illuminate\Support\Facades\Facadeklasa bazowa wykorzystuje trochę magii PHP, a mianowicie __callStaticmetodę:

  • Nasłuchuj wywołania metody statycznej, w tym przypadku allbez parametrów
  • Pobierz podstawowy obiekt z kontenera IoC przy użyciu klucza zwróconego przez getFacadeAccessor, w tym przypadku Illuminate\Http\Requestobiekt
  • Dynamicznie wywołaj metodę, którą otrzymała statycznie na pobranym obiekcie, w tym przypadku allnazywana jest niestatycznie w instancji Illuminate\Http\Request.

Dlatego, jak @patricus wskazał w swojej odpowiedzi powyżej, zmieniając instrukcję use/ import tak, aby odnosiła się do fasady, błędu już nie ma, ponieważ jeśli chodzi o PHP, allzostał poprawnie wywołany na instancji Illuminate\Http\Request.

Aliasing

Aliasing to kolejna funkcja, którą Laravel zapewnia dla wygody. Działa poprzez efektywne tworzenie klas aliasów, które wskazują fasady w głównej przestrzeni nazw. Jeśli spojrzysz na swój config/app.phpplik, pod aliaseskluczem znajdziesz długą listę mapowań ciągów znaków na klasy elewacji. Na przykład:

'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 tworzy dla Ciebie te klasy aliasów, w oparciu o Twoją konfigurację, co pozwala na wykorzystanie klas dostępnych w głównej przestrzeni nazw (do których odnoszą się klucze łańcuchowe aliaseskonfiguracji), tak jakbyś używał samej fasady:

use Request:

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

        // ...
    }
}

Uwaga na temat wstrzykiwania zależności

Chociaż Laravel nadal udostępnia fasady i aliasy, możliwe jest i zwykle zalecane jest skorzystanie z trasy wstrzykiwania zależności. Na przykład użycie iniekcji konstruktora, aby osiągnąć ten sam wynik:

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

        // ...
    }
}

Takie podejście ma wiele zalet, ale moim osobistym zdaniem największym plusem wstrzykiwania zależności jest to, że ułatwia testowanie kodu. Deklarując zależności twoich klas jako argumenty konstruktora lub metody, bardzo łatwo staje się mockowanie tych zależności i testowanie jednostkowe klasy w izolacji.

Jonathon
źródło
1
use Illuminate\Http\Request;
public function store(Request $request){
   dd($request->all());
}

to samo w kontekście powiedzenia

use Request;
public function store(){
   dd(Request::all());
}
Ravi G
źródło
1

zdarza się również, gdy importujesz następującą bibliotekę do pliku api.php. dzieje się tak z powodu sugestii niektórych IDE, aby zaimportować go, aby nie znaleźć klasy trasy .

po prostu go usuń i wszystko będzie dobrze działać.

use Illuminate\Routing\Route;

aktualizacja:

wydaje się, że jeśli dodasz tę bibliotekę, nie doprowadzi to do błędu

use Illuminate\Support\Facades\Route;
ghazyy
źródło
to zadziałało dla mnie, ale nadal nie rozumiem, dlaczego powód IDE nie dotyczy mnie, ponieważ sposób, w jaki wygenerowałem projekt i używam vscode.
Aldo Okware
0

Miałem do czynienia z tym problemem nawet z use Illuminate\Http\Request;linią na górze mojego kontrolera. Ciągnął za włosy, aż zdałem sobie sprawę, że $request::ip()zamiast tego robię $request->ip(). Może się zdarzyć, jeśli nie spałeś całą noc i patrzysz na kod o 6 rano z półotwartymi oczami.

Mam nadzieję, że to pomoże komuś w dalszej drodze.

dotNET
źródło
0

sprawiam, że działa z definicją zakresu

public function pagar (\ Illuminate \ Http \ Request $ request) {//

Julian Lanfranco
źródło
2
Proszę nie tylko pokazać, jaki kod działa, ale także wyjaśnić, dlaczego to zrobiłeś.
creyD